效果图:
1.绘制录音曲线效果
- 公式和网站介绍 我们要绘制这种效果,最直观方便的方式就是采用三角函数的cos/sin的函数,首先我们需要一个重要的网站:
Desmos: https://www.desmos.com/calculator 可以把我们的三角函数以图刑的方式显示,公式:y=Asin(ωx+φ)+k
例如: - 衰减函数选择
虽然我们得到了图形,但是效果好像不是我们需要的,所有需要修改,这里介绍一个重要的概念:衰减函数 而且是对称衰减 对应效果图:
- 其中 是我们选择的衰减函数,这样我们就得到了逐渐增加 和 减弱的波形效果。
转化成代码:
private float getSinPoint(float x) {
return (float) (4/(4+Math.pow(x,4))*Math.sin(3*x + 5*offset));
}
- 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