css贝塞尔曲线 多个点_贝塞尔曲线之爱心点赞代码全解析!| CSDN 博文精选

1a10029d875cbd45d40363bb34e1d6b6.gif 79ec9e34dcfd5e94257d7e9f62a173f8.png

作者 | 威威喵

责编 | 屠敏

出品 | CSDN 博客

直接步入正题,我们要实现的是一个 Android 客户端应用里面的一种点赞效果,比如你点一下那个爱心型的图片,就会产生一个小爱心,而且会以曲线的方式进行上升,直到它消失为止。

文字描述只能是这样的了,我们直接来看动态图吧,效果更直观。

1ea11f8d2fe35ee150a755150a023570.gif

本案例是由我自己写的,因为之前对这个贝塞尔曲线有一点点了解,还有无意间看到了这个效果,觉得挺赞的,就顺便写了一下demo,并且学习了一些关于贝塞尔曲线的相关知识。

首先,要看懂本案例的代码,你需要具备 Android 自定义 View 的基本知识,并且你还有了解一些关于贝塞尔曲线的公式和算法。不过没关系,我们并不需要对贝塞尔深刻了解,只要会基本的根据公式,套用代码就好了。

来看一下贝塞尔曲线的一些相关知识,我也是从大佬的博客中学习得来的。我们来看看什么是贝塞尔曲线?

贝塞尔曲线(Bézier curve),又称贝兹曲线或贝济埃曲线,是应用于二维图形应用程序的数学曲线。一般的矢量图形软件通过它来精确画出曲线,贝兹曲线由线段与节点组成,节点是可拖动的支点,线段像可伸缩的皮筋,我们在绘图工具上看到的钢笔工具就是来做这种矢量曲线的。

更形象的就直接来看动态图吧。

一阶贝塞尔曲线公式:由 P0 至 P1 的连续点, 描述的一条线段

3561bd53db189a2a61c4112049411f79.png 53ad082156008e98f58cc2f8e4aa4b20.gif

二阶贝塞尔曲线公式:曲线的切线 P0-P1、P1-P2 组成的运动轨迹

c288e1a549d4b7f316d39e5cc652f489.png ba4fe4b151b9d6ee0d509cd898038a0e.gif

三阶贝塞尔曲线公式:

b6fa0a096093f602a560447cb1e0e7bb.png 7905cae2b4334e6afa140aa7ac4664ab.gif

从上面的动态图,可以很直观的看到曲线的计算公式和它的路径形成的规律。而我们要实现的效果,运用的就是三阶贝塞尔曲线的公式。首先,需要确定曲线的路径的话,就必须先确定它的点位置。我以是这样的方式来确定点位置的,如下图:

b1794d4ca5ed88024087231e7f4c87f6.png

我使用的就是这三个点,两边都可以,随机的选择一边。这样的话,我们的曲线就在屏幕内,它的形成大致和我们上面的动态图有点类似。那么看代码:

private Point setPoint1 {

Point points = new Point{

new Point(mLoveX, mLoveY),

new Point(0, mCanvasHeight / 2),

new Point(mCanvasWidth + 20, -mLoveWidth - 10),

};

return points;

}

private Point setPoint2 {

Point points = new Point{

new Point(mLoveX, mLoveY),

new Point(mCanvasWidth, mCanvasHeight / 2),

new Point(-mLoveWidth - 20, -mLoveWidth - 10),

};

return points;

}

上面代码是初始化两种点的坐标,mLoveX,mLoveY 表示我们的爱心起始的位置。第一个集合点,对应图中的蓝线,第二个集合点,就对应橙色了。

接下来是重点部分,也就是把贝塞尔曲线公式转化为代码的形式,根据动态图中有一个 t 值,它的区间是 [0,1] 的,这个也很形象,t 从 0 变到 1 时,意味着曲线已经绘制完了。看代码:

/**

* 根据点得到曲线的路径上的点,k 是变化趋势

*/

private Point deCasteljau(Point[] points, float k) {

final int n = points.length;

for (int i = 1; i <= n; i++)

for (int j = 0; j < n - i; j++) {

points[j].x = (int) ((1 - k) * points[j].x + k * points[j + 1].x);

points[j].y = (int) ((1 - k) * points[j].y + k * points[j + 1].y);

}

return points[0];

}

刚刚我们定义的两种点的集合,就可以将它传入了,这样根据 k 值的变化,就可以得到对应位置曲线上的点坐标。接下来,我们的任务就是开启一个子线程去跟新 k 值,将 k 值有 0 加到 1,然后返回的每个 point 对象,就是整条曲线的坐标散点。执行子线程获取点的代码:

mLoveThread = new Thread(new Runnable {

@Override

public void run {

while (k < 1) {

k += 0.01;

Point point = deCasteljau(mPoints, k);

mLoveX = point.x;

mLoveY = point.y;

if (mLoveY <= -mLoveWidth || mLoveY >= mCanvasHeight) {

k = 1;

}

if (mLoveX <= -mLoveWidth || mLoveX >= mCanvasWidth) {

k = 1;

}

postInvalidate;//异步刷新

try {

Thread.sleep(80);

} catch (InterruptedException e) {

e.printStackTrace;

}

}

}

});

通过上面代码,我们就可以获取爱心图片的 x,y 坐标值了,然后再通过 onDraw 里面将它进行绘制就搞定啦。

@Override

protected void onDraw(Canvas canvas) {

super.onDraw(canvas);

mCanvasWidth = canvas.getWidth;

mCanvasHeight = canvas.getHeight;

mLoveBitmapX = mCanvasWidth / 2 - mLoveBitmapWidth / 2;

mLoveBitmapY = mCanvasHeight - 2 * mLoveBitmapHeight;

drawLoveBitmap(canvas);

canvas.drawBitmap(mDefLove, mLoveX, mLoveY, mPaint);

//随便画的

canvas.drawText("点赞

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值