zoukankan      html  css  js  c++  java
  • 制作水波载入动画

    本来想写写有点意思的东西的,哈哈。上篇文章说的。以后再写吧。今天先介绍一下一个水波载入动画,效果图例如以下:


    做的比較简单。真机效果比这个好非常多,这个截图做的gif,有点蛋疼。

    说说思路吧:

    1. 首先画正弦曲线。这里取的是正弦周期的前3/4个周期。这样看起来比其它的周期变化非常好点;

    2. 画了正弦曲线以后,就要让正弦曲线动起来,怎么动起来?乍一看认为非常困难的样子。事实上我们想想移动正弦曲线,只是是某个位置的Y轴值变化了,那么我们仅仅要给sin(x)中加入一个变量即可。即sin(x + offset)。offset的值按时间规律来变化。那么最后表现出来的效果就有移动的感觉。

    3. 关于正弦曲线振幅不能设置的太高,由于我们的屏幕本来就非常小,假设振幅非常大就表现的非常不真实。我这里取的是30,看起来效果还不错。

    4. 最后就是y轴方向的改变了。

    要不停的提升。这里写死了,假设想用。就直接写个方法。去设置即可,比方你要设置百分比之类的。

    最后上代码:

    package com.zdl.wavedemo;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.util.AttributeSet;
    import android.view.View;
    
    /**
     * Created by zhoudailiang on 2015/7/14.
     */
    public class WaveView extends View {
    
        private Paint paint;
        private Path mPath;
        private float offset = 0.0f; // 控制正弦曲线的变化
        private MyThread thread;
        private final float amplidute = 30; // 振幅
        private float gradualY; // Y方向的渐变量
        private float gradualX; // X方向的渐变量
        private boolean isMoving = true; // 能够移动
    
        public WaveView(Context context) {
            super(context);
            init();
        }
    
    
        public WaveView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        private void init() {
            // 初始化画笔
            paint = new Paint();
            paint.setAntiAlias(true);
            paint.setColor(Color.BLUE);
            paint.setStrokeWidth(2);
    
            // 初始化变量
            gradualX = 0.02f;
    
            // 初始化路径
            mPath = new Path();
    
            // 初始化线程
            thread = new MyThread();
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            gradualY = getMeasuredHeight();
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            int width = getMeasuredWidth();
            int height = getMeasuredHeight();
    
            mPath.reset();
            for (float i = 0; i < width; i += 0.5) {
                float tmp = (float) (1.5 * Math.PI * i / width);
                float y = amplidute * (float)Math.sin(tmp + offset) + gradualY;
                if (i == 0) {
                    mPath.moveTo(0f, y);
                } else {
                    mPath.lineTo(i, y);
                }
            }
            mPath.lineTo(width, height);
            mPath.lineTo(0, height);
            mPath.close();
            canvas.drawPath(mPath, paint);
            // 启动线程開始更新
            if (!thread.isAlive() && isMoving) {
                thread.start();
            }
        }
    
        class MyThread extends Thread {
            public void run() {
                while (isMoving) {
                    offset =  offset + gradualX > 2 * Math.PI ? 0 : offset + gradualX;
                    gradualY -= 0.5;
                    if (gradualY < -amplidute) {
                        isMoving = false;
                        break;
                    }
                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    postInvalidate();
                }
            }
        }
    }
    

    代码如上,非常easy。事实上这里还能够通过还有一种方式实现。下篇文章进行介绍。

    2015-7-15补充:

    使用贝塞尔曲线,代码例如以下:

    package com.zdl.wavedemo;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.util.AttributeSet;
    import android.view.View;
    
    /**
     * Created by Administrator on 2015/7/14.
     */
    public class WaveBesselView extends View{
        private Paint paint;
        private Path mPath;
        private float offset = 0.0f; // 控制正弦曲线的变化
        private MyThread thread;
        private final float amplidute = 100; // 振幅
        private float gradualY; // Y方向的渐变量
        private float gradualX; // X方向的渐变量
        private boolean isMoving = true; //
        private int width, height;
    
        public WaveBesselView(Context context) {
            super(context);
            init();
        }
    
        public WaveBesselView(Context context, AttributeSet attrs) {
            super(context, attrs);
            init();
        }
    
        private void init() {
            // 初始化画笔
            paint = new Paint();
            paint.setAntiAlias(true);
            paint.setColor(Color.BLUE);
            paint.setStrokeWidth(2);
    
            // 初始化变量
            gradualX = 0.0f;
    
            // 初始化路径
            mPath = new Path();
    
            // 初始化线程
            thread = new MyThread();
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            gradualY = getMeasuredHeight() - amplidute;
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            width = getMeasuredWidth();
            height = getMeasuredHeight();
            int ave = width / 4;
    
            mPath.reset();
            mPath.moveTo(gradualX, gradualY);
            mPath.cubicTo(gradualX + 1.73f * ave, gradualY - amplidute, gradualX + width - 1.73f * ave, gradualY + amplidute, gradualX + width, gradualY);
            mPath.cubicTo(gradualX + 1.73f * ave + width, gradualY - amplidute, gradualX + 2 * width - 1.73f * ave, gradualY + amplidute, gradualX + 3 * width, gradualY);
            mPath.lineTo(width, height);
            mPath.lineTo(0, height);
            mPath.close();
            canvas.drawPath(mPath, paint);
            // 启动线程開始更新
            if (!thread.isAlive() && isMoving) {
                thread.start();
            }
        }
    
        class MyThread extends Thread {
            public void run() {
                while (isMoving) {
                    gradualX = gradualX - 1f > -width ? gradualX - 1f : gradualX - 1f + width;
                    gradualY -= 0.2;
                    if (gradualY < -amplidute) {
                        isMoving = false;
                        break;
                    }
                    try {
                        Thread.sleep(5);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    postInvalidate();
                }
            }
        }
    
    }
    


  • 相关阅读:
    在开发项目中有些常用的的实用代码(ps:平时看着无关紧要的,却很容易忘记)
    C#中Socket编程解决应用程序直接的通信
    关于textjs的tree带复选框的树
    extjs中第一次访问有效,第二次访问出现部分组件无法显示的,动态改变组件的label值的方法,ExtJs中组件最好少使用ID属性(推荐更多使用Name属性)
    ExtJS中动态设置TextField的readOnly属性
    Tomcat根目录下work文件夹的作用
    Numpy包简单介绍
    数字图像处理-傅立叶变换
    数字图像处理-边缘检测
    matplotlib的一些代码
  • 原文地址:https://www.cnblogs.com/cynchanpin/p/7159059.html
Copyright © 2011-2022 走看看