SVID_20241010_155047_1

效果图

实现思路,在触摸事件中设置定时存储坐标点,通过坐标点的集合生成贝塞尔曲线显示在自定义View中

package com.plattysoft.leonids.bezierdemo;

import static java.lang.Double.NaN;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.graphics.BlurMaskFilter;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Shader;
import android.os.Handler;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateInterpolator;

import com.plattysoft.leonids.bezierdemo.leonids.ParticleSystem;

import java.util.LinkedList;
import java.util.Queue;

//尾迹
public class MainCanvas2 extends View {
    private ParticleSystem ps;
    private Context mContext;
    private Activity activity;
    private Paint mPaintMouse;
    private Paint mPaintTails;//鼠标拖尾画笔
    private final int strokeWidth = 280;
    boolean mouse_begin = false;//鼠标是否按下
    private Path pathBackground = new Path();
    private float mouseCurrentX = 0;//当前鼠标位置X
    private float mouseCurrentY = 0;//当前鼠标位置Y
    private float mouseLastX = 0;//
    private float mouseLastY = 0;//
    Queue<Float> mouseX = new LinkedList<Float>();//保存鼠标轨迹X
    Queue<Float> mouseY = new LinkedList<Float>();//保存鼠标轨迹Y

    private int time = 0;//累加时间

    int startColor = Color.argb(0, 69, 174, 161);
    int endColor = Color.argb(100, 69, 174, 161);
    int circleBigColor = Color.argb(255, 255, 255, 255);
    int circleSmallColor = Color.argb(255, 69, 174, 161);
    int tailsColor = Color.argb(255, 64, 224, 208);

