笔者是面霸,面试200+场 当过考官:面过别人300+场 去过500强,也呆过初创公司。
从月薪3000到年薪60万。从专科生到深圳一线大厂。关注我就能达到大师级水平,这话我终于敢说了, 年薪60万不是梦!
动画描述
拖动气泡,有一条线,然后到一定程度消失
1.先绘制一个固定圆
2.实现固定圆拖动
3.绘制拖动圆
4.固定圆和拖动圆,中间的贝塞尔: 一阶贝塞尔:quote to 手动计算坐标。得到控制点
5.动画爆炸消失:
动画实现:
2.1.1: 手指按下拖动的时候有一个拖拽的圆这个圆的半径是不会变化的但是位置会随着手指移动;
2.1.2: 手指按下拖动的时候有一个固定的圆这个圆的是会变化的但是位置不会变化,圆的半径取决于两个圆的距离,两个圆的距离越大圆半径越小,距离越小圆半径越大;
2.1.2: 两个圆之间有一个不规则的东西将两个圆连在一起感觉像粘液一样,这就是大家所说的贝塞尔效果。
用到的东西
1.拖动view
2.x坐标 :屏幕坐标和控件坐标
3.贝塞尔曲线公式
4.拖动的时候距离远,越小
mFixationRadius =FIXATION_RADIUS_MAX - distance /14;//距离越远,圆越小,值如果太小或者为负数是看不到的
拖动实现
public void updateDragPoint(float x, float y) {
mDragPoint.x = x;
mDragPoint.y = y;
invalidate();
}
public class MessageBubbleViewextends View {
public MessageBubbleView(Context context) {
this(context, null);
}
public MessageBubbleView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
init();
this.context = context;
}
private Paintpaint;
private void init() {
paint =new Paint();
paint.setColor(Color.RED);
mDragRadius = dip2px(mDragRadius);
mFixationRadius = dip2px(mFixationRadius);
FIXATION_RADIUS_MAX = dip2px(FIXATION_RADIUS_MAX);
}
private PointFmFixPoint;
private PointFmDragPoint;
int mDragRadius =15;
int mFixationRadius =10;
// 固定圆的最大半径
int FIXATION_RADIUS_MAX =7;
int FIXATION_RADIUS_MIN =3;
Contextcontext;
public MessageBubbleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mDragPoint ==null ||mFixPoint ==null) {
return;
}
paint.setColor(Color.RED);
//绘制触摸的那个圆
canvas.drawCircle(mDragPoint.x, mDragPoint.y, mDragRadius, paint);
int distance = BubbleUtils.getDistance(mDragPoint, mFixPoint);
mFixationRadius =FIXATION_RADIUS_MAX - distance /14;//距离越远,圆越小,值如果太小或者为负数是看不到的
Log.d("MessageBubbleView", "mFixationRadius :" +mFixationRadius);
//绘制另外一个圆
if (mFixationRadius >FIXATION_RADIUS_MIN) {
canvas.drawCircle(mFixPoint.x, mFixPoint.y, mFixationRadius, paint);
}
paint.setColor(Color.BLUE);
Path path = getBezierPath();
if (path !=null) {
canvas.drawPath(path, paint);
}
if (dragBitmap !=null) {//拖动的时候图片移动有问题,说明是图片的绘制地方有问题,拖动的坐标。(当前点的x-图片宽度的一半,当前点的y-图片高度的一半)
canvas.drawBitmap(dragBitmap, mDragPoint.x -dragBitmap.getWidth() /2, mDragPoint.y -dragBitmap.getHeight() /2, null);//截屏的原理,paint=null
}
}
/**
* 获取 Bezier 曲线
*
* @return
*/
public PathgetBezierPath() {
if (mFixationRadius
return null;
}
Path bezierPath =new Path();
// 贝塞尔曲线怎么求?
// 计算斜率
float dx =mFixPoint.x -mDragPoint.x;
float dy =mFixPoint.y -mDragPoint.y;
if (dx ==0) {
dx =0.001f;
}
float tan = dy / dx;
// 获取角a度值
float arcTanA = (float) Math.atan(tan);
// 依次计算 p0 , p1 , p2 , p3 点的位置
float P0X = (float) (mFixPoint.x +mFixationRadius * Math.sin(arcTanA));
float P0Y = (float) (mFixPoint.y -mFixationRadius * Math.cos(arcTanA));
float P1X = (float) (mDragPoint.x +mDragRadius * Math.sin(arcTanA));
float P1Y = (float) (mDragPoint.y -mDragRadius * Math.cos(arcTanA));
float P2X = (float) (mDragPoint.x -mDragRadius * Math.sin(arcTanA));
float P2Y = (float) (mDragPoint.y +mDragRadius * Math.cos(arcTanA));
float P3X = (float) (mFixPoint.x -mFixationRadius * Math.sin(arcTanA));
float P3Y = (float) (mFixPoint.y +mFixationRadius * Math.cos(arcTanA));
// 求控制点 两个点的中心位置作为控制点
PointF controlPoint = BubbleUtils.getPointByPercent(mDragPoint, mFixPoint, 0.5f);
// 整合贝塞尔曲线路径
bezierPath.moveTo(P0X, P0Y);
bezierPath.quadTo(controlPoint.x, controlPoint.y, P1X, P1Y);
bezierPath.lineTo(P2X, P2Y);
bezierPath.quadTo(controlPoint.x, controlPoint.y, P3X, P3Y);
bezierPath.close();
return bezierPath;
}
扩展:实现任意控件都可以拖动爆炸
网友评论