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
本站资源均来自互联网,仅供研究学习,禁止违法使用和商用,产生法律纠纷本站概不负责!如果侵犯了您的权益请与我们联系!
转载请注明出处: 免费源码网-免费的源码资源网站 » Android实现触摸跟随彗星拖尾效果
发表评论 取消回复