Android元素分散-飘移-聚合动效

藏宝库编辑 2024-9-8 08:31:38 38 0 来自 中国
效果预览

功能阐明


  • 使用Canvas绘制元素移动动效,极致高效;
  • 支持恣意方向元素漂移(出发点、止境恣意);
  • 支持修改元素图标及其大小(单位dp);
  • 支持修改动效连续时间及动画结束时回调;
  • 支持修改元素飘动个数;
使用方式


  • 在工程根目录的build.gradle中添加
allprojects {    repositories {        maven { url 'https://www.jitpack.io' }        ...    }}

  • 添加依赖
implementation 'com.gitee.chockqiu:animation-views:1.1'

  • 在xml中添加结构
<com.chockqiu.view.ElementFloatTogetherAnimation        android:layout_width="match_parent"        android:layout_height="match_parent" />

  • 确定出发点及止境,开始动画&处置惩罚回调
val p0 = Point().apply {    x = (viewStart.left + viewStart.right) / 2    y = (viewStart.top + viewStart.bottom) / 2}val p1 = Point().apply {    x = (endView.left + endView.right) / 2    y = (endView.top + endView.bottom) / 2}mElement.startAnimation(p0, p1) {    ...}
PS: 为了起/止境坐标与预期划一,发起将View放置在跟出发点止境View同一个ViewGroup中,而且动效View的宽高与ViewGroup划一,也就是match_parent(动效内部坐标系是以自身左上角为坐标原点举行绘制的),如不划一须要举行坐标转换。
实现原理

使用二阶贝塞尔曲线控制点决定曲线路径的特性,通过算法天生每一个元素的控制点,实现差别元素通过差别的路径从出发点飘向止境,再加上差别元素移动动画开始的时间差,终极组合实现这么一种效果。
二阶贝塞尔曲线原理图如下:

实现步骤

1)实现二阶贝塞尔曲线数学公式;

具体实现详见quadToFunValue(float t, Point p0, Point p1, Point p2)函数。


2)通过算法天生每个元素的控制点,为了悦目控制点需在出发点与止境地点直线的中垂线上随机分布;
以是终极控制点是一个与中点M(Mx,My)间隔为D的坐标,且它地点的直线是出发点与止境地点直线的中垂线。
4.png 如何盘算控制点坐标呢?
起首通过出发点止境地点的直线可以盘算出中垂线的斜率k2:
private double centerk(Point a, Point b) {    //已知A(Ax,Ay),B(Bx,By); 中垂线的斜率为:    //-1/k=-1/[(By-Ay)/(Bx-Ax)]=-(Bx-Ax)/(By-Ay)    if (b.y == a.y) {        return 0;    }    if (b.x == a.x) {        return Double.MAX_VALUE;    }    return -(((b.x - a.x) * 1f / (b.y - a.y)));}已知随机简直定正值D,可以盘算出控制点与坐标中点M(Mx,My)的坐标间隔dx和dy, 数学公式如下:
等式1: dy/dx = k2
等式2: dx*dx + dy*dy = D*D
只要出发点/止境确认, 则k1是一个定值,那么它的中垂线斜率k2也是定值,再加上随机的正值D,颠末转换可得
dx = D*D/(k2*k2+1)
dy = (D*D*k2*k2)/(k2*k2+1)
/** * 斜率k时间隔d对应的dx值 * * @param k 斜率k * @param d 间隔d * @return */private double dx(double k, double d) {    if (k == 0) {        return 0;    }    if (k == Double.MAX_VALUE) {        return d;    }    double dx = Math.sqrt((d * d) / (k * k + 1));    if (d < 0) {        return -dx;    } else {        return dx;    }}/** * 斜率k时间隔d对应的dy值 * * @param k 斜率k * @param d 间隔d * @return */private double dy(double k, double d) {    if (k == 0) {        return d;    }    if (k == Double.MAX_VALUE) {        return 0;    }    double dy = Math.sqrt((d * d) * (k * k) / (k * k + 1));    if (d < 0) {        return -dy;    } else {        return dy;    }}在根据出发点(Sx,Sy)、止境(Ex,Ey)的朝向差别,确定dx与dy的符号,大概是-dx,-dy,也大概是dx,-dy等等
终极得到控制点的准确坐标值;
5.png

如果本文对你有资助就点个赞支持下吧~~~
您需要登录后才可以回帖 登录 | 立即注册

Powered by CangBaoKu v1.0 小黑屋藏宝库It社区( 冀ICP备14008649号 )

GMT+8, 2024-11-22 04:33, Processed in 0.172723 second(s), 35 queries.© 2003-2025 cbk Team.

快速回复 返回顶部 返回列表