    Handler handler = new Handler();
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            time++;
            invalidate();//告诉主线程重新绘制
            if (mouseX.peek() != null) {
                boolean is_add_mouse = Math.abs(mouseX.peek() - mouseCurrentX) < 0.01;//鼠标不动时不记录坐标
                if (!is_add_mouse) {
                    mouseX.offer(mouseCurrentX);
                    mouseY.offer(mouseCurrentY);
                }
                if (mouseX.size() > 10 || is_add_mouse) {
                    mouseX.poll();
                    mouseY.poll();
                }
            } else if (mouse_begin) {
                mouseX.offer(mouseCurrentX);
                mouseY.offer(mouseCurrentY);
            }
            handler.postDelayed(this, 2);//每20ms循环一次,50fps
        }
    };

    public MainCanvas2(Context context) {
        super(context);
    }

    public MainCanvas2(Context context, AttributeSet attrs) {
        super(context, attrs);
        handler.postDelayed(runnable, 20);
        mPaintMouse = new Paint();//对画笔初始化
        mPaintTails = new Paint();//对画笔初始化
        resetPaintMouse(circleBigColor);
        resetPaintTails(tailsColor);
        mContext = context;
        activity = (Activity) context;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {//设置触摸事件,手指按下进行记录,手指抬起停止记录
        mouseCurrentX = event.getX();
        mouseCurrentY = event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mouse_begin = true;

                ps = new ParticleSystem(activity, 90, R.drawable.icon_leonids, 200);
                ps.setScaleRange(1.7f, 1.3f);
                ps.setSpeedRange(0.05f, 0.1f);
                ps.setRotationSpeedRange(290, 280);
                ps.setFadeOut(200, new AccelerateInterpolator());
                ps.emit((int) event.getX(), (int) event.getY(), 80);
                break;
            case MotionEvent.ACTION_MOVE:
                ps.updateEmitPoint((int) event.getX(), (int) event.getY());
                break;
            case MotionEvent.ACTION_UP:
                mouse_begin = false;
                endX = 0;
                endY = 0;

                ps.stopEmitting();
                break;
        }
        return true;
    }

    private float startX = 0, startY = 0;
    private float endX = 0, endY = 0;
    private float degrees;

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        int size = mouseX.size();
        if (size == 0) {
            startX = 0;
            startY = 0;
            endX = 0;
            endY = 0;
        }

        pathBackground.reset();
        float x1 = 0, x2 = 0, y1 = 0, y2 = 0;
        for (int i = 0; i < size; i++) {
            float percent = (float) i / size;
            float res[] = Bezier.bezier((LinkedList) mouseX, (LinkedList) mouseY, percent);
            x1 = res[0];
            y1 = res[1];
            if (i == 0) {
                x2 = x1;
                y2 = y1;
                startX = x1;
                startY = y1;
                pathBackground.moveTo(x1, y1);
                continue;
            }
            BlurMaskFilter blurMaskFilter = new BlurMaskFilter(10, BlurMaskFilter.Blur.NORMAL);
            mPaintTails.setMaskFilter(blurMaskFilter);
            mPaintTails.setStrokeWidth((int)(percent * 20));
            canvas.drawLine(x1, y1, x2, y2, mPaintTails);
            if (Math.abs(x1 - x2) > 5 || Math.abs(y1 - y2) > 5) {
                pathBackground.lineTo(x1, y1);
            }
            x2 = x1;
            y2 = y1;

            if (i == size - 2) {
                mouseLastX = x1;
                mouseLastY = y1;
            }
            if (i == size - 1) {
                endX = x1;
                endY = y1;
//                Log.e("YinTest_","endX ="+endX+",endY ="+endY);
//                Log.e("YinTest_","mouseCurrentX ="+mouseCurrentX+",mouseCurrentY ="+mouseCurrentY);
                degrees = (float) Math.toDegrees(Math.atan2((mouseCurrentY - endY), (mouseCurrentX - endX)));
                pathBackground.lineTo(mouseCurrentX, mouseCurrentY);
            }
        }


        if (mouse_begin) {
            @SuppressLint("DrawAllocation")
            Shader shader = new LinearGradient(startX, startY, endX, endY, startColor, endColor, Shader.TileMode.CLAMP);
            mPaintMouse.setShader(shader);
            mPaintMouse.setStyle(Paint.Style.STROKE);
            BlurMaskFilter blurMaskFilter = new BlurMaskFilter(10, BlurMaskFilter.Blur.NORMAL);
            mPaintMouse.setMaskFilter(blurMaskFilter);
            canvas.drawPath(pathBackground, mPaintMouse);

            float dx = Math.abs(endX - startX);
            float dy = Math.abs(endY - startY);
            float distance = (float) Math.sqrt(dx * dx + dy * dy);
            Log.e("YinTest_", ",distance =" + distance + ",startX =" + startX + ",startY =" + startY + ",endX =" + endX + ",endY =" + endY);
            if (NaN != degrees) {
                resetPaintMouse(endColor);
                mPaintMouse.setMaskFilter(blurMaskFilter);
                float sweepAngle = 180;
                if (endX == 0 || distance > 500 || distance < 100) {
                    sweepAngle = 360;
                }

                float left = mouseCurrentX - strokeWidth / 2;
                float top = mouseCurrentY - strokeWidth / 2;
                RectF rectF = new RectF(left, top, strokeWidth + left, strokeWidth + top);
                canvas.drawArc(rectF, degrees - 90, sweepAngle, true, mPaintMouse); // 绘制半圆
            }

        }

        resetPaintMouse(circleBigColor);
        canvas.drawCircle(mouseCurrentX, mouseCurrentY, strokeWidth / 3f, mPaintMouse);

        resetPaintMouse(circleSmallColor);
        canvas.drawCircle(mouseCurrentX, mouseCurrentY, strokeWidth / 4f, mPaintMouse);
    }

    private void resetPaintMouse(int color) {
        mPaintMouse.reset();
        mPaintMouse.setColor(color);
        mPaintMouse.setStrokeWidth(strokeWidth);
    }
    private void resetPaintTails(int color) {
        mPaintTails.reset();
        mPaintTails.setColor(color);
        mPaintTails.setStrokeWidth(10);
    }
}

完成Demo

https://download.csdn.net/download/y280903468/89871386

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部