美文网首页
【Android】水波纹

【Android】水波纹

作者: Sraindy | 来源:发表于2019-08-08 16:54 被阅读0次

    正弦曲线

    正弦曲线可表示为y=Asin(ωx+φ)+k,定义为函数y=Asin(ωx+φ)+k在直角坐标系上的图象,其中sin为正弦符号,x是直角坐标系x轴上的数值,y是在同一直角坐标系上函数对应的y值,k、ω和φ是常数(k、ω、φ∈R且ω≠0)
    A——振幅,当物体作轨迹符合正弦曲线的直线往复运动时,其值为行程的1/2。
    (ωx+φ)——相位,反映变量y所处的状态。
    φ——初相,x=0时的相位;反映在坐标系上则为图像的左右移动。
    k——偏距,反映在坐标系上则为图像的上移或下移。
    ω——角速度, 控制正弦周期(单位弧度内震动的次数)。


    image.png

    Android中Math.sin()和Math.cos()

    Math.sin(x) x 的正玄值。返回值在 -1.0 到 1.0 之间;
    Math.cos(x) x 的余弦值。返回的是 -1.0 到 1.0 之间的数;
    这两个函数中的X 都是指的“弧度”而非“角度”,弧度的计算公式为: 2PI/360角度;
    30° 角度 的弧度 = 2PI/360*30

    水波纹案例

    来源:
    [https://blog.csdn.net/tianjian4592/article/details/44222565]

    1、标准正余弦水波纹

    思路基本如下:
    1.确定水波函数方程
    2.根据函数方程得出每一个波纹上点的坐标;
    3.将水波进行平移,即将水波上的点不断的移动;
    4.不断的重新绘制,生成动态水波纹;
    实现如下:
    正余弦函数方程为:
    y = Asin(wx+b)+h ,这个公式里:w影响周期,A影响振幅,h影响y位置,b为初相;
    x = (2π-b)/w,
    以屏幕的宽度为周期,再根据函数方程得出每一个波纹上点的坐标

    mTotalWidth:是屏幕宽度   
    OFFSET_Y:Y轴的位置(x=0,y的位置)
    mCycleFactorW = (float) (2 * Math.PI / mTotalWidth);
            // 根据view总宽度得出所有对应的y值
            for (int i = 0; i < mTotalWidth; i++) {
                //y=Asin(ωx+φ)+k
                mYPositions[i] = (float) (STRETCH_FACTOR_A * Math.sin(mCycleFactorW * i) + OFFSET_Y);
            }
    

    根据得出的所有y值,则可以在onDraw中通过如下代码绘制两条静态波纹(竖着画线):

       for (int i = 0; i < mTotalWidth; i++) {
                // 减1000和800只是为了控制波纹绘制的y的在屏幕的位置,大家可以改成一个变量,然后动态改变这个变量,从而形成波纹上升下降效果
                // 绘制第一条水波纹
                canvas.drawLine(i, mTotalHeight - mResetOneYPositions[i] - 1000, i, mTotalHeight - 800, mWavePaint);
                // 绘制第二条水波纹
                canvas.drawLine(i, mTotalHeight - mResetTwoYPositions[i] - 1000, i, mTotalHeight - 800, mWavePaint);
            }
    

    这种方式类似于数学里面的细分法,一条波纹,如果横向以一个像素点为单位进行细分,则形成view总宽度条直线,并且每条直线的起点和终点我们都能知道,在此基础上我们只需要循环绘制出所有细分出来的直线(直线都是纵向的),则形成了一条静态的水波纹。
    让水波纹动起来:

     private void resetPositonY() {
            // mXOneOffset代表当前第一条水波纹要移动的距离
            int yOneInterval = mYPositions.length - mXOneOffset;
            /**
             * arraycopy方法
             * src - 源数组。
             * srcPos - 源数组中的起始位置。
             * dest - 目标数组。
             * destPos - 目标数据中的起始位置。
             * length - 要复制的数组元素的数量。
             */
            // 使用System.arraycopy方式重新填充第一条波纹的数据。平移偏移个数,将偏移的数据添加到数组后面
            System.arraycopy(mYPositions, mXOneOffset, mResetOneYPositions, 0, yOneInterval);
            System.arraycopy(mYPositions, 0, mResetOneYPositions, yOneInterval, mXOneOffset);
            int yTwoInterval = mYPositions.length - mXTwoOffset;
            System.arraycopy(mYPositions, mXTwoOffset, mResetTwoYPositions, 0, yTwoInterval);
            System.arraycopy(mYPositions, 0, mResetTwoYPositions, yTwoInterval, mXTwoOffset);
        }
    

    将偏移的数,插到尾部。
    如此下来只要不断的改变这两个数组的数据,然后不断刷新,即可生成动态水波纹了。刷新可以调用invalidate()或postInvalidate(),区别在于后者可以在子线程中更新UI

    相关文章

      网友评论

          本文标题:【Android】水波纹

          本文链接:https://www.haomeiwen.com/subject/vigxjctx.html