-| Wave | Bar |
-| ------------- |:-------------:|
-|  ||
+#### 安装教程
-## Available Visualizers:
-* **BlobVisualizer** - Gives blob like effect, good for low bpm audio
-* **BlastVisualizer** - Gives a blast like effect, very random, good for high bpm audio
-* **WaveVisualizer** - Gives a nice wave like effect, good for all kinds of audio
-* **BarVisualizer** - Gives the contemporary bar effect, good for all kinds of audio
-* **CircleLineVisualizer** - Gives the circular bar like effect, good for all kinds of audio
-* **HifiVisualizer** - Gives a unique circular wave like effect, good for all kinds of audio
+1.在项目根目录下的build.gradle文件中
-## Usage
-
-**Note:** Use of the visualizer requires the permission `android.permission.RECORD_AUDIO` so add it to your manifest file. Also for Android 6.0 and above you will need request permission in runtime.
+```java
+allprojects {
+ repositories {
+ maven {
+ url 'https://s01.oss.sonatype.org/content/repositories/snapshots/'
+ }
+ }
+}
+```
-Check out the Sample app, to see how its implemented.
+2.在entry模块下的build.gradle文件中
-* This library is available on JCenter. To use it, add the following to `build.gradle`
-```gradle
+```java
dependencies {
- implementation 'com.gauravk.audiovisualizer:audiovisualizer:0.9.2'
-}
+ implementation('com.gitee.chinasoft_ohos:audio-visualizer-ohos:0.0.1-SNAPSHOT')
+ ......
+ }
```
-* Add the `com.gauravk.audiovisualizer.visualizer.BlastVisualizer` to your XML Layout file:
+
+
+
+#### 使用说明
+
+在布局中引入对应的自定义控件用于绘制频率,例如:
+
```xml
* Created by gk */ - -public class BarVisualizer extends BaseVisualizer { - +public class BarVisualizer extends BaseVisualizer implements Component.DrawTask { private static final int BAR_MAX_POINTS = 120; private static final int BAR_MIN_POINTS = 3; @@ -43,48 +42,63 @@ public class BarVisualizer extends BaseVisualizer { private int nPoints; - private float[] mSrcY, mDestY; + private float[] mSrcY; + private float[] mDestY; private float mBarWidth; private Rect mClipBounds; private int nBatchCount; - private Random mRandom; + private Random mRandom = new Random(); + /** + * 使用java代码实例化调用 + * + * @param context + */ public BarVisualizer(Context context) { super(context); } - public BarVisualizer(Context context, - @Nullable AttributeSet attrs) { - super(context, attrs); + /** + * 使用xml布局引用调用 + * + * @param context + * @param attrSet + */ + public BarVisualizer(Context context, AttrSet attrSet) { + super(context, attrSet); } - public BarVisualizer(Context context, - @Nullable AttributeSet attrs, - int defStyleAttr) { - super(context, attrs, defStyleAttr); + /** + * 使用xml并设置style调用 + * + * @param context + * @param attrSet + * @param styleName + */ + public BarVisualizer(Context context, AttrSet attrSet, String styleName) { + super(context, attrSet, styleName); } @Override protected void init() { + addDrawTask(this::onDraw); nPoints = (int) (BAR_MAX_POINTS * mDensity); - if (nPoints < BAR_MIN_POINTS) + if (nPoints < BAR_MIN_POINTS) { nPoints = BAR_MIN_POINTS; + } mBarWidth = -1; nBatchCount = 0; setAnimationSpeed(mAnimSpeed); - mRandom = new Random(); - mClipBounds = new Rect(); mSrcY = new float[nPoints]; mDestY = new float[nPoints]; - } @Override @@ -94,52 +108,51 @@ public class BarVisualizer extends BaseVisualizer { } @Override - protected void onDraw(Canvas canvas) { - + public void onDraw(Component component, Canvas canvas) { if (mBarWidth == -1) { + canvas.getLocalClipBounds(mClipBounds); + mBarWidth = component.getWidth() / nPoints; - canvas.getClipBounds(mClipBounds); - - mBarWidth = canvas.getWidth() / nPoints; - - //initialize points + // initialize points for (int i = 0; i < mSrcY.length; i++) { float posY; - if (mPositionGravity == PositionGravity.TOP) + if (mPositionGravity == PositionGravity.TOP) { posY = mClipBounds.top; - else + } else { posY = mClipBounds.bottom; + } mSrcY[i] = posY; mDestY[i] = posY; } } - //create the path and draw + // create the path and draw if (isVisualizationEnabled && mRawAudioBytes != null) { - if (mRawAudioBytes.length == 0) { return; } - //find the destination bezier point for a batch + // find the destination bezier point for a batch if (nBatchCount == 0) { float randPosY = mDestY[mRandom.nextInt(nPoints)]; for (int i = 0; i < mSrcY.length; i++) { int x = (int) Math.ceil((i + 1) * (mRawAudioBytes.length / nPoints)); int t = 0; - if (x < 1024) - t = canvas.getHeight() + - ((byte) (Math.abs(mRawAudioBytes[x]) + 128)) * canvas.getHeight() / 128; + if (x < 1024) { + t = component.getHeight() + + ((byte) (Math.abs(mRawAudioBytes[x]) + 128)) * component.getHeight() / 128; + } float posY; - if (mPositionGravity == PositionGravity.TOP) + if (mPositionGravity == PositionGravity.TOP) { posY = mClipBounds.bottom - t; - else + } else { posY = mClipBounds.top + t; + } - //change the source and destination y + // change the source and destination y mSrcY[i] = mDestY[i]; mDestY[i] = posY; } @@ -147,22 +160,22 @@ public class BarVisualizer extends BaseVisualizer { mDestY[mSrcY.length - 1] = randPosY; } - //increment batch count + // increment batch count nBatchCount++; - //calculate bar position and draw + // calculate bar position and draw for (int i = 0; i < mSrcY.length; i++) { float barY = mSrcY[i] + (((float) (nBatchCount) / mMaxBatchCount) * (mDestY[i] - mSrcY[i])); float barX = (i * mBarWidth) + (mBarWidth / 2); - canvas.drawLine(barX, canvas.getHeight(), barX, barY, mPaint); + canvas.drawLine(barX, component.getHeight(), barX, barY, mPaint); } - //reset the batch count - if (nBatchCount == mMaxBatchCount) + // reset the batch count + if (nBatchCount == mMaxBatchCount) { nBatchCount = 0; - + } } - super.onDraw(canvas); + super.addDrawTask(this::onDraw); } } \ No newline at end of file diff --git a/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/BlastVisualizer.java b/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/BlastVisualizer.java index dc30207a9c0b2aa7f1ba5ac7564b9ecca65bf40a..cb30ad6f3b45bab1f6d3934864f3b3d0ca3325f8 100644 --- a/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/BlastVisualizer.java +++ b/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/BlastVisualizer.java @@ -13,24 +13,25 @@ See the License for the specific language governing permissions and limitations under the License. */ -package com.gauravk.audiovisualizer.visualizer; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Path; -import android.support.annotation.Nullable; -import android.util.AttributeSet; +package com.gauravk.audiovisualizer.visualizer; import com.gauravk.audiovisualizer.base.BaseVisualizer; +import ohos.agp.components.AttrSet; +import ohos.agp.components.Component; +import ohos.agp.render.Canvas; +import ohos.agp.render.Path; +import ohos.app.Context; + +import org.jetbrains.annotations.Nullable; + /** * Custom view to create blast visualizer *
* Created by gk */ - -public class BlastVisualizer extends BaseVisualizer { - +public class BlastVisualizer extends BaseVisualizer implements Component.DrawTask { private static final int BLAST_MAX_POINTS = 1000; private static final int BLAST_MIN_POINTS = 3; @@ -38,43 +39,48 @@ public class BlastVisualizer extends BaseVisualizer { private int mRadius; private int nPoints; + /** + * 使用java代码实例化调用 + * + * @param context + */ public BlastVisualizer(Context context) { super(context); } + /** + * 使用xml布局引用调用 + * + * @param context + * @param attrSet + */ public BlastVisualizer(Context context, - @Nullable AttributeSet attrs) { - super(context, attrs); - } - - public BlastVisualizer(Context context, - @Nullable AttributeSet attrs, - int defStyleAttr) { - super(context, attrs, defStyleAttr); + @Nullable AttrSet attrSet) { + super(context, attrSet); } @Override protected void init() { + addDrawTask(this::onDraw); mRadius = -1; nPoints = (int) (BLAST_MAX_POINTS * mDensity); - if (nPoints < BLAST_MIN_POINTS) + if (nPoints < BLAST_MIN_POINTS) { nPoints = BLAST_MIN_POINTS; + } mSpikePath = new Path(); } @Override - protected void onDraw(Canvas canvas) { - - //first time initialization + public void onDraw(Component component,Canvas canvas) { + // first time initialization if (mRadius == -1) { mRadius = getHeight() < getWidth() ? getHeight() : getWidth(); mRadius = (int) (mRadius * 0.65 / 2); } - //create the path and draw + // create the path and draw if (isVisualizationEnabled && mRawAudioBytes != null) { - if (mRawAudioBytes.length == 0) { return; } @@ -85,8 +91,9 @@ public class BlastVisualizer extends BaseVisualizer { for (int i = 0; i < nPoints; i++, angle += (360.0f / nPoints)) { int x = (int) Math.ceil(i * (mRawAudioBytes.length / nPoints)); int t = 0; - if (x < 1024) - t = ((byte) (-Math.abs(mRawAudioBytes[x]) + 128)) * (canvas.getHeight() / 4) / 128; + if (x < 1024) { + t = ((byte) (-Math.abs(mRawAudioBytes[x]) + 128)) * (component.getHeight() / 4) / 128; + } float posX = (float) (getWidth() / 2 + (mRadius + t) @@ -96,18 +103,15 @@ public class BlastVisualizer extends BaseVisualizer { + (mRadius + t) * Math.sin(Math.toRadians(angle))); - if (i == 0) + if (i == 0) { mSpikePath.moveTo(posX, posY); - else + } else { mSpikePath.lineTo(posX, posY); - + } } mSpikePath.close(); - canvas.drawPath(mSpikePath, mPaint); - } - - super.onDraw(canvas); + super.addDrawTask(this::onDraw); } } \ No newline at end of file diff --git a/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/BlobVisualizer.java b/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/BlobVisualizer.java index 578cad62762259411f6476b71a4f949eccc2b58f..444c79d6327335d398c57a14a30de6f0842d95c5 100644 --- a/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/BlobVisualizer.java +++ b/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/BlobVisualizer.java @@ -13,28 +13,28 @@ See the License for the specific language governing permissions and limitations under the License. */ -package com.gauravk.audiovisualizer.visualizer; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Path; -import android.graphics.PointF; -import android.support.annotation.Nullable; -import android.util.AttributeSet; +package com.gauravk.audiovisualizer.visualizer; import com.gauravk.audiovisualizer.base.BaseVisualizer; import com.gauravk.audiovisualizer.model.AnimSpeed; import com.gauravk.audiovisualizer.model.PaintStyle; import com.gauravk.audiovisualizer.utils.BezierSpline; +import ohos.agp.components.AttrSet; +import ohos.agp.components.Component; +import ohos.agp.components.element.ShapeElement; +import ohos.agp.render.Canvas; +import ohos.agp.render.Path; +import ohos.agp.utils.Point; +import ohos.app.Context; + /** * Custom view to create blob visualizer *
* Created by gk */ - -public class BlobVisualizer extends BaseVisualizer { - +public class BlobVisualizer extends BaseVisualizer implements Component.DrawTask { private static final int BLOB_MAX_POINTS = 60; private static final int BLOB_MIN_POINTS = 3; @@ -43,33 +43,52 @@ public class BlobVisualizer extends BaseVisualizer { private int nPoints; - private PointF[] mBezierPoints; + private Point[] mBezierPoints; private BezierSpline mBezierSpline; private float mAngleOffset; private float mChangeFactor; + /** + * 使用java代码实例化调用 + * + * @param context + */ public BlobVisualizer(Context context) { super(context); } - public BlobVisualizer(Context context, - @Nullable AttributeSet attrs) { - super(context, attrs); + /** + * 使用xml布局引用调用 + * + * @param context + * @param attrSet + */ + public BlobVisualizer(Context context, AttrSet attrSet) { + super(context, attrSet); } - public BlobVisualizer(Context context, - @Nullable AttributeSet attrs, - int defStyleAttr) { - super(context, attrs, defStyleAttr); + /** + * 使用xml并设置style调用 + * + * @param context + * @param attrSet + * @param styleName + */ + public BlobVisualizer(Context context, AttrSet attrSet, String styleName) { + super(context, attrSet, styleName); } + + @Override protected void init() { + addDrawTask(this::onDraw); mRadius = -1; nPoints = (int) (mDensity * BLOB_MAX_POINTS); - if (nPoints < BLOB_MIN_POINTS) + if (nPoints < BLOB_MIN_POINTS) { nPoints = BLOB_MIN_POINTS; + } mAngleOffset = (360.0f / nPoints); @@ -77,10 +96,10 @@ public class BlobVisualizer extends BaseVisualizer { mBlobPath = new Path(); - //initialize mBezierPoints, 2 extra for the smoothing first and last point - mBezierPoints = new PointF[nPoints + 2]; + // initialize mBezierPoints, 2 extra for the smoothing first and last point + mBezierPoints = new Point[nPoints + 2]; for (int i = 0; i < mBezierPoints.length; i++) { - mBezierPoints[i] = new PointF(); + mBezierPoints[i] = new Point(); } mBezierSpline = new BezierSpline(mBezierPoints.length); @@ -94,29 +113,34 @@ public class BlobVisualizer extends BaseVisualizer { private void updateChangeFactor(AnimSpeed animSpeed, boolean useHeight) { int height = 1; - if (useHeight) + if (useHeight) { height = getHeight() > 0 ? getHeight() : 1000; + } - if (animSpeed == AnimSpeed.SLOW) + if (animSpeed == AnimSpeed.SLOW) { mChangeFactor = height * 0.003f; - else if (animSpeed == AnimSpeed.MEDIUM) + } else if (animSpeed == AnimSpeed.MEDIUM) { mChangeFactor = height * 0.006f; - else + } else { mChangeFactor = height * 0.01f; + } } @Override - protected void onDraw(Canvas canvas) { + public void onDraw(Component component, Canvas canvas) { double angle = 0; - //first time initialization + // first time initialization if (mRadius == -1) { mRadius = getHeight() < getWidth() ? getHeight() : getWidth(); + + // 382 mRadius = (int) (mRadius * 0.65 / 2); + // 10.8 mChangeFactor = getHeight() * mChangeFactor; - //initialize bezier points + // initialize bezier points for (int i = 0; i < nPoints; i++, angle += mAngleOffset) { float posX = (float) (getWidth() / 2 + (mRadius) @@ -126,26 +150,28 @@ public class BlobVisualizer extends BaseVisualizer { + (mRadius) * Math.sin(Math.toRadians(angle))); - mBezierPoints[i].set(posX, posY); + mBezierPoints[i].modify(posX, posY); } } - //create the path and draw + // create the path and draw if (isVisualizationEnabled && mRawAudioBytes != null) { - if (mRawAudioBytes.length == 0) { return; } mBlobPath.rewind(); - //find the destination bezier point for a batch + // find the destination bezier point for a batch for (int i = 0; i < nPoints; i++, angle += mAngleOffset) { + Point mBezierPoint = mBezierPoints[i]; + // 1=1 X=34 i=2 X=68 int x = (int) Math.ceil((i + 1) * (mRawAudioBytes.length / nPoints)); int t = 0; - if (x < 1024) - t = ((byte) (-Math.abs(mRawAudioBytes[x]) + 128)) * (canvas.getHeight() / 4) / 128; + if (x < 1024) { + t = ((byte) (-Math.abs(mRawAudioBytes[x]) + 128)) * (component.getHeight() / 4) / 128; + } float posX = (float) (getWidth() / 2 + (mRadius + t) @@ -155,44 +181,45 @@ public class BlobVisualizer extends BaseVisualizer { + (mRadius + t) * Math.sin(Math.toRadians(angle))); - //calculate the new x based on change - if (posX - mBezierPoints[i].x > 0) { - mBezierPoints[i].x += mChangeFactor; + // calculate the new x based on change + if (posX - mBezierPoint.getPointXToInt() > 0) { + mBezierPoint.modify(mBezierPoint.getPointX() + mChangeFactor, mBezierPoint.getPointY()); } else { - mBezierPoints[i].x -= mChangeFactor; + mBezierPoint.modify(mBezierPoint.getPointX() - mChangeFactor, mBezierPoint.getPointY()); } - //calculate the new y based on change - if (posY - mBezierPoints[i].y > 0) { - mBezierPoints[i].y += mChangeFactor; + // calculate the new y based on change + if (posY - mBezierPoint.getPointY() > 0) { + mBezierPoint.modify(mBezierPoint.getPointX(), mBezierPoint.getPointY() + mChangeFactor); } else { - mBezierPoints[i].y -= mChangeFactor; + mBezierPoint.modify(mBezierPoint.getPointX(), mBezierPoint.getPointY() - mChangeFactor); } } - //set the first and last point as first - mBezierPoints[nPoints].set(mBezierPoints[0].x, mBezierPoints[0].y); - mBezierPoints[nPoints + 1].set(mBezierPoints[0].x, mBezierPoints[0].y); - //update the control points + // set the first and last point as first + + mBezierPoints[nPoints].modify(mBezierPoints[0].getPointX(), mBezierPoints[0].getPointY()); + mBezierPoints[nPoints + 1].modify(mBezierPoints[0].getPointX(), mBezierPoints[0].getPointY()); + + // update the control points mBezierSpline.updateCurveControlPoints(mBezierPoints); - PointF[] firstCP = mBezierSpline.getFirstControlPoints(); - PointF[] secondCP = mBezierSpline.getSecondControlPoints(); + Point[] firstCP = mBezierSpline.getFirstControlPoints(); + Point[] secondCP = mBezierSpline.getSecondControlPoints(); - //create the path - mBlobPath.moveTo(mBezierPoints[0].x, mBezierPoints[0].y); + // create the path + mBlobPath.moveTo(mBezierPoints[0].getPointX(), mBezierPoints[0].getPointY()); for (int i = 0; i < firstCP.length; i++) { - mBlobPath.cubicTo(firstCP[i].x, firstCP[i].y, - secondCP[i].x, secondCP[i].y, - mBezierPoints[i + 1].x, mBezierPoints[i + 1].y); + mBlobPath.cubicTo(firstCP[i].getPointX(), firstCP[i].getPointY(), + secondCP[i].getPointX(), secondCP[i].getPointY(), + mBezierPoints[i + 1].getPointX(), mBezierPoints[i + 1].getPointY()); } - //add an extra line to center cover the gap generated by last cubicTo - if (mPaintStyle == PaintStyle.FILL) - mBlobPath.lineTo(getWidth() / 2, getHeight() / 2); + // add an extra line to center cover the gap generated by last cubicTo + if (mPaintStyle == PaintStyle.FILL) { + mBlobPath.lineTo(getWidth() / 2, getHeight() / 2); + } canvas.drawPath(mBlobPath, mPaint); - } - - super.onDraw(canvas); + super.addDrawTask(this::onDraw); } } \ No newline at end of file diff --git a/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/CircleLineVisualizer.java b/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/CircleLineVisualizer.java index c2bda3609f9bbe365cfcffdfd4bc17989288694d..e0481aefd8d439faa0e802251bf7a0eb9ee25e74 100644 --- a/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/CircleLineVisualizer.java +++ b/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/CircleLineVisualizer.java @@ -1,24 +1,27 @@ package com.gauravk.audiovisualizer.visualizer; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Color; -import android.graphics.LinearGradient; -import android.graphics.Paint; -import android.graphics.Path; -import android.graphics.Rect; -import android.graphics.Shader; -import android.support.annotation.Nullable; -import android.util.AttributeSet; - import com.gauravk.audiovisualizer.base.BaseVisualizer; +import ohos.agp.components.AttrSet; +import ohos.agp.components.Component; +import ohos.agp.components.ComponentContainer; +import ohos.agp.render.*; +import ohos.agp.utils.Color; +import ohos.agp.utils.Point; +import ohos.agp.utils.Rect; +import ohos.app.Context; + +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; + /** + * 圆形 + * * @author maple on 2019/4/24 15:17. * @version v1.0 - * @see 1040441325@qq.com */ -public class CircleLineVisualizer extends BaseVisualizer { +public class CircleLineVisualizer extends BaseVisualizer implements Component.DrawTask, ComponentContainer.ArrangeListener { private static final int BAR_MAX_POINTS = 240; private static final int BAR_MIN_POINTS = 30; private Rect mClipBounds; @@ -29,18 +32,25 @@ public class CircleLineVisualizer extends BaseVisualizer { private Paint mGPaint; private boolean drawLine; + /** + * 使用java代码实例化调用 + * + * @param context + */ public CircleLineVisualizer(Context context) { super(context); } - public CircleLineVisualizer(Context context, @Nullable AttributeSet attrs) { + /** + * 使用xml布局引用调用 + * + * @param context + * @param attrs + */ + public CircleLineVisualizer(Context context, @Nullable AttrSet attrs) { super(context, attrs); } - public CircleLineVisualizer(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - public boolean isDrawLine() { return drawLine; } @@ -56,9 +66,12 @@ public class CircleLineVisualizer extends BaseVisualizer { @Override protected void init() { + addDrawTask(this::onDraw); + setArrangeListener(this::onArrange); mPoints = (int) (BAR_MAX_POINTS * mDensity); - if (mPoints < BAR_MIN_POINTS) + if (mPoints < BAR_MIN_POINTS) { mPoints = BAR_MIN_POINTS; + } mSrcY = new float[mPoints]; mClipBounds = new Rect(); setAnimationSpeed(mAnimSpeed); @@ -68,31 +81,27 @@ public class CircleLineVisualizer extends BaseVisualizer { } @Override - protected void onSizeChanged(int w, int h, int oldw, int oldh) { - super.onSizeChanged(w, h, oldw, oldh); - mRadius = Math.min(w, h) / 4; - mPointRadius = Math.abs((int) (2 * mRadius * Math.sin(Math.PI / mPoints / 3))); - LinearGradient lg = new LinearGradient(getWidth() / 2 + mRadius, getHeight() / 2, getWidth() / 2 + mRadius + mPointRadius * 5, getHeight() / 2 - , Color.parseColor("#77FF5722"), Color.parseColor("#10FF5722"), Shader.TileMode.CLAMP); - mGPaint.setShader(lg); - } - - @Override - protected void onDraw(Canvas canvas) { - super.onDraw(canvas); - canvas.getClipBounds(mClipBounds); + public void onDraw(Component component, Canvas canvas) { + canvas.getLocalClipBounds(mClipBounds); updateData(); + // draw circle's points for (int i = 0; i < 360; i = i + 360 / mPoints) { float cx = (float) (getWidth() / 2 + Math.cos(i * Math.PI / 180) * mRadius); float cy = (float) (getHeight() / 2 - Math.sin(i * Math.PI / 180) * mRadius); canvas.drawCircle(cx, cy, mPointRadius, mPaint); } + // draw lines - if (drawLine) drawLines(canvas); + if (drawLine) { + drawLines(canvas); + } + // draw bar for (int i = 0; i < 360; i = i + 360 / mPoints) { - if (mSrcY[i * mPoints / 360] == 0) continue; + if (mSrcY[i * mPoints / 360] == 0) { + continue; + } canvas.save(); canvas.rotate(-i, getWidth() / 2, getHeight() / 2); float cx = (float) (getWidth() / 2 + mRadius); @@ -102,6 +111,7 @@ public class CircleLineVisualizer extends BaseVisualizer { canvas.drawCircle(cx + mSrcY[i * mPoints / 360], cy, mPointRadius, mPaint); canvas.restore(); } + super.addDrawTask(this::onDraw); } /** @@ -110,7 +120,9 @@ public class CircleLineVisualizer extends BaseVisualizer { * @param canvas target canvas */ private void drawLines(Canvas canvas) { - int lineLen = 14 * mPointRadius;//default len, + int lineLen = 14 * mPointRadius; + + // default len, for (int i = 0; i < 360; i = i + 360 / mPoints) { canvas.save(); canvas.rotate(-i, getWidth() / 2, getHeight() / 2); @@ -127,7 +139,9 @@ public class CircleLineVisualizer extends BaseVisualizer { private void updateData() { if (isVisualizationEnabled && mRawAudioBytes != null) { - if (mRawAudioBytes.length == 0) return; + if (mRawAudioBytes.length == 0) { + return; + } for (int i = 0; i < mSrcY.length; i++) { int x = (int) Math.ceil((i + 1) * (mRawAudioBytes.length / mPoints)); int t = 0; @@ -138,4 +152,30 @@ public class CircleLineVisualizer extends BaseVisualizer { } } } + + /** + * 大小发生变化调用 + * + * @param w 0 + * @param h 0 + * @param oldw 1176 + * @param oldh 1800 + * @return + */ + @Override + public boolean onArrange(int w, int h, int oldw, int oldh) { + mRadius = Math.min(oldw, oldh) / 4; + mPointRadius = Math.abs((int) (2 * mRadius * Math.sin(Math.PI / mPoints / 3))); + Point[] newPoints = new Point[]{new Point(getWidth() / 2 + mRadius, getHeight() / 2)}; + float[] newStops = {getWidth() / 2 + mRadius + mPointRadius * 5, getHeight() / 2}; + Color[] newColors = new Color[]{new Color(Color.rgb(255, 174, 137)), new Color(Color.rgb(255, 239, 215))}; + LinearShader lg = new LinearShader( + newPoints, + newStops, + newColors, + Shader.TileMode.CLAMP_TILEMODE); + mGPaint.setShader(lg, Paint.ShaderType.LINEAR_SHADER); + mPaint.setShader(lg, Paint.ShaderType.LINEAR_SHADER); + return false; + } } diff --git a/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/HiFiVisualizer.java b/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/HiFiVisualizer.java index 629b674b8dfc503df8b151c7ae9702fdc5e31ca9..c12ecde1e01547190bfb7f4548ecc35748eef019 100644 --- a/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/HiFiVisualizer.java +++ b/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/HiFiVisualizer.java @@ -1,79 +1,93 @@ package com.gauravk.audiovisualizer.visualizer; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Paint; -import android.graphics.Path; -import android.support.annotation.Nullable; -import android.util.AttributeSet; -import android.util.Log; -import android.view.MotionEvent; - import com.gauravk.audiovisualizer.base.BaseVisualizer; + import com.gauravk.audiovisualizer.model.PaintStyle; +import ohos.agp.colors.ColorSpec; +import ohos.agp.colors.RgbColor; +import ohos.agp.components.AttrSet; +import ohos.agp.components.Component; +import ohos.agp.render.Canvas; +import ohos.agp.render.Paint; +import ohos.agp.render.Path; +import ohos.agp.utils.Color; +import ohos.app.Context; -import java.util.ArrayList; -import java.util.Arrays; +import org.jetbrains.annotations.Nullable; /** + * 折线图 + * * @author maple on 2019/4/25 10:17. * @version v1.0 - * @see 1040441325@qq.com */ -public class HiFiVisualizer extends BaseVisualizer { +public class HiFiVisualizer extends BaseVisualizer implements Component.DrawTask { private static final int BAR_MAX_POINTS = 240; private static final int BAR_MIN_POINTS = 30; private static final float PER_RADIUS = .65f; private int mRadius; private int mPoints; private int[] mHeights; - private Path mPath;//outward path - private Path mPath1;//inward path + private Paint paint; + // outward path + private Path mPath; + + // inward path + private Path mPath1; + /** * This is the distance from center to bezier control point. * We can calculate the bezier control points of each segment this distance and its angle; */ private int mBezierControlPointLen; + /** + * 使用java代码实例化调用 + * + * @param context + */ public HiFiVisualizer(Context context) { super(context); } - public HiFiVisualizer(Context context, @Nullable AttributeSet attrs) { + /** + * 使用xml布局引用调用 + * + * @param context + * @param attrs + */ + public HiFiVisualizer(Context context, @Nullable AttrSet attrs) { super(context, attrs); } - public HiFiVisualizer(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { - super(context, attrs, defStyleAttr); - } - @Override protected void init() { + addDrawTask(this::onDraw); mRadius = -1; mPath = new Path(); mPath1 = new Path(); - mPaint.setStyle(Paint.Style.STROKE); + mPaint.setStyle(Paint.Style.STROKE_STYLE); mPaint.setAntiAlias(true); mPaint.setStrokeWidth(1.0f); mPoints = (int) (BAR_MAX_POINTS * mDensity); - if (mPoints < BAR_MIN_POINTS) mPoints = BAR_MIN_POINTS; + if (mPoints < BAR_MIN_POINTS) { + mPoints = BAR_MIN_POINTS; + } mHeights = new int[mPoints]; - } - - /** - * you cannot change the style of paint; - * the paintStyle fixed at Paint.Style.STROKE: - * - * @param paintStyle style of the visualizer. - */ - @Override - @Deprecated() - public void setPaintStyle(PaintStyle paintStyle) { + paint = new Paint(); + paint.setColor(new Color(Color.getIntColor("#FCB8A3"))); + paint.setStrokeWidth(mStrokeWidth); + if (mPaintStyle == PaintStyle.FILL) { + paint.setStyle(Paint.Style.FILL_STYLE); + } + else { + paint.setStyle(Paint.Style.STROKE_STYLE); + } } @Override - protected void onDraw(Canvas canvas) { + public void onDraw(Component component, Canvas canvas) { if (mRadius == -1) { mRadius = (int) (Math.min(getWidth(), getHeight()) / 2 * PER_RADIUS); mBezierControlPointLen = (int) (mRadius / Math.cos(Math.PI / mPoints)); @@ -81,10 +95,12 @@ public class HiFiVisualizer extends BaseVisualizer { updateData(); mPath.reset(); mPath1.reset(); + // start the outward path from the last point float cxL = (float) (getWidth() / 2 + Math.cos((360 - 360 / mPoints) * Math.PI / 180) * (mRadius + mHeights[mPoints - 1])); float cyL = (float) (getHeight() / 2 - Math.sin((360 - 360 / mPoints) * Math.PI / 180) * (mRadius + mHeights[mPoints - 1])); mPath.moveTo(cxL, cyL); + // start the inward path from the last point float cxL1 = (float) (getWidth() / 2 + Math.cos((360 - 360 / mPoints) * Math.PI / 180) * (mRadius - mHeights[mPoints - 1])); float cyL1 = (float) (getHeight() / 2 - Math.sin((360 - 360 / mPoints) * Math.PI / 180) * (mRadius - mHeights[mPoints - 1])); @@ -94,14 +110,17 @@ public class HiFiVisualizer extends BaseVisualizer { // the next point of path float cx = (float) (getWidth() / 2 + Math.cos(i * Math.PI / 180) * (mRadius + mHeights[i * mPoints / 360])); float cy = (float) (getHeight() / 2 - Math.sin(i * Math.PI / 180) * (mRadius + mHeights[i * mPoints / 360])); - //second bezier control point + + // second bezier control point float bx = (float) (getWidth() / 2 + Math.cos((i - (180 / mPoints)) * Math.PI / 180) * (mBezierControlPointLen + mHeights[i * mPoints / 360])); float by = (float) (getHeight() / 2 - Math.sin((i - (180 / mPoints)) * Math.PI / 180) * (mBezierControlPointLen + mHeights[i * mPoints / 360])); int lastPoint = i == 0 ? mPoints - 1 : i * mPoints / 360 - 1; - //fist bezier control point + + // fist bezier control point float ax = (float) (getWidth() / 2 + Math.cos((i - (180 / mPoints)) * Math.PI / 180) * (mBezierControlPointLen + mHeights[lastPoint])); float ay = (float) (getHeight() / 2 - Math.sin((i - (180 / mPoints)) * Math.PI / 180) * (mBezierControlPointLen + mHeights[lastPoint])); mPath.cubicTo(ax, ay, bx, by, cx, cy); + // inward float cx1 = (float) (getWidth() / 2 + Math.cos(i * Math.PI / 180) * (mRadius - mHeights[i * mPoints / 360])); float cy1 = (float) (getHeight() / 2 - Math.sin(i * Math.PI / 180) * (mRadius - mHeights[i * mPoints / 360])); @@ -122,8 +141,9 @@ public class HiFiVisualizer extends BaseVisualizer { for (int i = 0; i < mHeights.length; i++) { int x = (int) Math.ceil((i + 1) * (mRawAudioBytes.length / mPoints)); int t = 0; - if (x < 1024) + if (x < 1024) { t = ((byte) (Math.abs(mRawAudioBytes[x]) + 128)) * mRadius / 128; + } mHeights[i] = -t; } } diff --git a/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/WaveVisualizer.java b/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/WaveVisualizer.java index 13e2bdbfc307087305e1151942f3a56728a62ebb..84f5ffb857362f6a7ba2b16a33df7d24062ca4ee 100644 --- a/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/WaveVisualizer.java +++ b/audiovisualizer/src/main/java/com/gauravk/audiovisualizer/visualizer/WaveVisualizer.java @@ -13,15 +13,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -package com.gauravk.audiovisualizer.visualizer; -import android.content.Context; -import android.graphics.Canvas; -import android.graphics.Path; -import android.graphics.PointF; -import android.graphics.Rect; -import android.support.annotation.Nullable; -import android.util.AttributeSet; +package com.gauravk.audiovisualizer.visualizer; import com.gauravk.audiovisualizer.base.BaseVisualizer; import com.gauravk.audiovisualizer.model.AnimSpeed; @@ -29,6 +22,16 @@ import com.gauravk.audiovisualizer.model.PaintStyle; import com.gauravk.audiovisualizer.model.PositionGravity; import com.gauravk.audiovisualizer.utils.AVConstants; +import ohos.agp.components.AttrSet; +import ohos.agp.components.Component; +import ohos.agp.render.Canvas; +import ohos.agp.render.Path; +import ohos.agp.utils.Point; +import ohos.agp.utils.Rect; +import ohos.app.Context; + +import org.jetbrains.annotations.Nullable; + import java.util.Random; /** @@ -36,9 +39,7 @@ import java.util.Random; *
* Created by gk
*/
-
-public class WaveVisualizer extends BaseVisualizer {
-
+public class WaveVisualizer extends BaseVisualizer implements Component.DrawTask {
private static final int WAVE_MAX_POINTS = 54;
private static final int WAVE_MIN_POINTS = 3;
@@ -48,45 +49,53 @@ public class WaveVisualizer extends BaseVisualizer {
private int nPoints;
- private PointF[] mBezierPoints, mBezierControlPoints1, mBezierControlPoints2;
+ private Point[] mBezierPoints;
+ private Point[] mBezierControlPoints1;
+ private Point[] mBezierControlPoints2;
- private float[] mSrcY, mDestY;
+ private float[] mSrcY;
+ private float[] mDestY;
private float mWidthOffset;
private Rect mClipBounds;
private int nBatchCount;
- private Random mRandom;
+ private Random mRandom = new Random();
+ /**
+ * 使用java代码实例化调用
+ *
+ * @param context
+ */
public WaveVisualizer(Context context) {
super(context);
}
+ /**
+ * 使用xml布局引用调用
+ *
+ * @param context
+ * @param attrs
+ */
public WaveVisualizer(Context context,
- @Nullable AttributeSet attrs) {
+ @Nullable AttrSet attrs) {
super(context, attrs);
}
- public WaveVisualizer(Context context,
- @Nullable AttributeSet attrs,
- int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- }
-
@Override
protected void init() {
+ addDrawTask(this::onDraw);
nPoints = (int) (WAVE_MAX_POINTS * mDensity);
- if (nPoints < WAVE_MIN_POINTS)
+ if (nPoints < WAVE_MIN_POINTS) {
nPoints = WAVE_MIN_POINTS;
+ }
mWidthOffset = -1;
nBatchCount = 0;
setAnimationSpeed(mAnimSpeed);
- mRandom = new Random();
-
mClipBounds = new Rect();
mWavePath = new Path();
@@ -94,16 +103,15 @@ public class WaveVisualizer extends BaseVisualizer {
mSrcY = new float[nPoints + 1];
mDestY = new float[nPoints + 1];
- //initialize mBezierPoints
- mBezierPoints = new PointF[nPoints + 1];
- mBezierControlPoints1 = new PointF[nPoints + 1];
- mBezierControlPoints2 = new PointF[nPoints + 1];
+ // initialize mBezierPoints
+ mBezierPoints = new Point[nPoints + 1];
+ mBezierControlPoints1 = new Point[nPoints + 1];
+ mBezierControlPoints2 = new Point[nPoints + 1];
for (int i = 0; i < mBezierPoints.length; i++) {
- mBezierPoints[i] = new PointF();
- mBezierControlPoints1[i] = new PointF();
- mBezierControlPoints2[i] = new PointF();
+ mBezierPoints[i] = new Point();
+ mBezierControlPoints1[i] = new Point();
+ mBezierControlPoints2[i] = new Point();
}
-
}
@Override
@@ -113,57 +121,55 @@ public class WaveVisualizer extends BaseVisualizer {
}
@Override
- protected void onDraw(Canvas canvas) {
-
+ public void onDraw(Component component, Canvas canvas) {
if (mWidthOffset == -1) {
+ canvas.getLocalClipBounds(mClipBounds);
- canvas.getClipBounds(mClipBounds);
-
- mWidthOffset = canvas.getWidth() / nPoints;
+ mWidthOffset = component.getWidth() / nPoints;
//initialize bezier points
for (int i = 0; i < mBezierPoints.length; i++) {
float posX = mClipBounds.left + (i * mWidthOffset);
float posY;
- if (mPositionGravity == PositionGravity.TOP)
+ if (mPositionGravity == PositionGravity.TOP) {
posY = mClipBounds.top;
- else
+ } else {
posY = mClipBounds.bottom;
+ }
mSrcY[i] = posY;
mDestY[i] = posY;
- mBezierPoints[i].set(posX, posY);
+ mBezierPoints[i].modify(posX, posY);
}
}
- //create the path and draw
+ // create the path and draw
if (isVisualizationEnabled && mRawAudioBytes != null) {
-
if (mRawAudioBytes.length == 0) {
return;
}
mWavePath.rewind();
- //find the destination bezier point for a batch
+ // find the destination bezier point for a batch
if (nBatchCount == 0) {
-
float randPosY = mDestY[mRandom.nextInt(nPoints)];
for (int i = 0; i < mBezierPoints.length; i++) {
-
int x = (int) Math.ceil((i + 1) * (mRawAudioBytes.length / nPoints));
int t = 0;
- if (x < 1024)
- t = canvas.getHeight() +
- ((byte) (Math.abs(mRawAudioBytes[x]) + 128)) * canvas.getHeight() / 128;
+ if (x < 1024) {
+ t = component.getHeight()
+ + ((byte) (Math.abs(mRawAudioBytes[x]) + 128)) * component.getHeight() / 128;
+ }
float posY;
- if (mPositionGravity == PositionGravity.TOP)
+ if (mPositionGravity == PositionGravity.TOP) {
posY = mClipBounds.bottom - t;
- else
+ } else {
posY = mClipBounds.top + t;
+ }
//change the source and destination y
mSrcY[i] = mDestY[i];
@@ -173,43 +179,40 @@ public class WaveVisualizer extends BaseVisualizer {
mDestY[mBezierPoints.length - 1] = randPosY;
}
- //increment batch count
+ // increment batch count
nBatchCount++;
- //for smoothing animation
+ // for smoothing animation
for (int i = 0; i < mBezierPoints.length; i++) {
- mBezierPoints[i].y = mSrcY[i] + (((float) (nBatchCount) / mMaxBatchCount) * (mDestY[i] - mSrcY[i]));
+ mBezierPoints[i].modify(mBezierPoints[i].getPointX(), mSrcY[i] + (((float) (nBatchCount) / mMaxBatchCount) * (mDestY[i] - mSrcY[i])));
}
- //reset the batch count
- if (nBatchCount == mMaxBatchCount)
+ // reset the batch count
+ if (nBatchCount == mMaxBatchCount) {
nBatchCount = 0;
+ }
- //calculate the bezier curve control points
+ // calculate the bezier curve control points
for (int i = 1; i < mBezierPoints.length; i++) {
- mBezierControlPoints1[i].set((mBezierPoints[i].x + mBezierPoints[i - 1].x) / 2, mBezierPoints[i - 1].y);
- mBezierControlPoints2[i].set((mBezierPoints[i].x + mBezierPoints[i - 1].x) / 2, mBezierPoints[i].y);
+ mBezierControlPoints1[i].modify((mBezierPoints[i].getPointX() + mBezierPoints[i - 1].getPointX()) / 2, mBezierPoints[i - 1].getPointY());
+ mBezierControlPoints2[i].modify((mBezierPoints[i].getPointX() + mBezierPoints[i - 1].getPointX()) / 2, mBezierPoints[i].getPointY());
}
- //create the path
- mWavePath.moveTo(mBezierPoints[0].x, mBezierPoints[0].y);
+ // create the path
+ mWavePath.moveTo(mBezierPoints[0].getPointX(), mBezierPoints[0].getPointY());
for (int i = 1; i < mBezierPoints.length; i++) {
- mWavePath.cubicTo(mBezierControlPoints1[i].x, mBezierControlPoints1[i].y,
- mBezierControlPoints2[i].x, mBezierControlPoints2[i].y,
- mBezierPoints[i].x, mBezierPoints[i].y);
+ mWavePath.cubicTo(mBezierControlPoints1[i].getPointX(), mBezierControlPoints1[i].getPointY(),
+ mBezierControlPoints2[i].getPointX(), mBezierControlPoints2[i].getPointY(),
+ mBezierPoints[i].getPointX(), mBezierPoints[i].getPointY());
}
- //add last 3 line to close the view
- //mWavePath.lineTo(mClipBounds.right, mBezierPoints[0].y);
if (mPaintStyle == PaintStyle.FILL) {
mWavePath.lineTo(mClipBounds.right, mClipBounds.bottom);
mWavePath.lineTo(mClipBounds.left, mClipBounds.bottom);
mWavePath.close();
}
-
canvas.drawPath(mWavePath, mPaint);
}
-
- super.onDraw(canvas);
+ super.addDrawTask(this::onDraw);
}
}
\ No newline at end of file
diff --git a/audiovisualizer/src/main/res/values/attrs.xml b/audiovisualizer/src/main/res/values/attrs.xml
deleted file mode 100644
index 91eca69ddc39d36ca2e453191f7b738ac55fd91d..0000000000000000000000000000000000000000
--- a/audiovisualizer/src/main/res/values/attrs.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-