效果图:
1.绘制录音曲线效果
- 公式和网站介绍
我们要绘制这种效果,最直观方便的方式就是采用三角函数的cos/sin的函数,首先我们需要一个重要的网站:
Desmos: https://www.desmos.com/calculator 可以把我们的三角函数以图刑的方式显示,公式:y=Asin(ωx+φ)+k
例如:
- 衰减函数选择
虽然我们得到了图形,但是效果好像不是我们需要的,所有需要修改,这里介绍一个重要的概念:衰减函数 而且是对称衰减
对应效果图:
其中是我们选择的衰减函数,这样我们就得到了逐渐增加 和 减弱的波形效果。
转化成代码:
offset 看第三处相位变化,参数可以根据自己需要修改private float getSinPoint(float x) { return (float) (4/(4+Math.pow(x,4))*Math.sin(3*x + 5*offset)); }
- 修改相位,让曲线动起来
虽然我们得到了,想要的波形但是怎么让他动起来呢,我们知道公式:y=Asin(ωx+φ)+k 其中 φ 是改变相位的,也就是我们只要动态的修改这个值,我们就能得到不同位置的图形
如图我们可以动态的拖动修改 a 这个值,看到图形也在移动。
1.获取采样数据,我们能看到整个衰减过程,从-4 到 4 之间变化明显,我们就取这段值作为采样数据List<Float> mSimples = new ArrayList<>(); /** * 采样图像中就有变化的数据【-4,4】这是x值 */ private void simple() { ValueAnimator animator = ValueAnimator.ofFloat(-4, 4); animator.setDuration(1500); animator.setInterpolator(new LinearInterpolator()); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { mSimples.add((float) animation.getAnimatedValue()); invalidate(); } }); animator.start(); }
2.根据采样的x值,计算相应的 y 值并且用path路径封装,等待绘制
@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); canvas.translate(getWidth()/2,getHeight()/2); mPath.reset(); for (int i = 0;i<mSimples.size();i++){ if (i==0){ mPath.moveTo(mSimples.get(i)*130,getSinPoint(mSimples.get(i))*100); }else { mPath.lineTo(mSimples.get(i)*130,getSinPoint(mSimples.get(i))*100); } } canvas.drawPath(mPath,mPaint); }
其中x,y乘以130和100是为了放大在手机界面的效果,这里只是做个简单的放大,主要为了demo方便,真正项目上要根据分辨率来。
3.修改 offset 相位让曲线移动float offset = 0; ValueAnimator mAnimator; private void startAnimation(){ mAnimator = ValueAnimator.ofFloat(0, (float) (2*Math.PI)); mAnimator.setDuration(5000); mAnimator.setInterpolator(new LinearInterpolator()); mAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { offset = (float) animation.getAnimatedValue(); invalidate(); } }); }
这里用个属性动画修改 三角函数的移动,我们知道一个三角函数的周期 是 2π,所以这里只需要取一个周期內就行。
所以分析到这里基本原理我们都明白了,也有代码实现,需要作成多复杂的,就自己去发挥发挥就行了。
github:https://github.com/WangRain1/AnimationLine
2.让字体迎波而浪
通过绘制录音波浪我们能够把波浪曲线绘制出来并且能动起来,接下来我们要做的是要把我们的字体,给放到曲线上并且让字体也能和曲线一样浪浪的~~
- 选择合适的波浪曲线
效果图:
波动不用太大,让字体有浮动的效果就行,看起来舒服,转化成代码:
private float getSinPoint(float x) { return (float) (4/(4+Math.pow(x,2))*Math.sin(0.2*x + offset)); }
其他就和绘制录音波浪一样,这里就不累赘了,下面提一个Path的方法
-
canves绘制text 到 path上
/** * Draw the text, with origin at (x,y), using the specified paint, along the specified path. The * paint's Align setting determins where along the path to start the text. * * @param text The text to be drawn * @param path The path the text should follow for its baseline * @param hOffset The distance along the path to add to the text's starting position * @param vOffset The distance above(-) or below(+) the path to position the text * @param paint The paint used for the text (e.g. color, size, style) */ public void drawTextOnPath(@NonNull String text, @NonNull Path path, float hOffset, float vOffset, @NonNull Paint paint) { super.drawTextOnPath(text, path, hOffset, vOffset, paint); }
通过这个方法可以实现把我们的字体绘制到path上。
canvas.drawTextOnPath("w a n g r a i n 1",mPath,200,0,mPaint);
200是x坐标的偏移量,y坐标偏移量为0。
至此就结束了,整个绘制流程。Github:https://github.com/WangRain1/AnimationLine