美文网首页
Android 绘制水波纹小球球

Android 绘制水波纹小球球

作者: 带带我 | 来源:发表于2021-03-12 11:55 被阅读0次
    1615521127828.gif
    public class BezierCurvePercentView extends View {
    
        //外圈
        private Paint paintOutside;
        private int paintOutsideColor = Color.parseColor("#FD6F5C");
        //背景色
        private Paint paintBg;
        private int paintBgColor = Color.parseColor("#F4F4F4");
        //已使用百分比
        private Paint paintPercent;
        private int paintPercentColor = Color.parseColor("#FD6F5C");
        private Path percentPath;
        //文本
        private Paint paintText;
        private int paintTextColor = Color.parseColor("#ffffff");
        private float percent = 0.3f;
    
        /**
         * 波纹的长度
         */
        private int WAVE_LENGTH = 300;
    
        /**
         * 波纹的高度
         */
        private final static int WAVE_HEGHT = 20;
        private PorterDuffXfermode mMode = new PorterDuffXfermode(PorterDuff.Mode.SRC_IN);
    
        private int viewWidth;
        private int viewHeight;
        private int dx;
    
        public BezierCurvePercentView(Context context) {
            super(context);
        }
    
        public BezierCurvePercentView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            paintOutside = new Paint();
            paintOutside.setAntiAlias(true);
            paintOutside.setColor(paintOutsideColor);
            paintOutside.setStrokeWidth(3f);
            paintOutside.setStyle(Paint.Style.STROKE);
    
            paintBg = new Paint();
            paintBg.setAntiAlias(true);
            paintBg.setColor(paintBgColor);
            paintBg.setStyle(Paint.Style.FILL);
    
            paintPercent = new Paint();
            paintPercent.setAntiAlias(true);
            paintPercent.setColor(paintPercentColor);
            paintPercent.setStyle(Paint.Style.FILL);
            percentPath = new Path();
    
            paintText = new Paint();
            paintText.setAntiAlias(true);
            paintText.setColor(paintTextColor);
            paintText.setStrokeWidth(2f);
            paintText.setTextSize(100);
            paintText.setStyle(Paint.Style.FILL);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            viewWidth = MeasureSpec.getSize(widthMeasureSpec);
            viewHeight = MeasureSpec.getSize(heightMeasureSpec);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            int layerId = canvas.saveLayer(0, 0, viewWidth, viewHeight, null, Canvas.ALL_SAVE_FLAG);
    
            canvas.drawCircle(viewWidth/2, viewHeight/2, viewWidth/2-2, paintOutside);
            canvas.drawCircle(viewWidth/2, viewHeight/2, viewWidth/2-3, paintBg);
    
            percentPath.reset();
            percentPath.moveTo( -WAVE_LENGTH + dx, (1-percent)*viewHeight);
            for (int i = -WAVE_LENGTH; i < getWidth() + WAVE_LENGTH; i += WAVE_LENGTH) {
                percentPath.rQuadTo(WAVE_LENGTH / 4, -WAVE_HEGHT, WAVE_LENGTH / 2, 0);
                percentPath.rQuadTo(WAVE_LENGTH / 4, WAVE_HEGHT, WAVE_LENGTH / 2, 0);
            }
            percentPath.lineTo(viewWidth, viewHeight);
            percentPath.lineTo(0, viewHeight);
            percentPath.close();
    
            paintPercent.setXfermode(mMode);
            canvas.drawPath(percentPath, paintPercent);
    
            paintPercent.setXfermode(null);
    
            Rect rect = new Rect();
            String textStr = (int)(percent*100) + "%";
            paintText.getTextBounds(textStr, 0, textStr.length(), rect);
            canvas.drawText(textStr, viewWidth/2 - rect.width()/2, viewHeight/2 + rect.height()/2, paintText);
            canvas.restoreToCount(layerId);
        }
    
        public void setPercent(float percent){
            this.percent = percent;
            ValueAnimator mValueAnimator = ValueAnimator.ofInt(0, WAVE_LENGTH);
            mValueAnimator.setDuration(2000);
            mValueAnimator.setRepeatCount(ValueAnimator.INFINITE);
            // 动画插值器,也可以使用其他
            mValueAnimator.setInterpolator(new LinearInterpolator());
            mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    dx = ( int ) animation.getAnimatedValue();
                    invalidate();
                }
            });
            mValueAnimator.start();
        }
    }
    

    二阶贝塞尔曲线的两个方法 quadTo 与 rQuadTo

    path.moveTo(x, y);
    quadTo(x1, y1, x2, y2);
    quadTo(x3, y3, x4, y4);
    此方法中的每个坐标是相对起点的坐标,即 x1-x = x2-x1 = x3-x2 = x4-x3;
    
    path.moveTo(x, y);
    rQuadTo(x1, y1, x2, y2);
    rQuadTo(x3, y3, x4, y4);
    
    此方法中的每个坐标是相对上一个点的坐标,假设起点是(0, 0),波长是100,波高度20,则:
    
    path.moveTo(0, 0);
    rQuadTo(100/4, 20,100/2, 0);
    ↓↓↓第二段曲线 (x,y)把上一个点看做(0, 0)即相对上一个点X位移量为1/4波长=100/4,Y减少波高度20
    rQuadTo(100/4, -20, 100/2, 0);
    

    完整曲线共5个点,如下图:
    path.moveTo(起点x, 起点y);
    quadTo(Ax, Ay, Bx, By);
    quadTo(Cx, Cy, Dx, Dy);


    二阶贝塞尔.jpg

    相关文章

      网友评论

          本文标题:Android 绘制水波纹小球球

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