Android 绘制录音波浪 + 拓展: 让“字体”迎波而浪

效果图: 

                                       

1.绘制录音曲线效果

  1. 公式和网站介绍

    我们要绘制这种效果,最直观方便的方式就是采用三角函数的cos/sin的函数,首先我们需要一个重要的网站:

    Desmos: https://www.desmos.com/calculator 可以把我们的三角函数以图刑的方式显示,公式:y=Asin(ωx+φ)+k

    例如:

  2. 衰减函数选择

    虽然我们得到了图形,但是效果好像不是我们需要的,所有需要修改,这里介绍一个重要的概念:衰减函数 而且是对称衰减

    对应效果图:

    其中 \frac{4}{4+x^{4}} 是我们选择的衰减函数,这样我们就得到了逐渐增加 和 减弱的波形效果。
    转化成代码:
        private float getSinPoint(float x) {
    
            return (float) (4/(4+Math.pow(x,4))*Math.sin(3*x + 5*offset));
        }
    offset 看第三处相位变化,参数可以根据自己需要修改
     
  3. 修改相位,让曲线动起来
    虽然我们得到了,想要的波形但是怎么让他动起来呢,我们知道公式: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.让字体迎波而浪

通过绘制录音波浪我们能够把波浪曲线绘制出来并且能动起来,接下来我们要做的是要把我们的字体,给放到曲线上并且让字体也能和曲线一样浪浪的~~

  1. 选择合适的波浪曲线

     

    效果图:

    波动不用太大,让字体有浮动的效果就行,看起来舒服,转化成代码:

    private float getSinPoint(float x) {
    
            return (float) (4/(4+Math.pow(x,2))*Math.sin(0.2*x + offset));
        }

    其他就和绘制录音波浪一样,这里就不累赘了,下面提一个Path的方法

  2. 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

发布了119 篇原创文章 · 获赞 140 · 访问量 18万+

猜你喜欢

转载自blog.csdn.net/WangRain1/article/details/100036456