自定义控件三部曲之绘图篇(六)——Path之贝赛尔曲线和手势轨迹、水波纹效果

前言:好想义无反顾地追逐梦想

相关文章:
《Android自定义控件三部曲文章索引》http://blog.csdn.net/harvic880925/article/details/50995268


从这篇开始,我将延续androidGraphics系列文章把图片相关的知识给大家讲完,这一篇先稍微进阶一下,给大家把《android Graphics(二):路径及文字》略去的quadTo(二阶贝塞尔)函数,给大家补充一下。
本篇最终将以两个例子给大家演示贝塞尔曲线的强大用途:
1、手势轨迹

利用贝塞尔曲线,我们能实现平滑的手势轨迹效果
2、水波纹效果

电池充电时,有些手机会显示水波纹效果,就是这样做出来的。
废话不多说,开整吧

一、概述

《android Graphics(二):路径及文字》中我们略去了有关所有贝赛尔曲线的知识,在Path中有四个函数与贝赛尔曲线有关:

 

//二阶贝赛尔
public void quadTo(float x1, float y1, float x2, float y2)
public void rQuadTo(float dx1, float dy1, float dx2, float dy2)
//三阶贝赛尔
public void cubicTo(float x1, float y1, float x2, float y2,float x3, float y3)
public void rCubicTo(float x1, float y1, float x2, float y2,float x3, float y3)

这里的四个函数的具体意义我们后面会具体详细讲解,我们这篇也就是利用这四个函数来实现我们的贝赛尔曲线相关的效果的。

 

1、贝赛尔曲线来源

在数学的数值分析领域中,贝赛尔曲线(Bézier曲线)是电脑图形学中相当重要的参数曲线。更高维度的广泛化贝塞尔曲线就称作贝塞尔曲面,其中贝塞尔三角是一种特殊的实例。
贝塞尔曲线于1962年,由法国工程师皮埃尔·贝塞尔(Pierre Bézier)所广泛发表,他运用贝塞尔曲线来为汽车的主体进行设计。贝塞尔曲线最初由Paul de Casteljau于1959年运用de Casteljau算法开发,以稳定数值的方法求出贝塞尔曲线。

2、贝赛尔曲线公式

这部分是很有难度的,大家做好准备了哦

一阶贝赛尔曲线

其公式可概括为:

对应动画演示为:

P0为起点、P1为终点,t表示当前时间,B(t)表示公式的结果值。
注意,曲线的意义就是公式结果B(t)随时间的变化,其取值所形成的轨迹。在动画中,黑色点表示在当前时间t下公式B(t)的取值。而红色的那条线就不在各个时间点下不同取值的B(t)所形成的轨迹。
总而言之:对于一阶贝赛尔曲线,大家可以理解为在起始点和终点形成的这条直线上,匀速移动的点。

二阶贝赛尔曲线

同样,先来看看二阶贝赛尔曲线的公式(虽然看不懂,呵呵)

大家也不用研究这个公式了,没一定数学功底也研究不出来了啥,咱还是看动画吧

在这里P0是起始点,P2是终点,P1是控制点
假设将时间定在t=0.25的时刻,此时的状态如下图所示:

首先,P0点和P1点形成了一条贝赛尔曲线,还记得我们上面对一阶贝赛尔曲线的总结么:就是一个点在这条直线上做匀速运动;所以P0-P1这条直线上的移动的点就是Q0;
同样,P1,P2形成了一条一阶贝赛尔曲线,在这条一阶贝赛尔曲线上,它们的随时间移动的点是Q1
最后,动态点Q0和Q1又形成了一条一阶贝赛尔曲线,在它们这条一阶贝赛尔曲线动态移动的点是B
而B的移动轨迹就是这个二阶贝赛尔曲线的最终形态。从上面的讲解大家也可以知道,之所以叫它二阶贝赛尔曲线是因为,B的移动轨迹是建立在两个一阶贝赛尔曲线的中间点Q0,Q1的基础上的。
在理解了二阶贝赛尔曲线的形成原理以后,我们就不难理解三阶贝赛尔曲线了

三阶贝赛尔曲线

同样,先列下基本看不懂的公式

这玩意估计也看不懂,讲了也没什么意义,还是结合动画来吧

同样,我们取其中一点来讲解轨迹的形成原理,当t=0.25时,此时状态如下:

同样,P0是起始点,P3是终点;P1是第一个控制点,P2是第二个控制点;
首先,这里有三条一阶贝赛尔曲线,分别是P0-P1,P1-P2,P2-P3;
他们随时间变化的点分别为Q0,Q1,Q2
然后是由Q0,Q1,Q2这三个点,再次连接,形成了两条一阶贝赛尔曲线,分别是Q0—Q1,Q1—Q2;他们随时间变化的点为R0,R1
同样,R0和R1同样可以连接形成一条一阶贝赛尔曲线,在R0—R1这条贝赛尔曲线上随时间移动的点是B
而B的移动轨迹就是这个三阶贝赛尔曲线的最终形状。
从上面的解析大家可以看出,所谓几阶贝赛尔曲线,全部是由一条条一阶贝赛尔曲线搭起来的;
在上图中,形成一阶贝赛尔曲线的直线是灰色的,形成二阶贝赛尔曲线线是绿色的,形成三阶贝赛尔曲线的线是蓝色的。
在理解了上面的二阶和三阶贝赛尔曲线以后,我们再来看几个贝赛尔曲线的动态图

四阶贝赛尔曲线

五阶贝赛尔曲线

这里就不再一一讲解形成原理了,大家理解了二阶和三阶贝赛尔曲线以后,这两条的看看就好了,想必大家也是能自己推出四阶贝赛尔曲线的形成原理的。

3、贝赛尔曲线与PhotoShop钢笔工具

如果有些同学不懂PhotoShop,这篇文章可能就会有些难度了,本篇文章主要是利用PhotoShop的钢笔工具来得出具体贝塞尔图像的
这么屌的贝赛尔曲线,在专业绘图工具PhotoShop中当然会有它的踪影,它就是钢笔工具,钢笔工具所使用的路径弯曲效果就是二阶贝赛尔曲线。
我来给大家演示一下钢笔工具的用法:

我们拿最终成形的图形来看一下为什么钢笔工具是二阶贝赛尔曲线:

右图演示的假设某一点t=0.25时,动态点B的位置图
同样,这里P0是起始点,P2是终点,P1是控制点;
P0-P1、P1-P2形成了第一层的一阶贝赛尔曲线。它们随时间的动态点分别是Q0,Q1
动态点Q0,Q1又形成了第二层的一阶贝赛尔曲线,它们的动态点是B.而B的轨迹跟钢笔工具的形状是完全一样的。所以钢笔工具的拉伸效果是使用的二阶贝赛尔曲线!
这个图与上面二阶贝赛尔曲线t=0.25时的曲线差不多,大家理解起来难度也不大。
这里需要注意的是,我们在使用钢笔工具时,拖动的是P5点。其实二阶贝赛尔曲线的控制点是其对面的P1点,钢笔工具这样设计是当然是因为操作起来比较方便。
好了,对贝赛尔曲线的知识讲了那么多,下面开始实战了,看在代码中,贝赛尔曲线是怎么来做的。

二、Android中贝赛尔曲线之quadTo

在开篇中,我们已经提到,在Path类中有四个方法与贝赛尔曲线相关,分别是:

 

//二阶贝赛尔
public void quadTo(float x1, float y1, float x2, float y2)
public void rQuadTo(float dx1, float dy1, float dx2, float dy2)
//三阶贝赛尔
public void cubicTo(float x1, float y1, float x2, float y2,float x3, float y3)
public void rCubicTo(float x1, float y1, float x2, float y2,float x3, float y3)

在这四个函数中quadTo、rQuadTo是二阶贝赛尔曲线,cubicTo、rCubicTo是三阶贝赛尔曲线;我们这篇文章以二阶贝赛尔曲线的quadTo、rQuadTo为主,三阶贝赛尔曲线cubicTo、rCubicTo用的使用方法与二阶贝赛尔曲线类似,用处也比较少,这篇就不再细讲了。

 

1、quadTo使用原理

这部分我们先来看看quadTo函数的用法,其定义如下:

public void quadTo(float x1, float y1, float x2, float y2)

参数中(x1,y1)是控制点坐标,(x2,y2)是终点坐标

  • 103
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 79
    评论
要实现加入购物车飞入动画,可以使用贝塞尔曲线来控制动画路径。具体实现步骤如下: 1. 在购买按钮点击事件中,获取购买按钮的位置和购物车图标的位置,并计算出两者之间的距离。 2. 创建一个贝塞尔曲线,控制点设置为购买按钮位置和购物车图标位置的中心点,终点设置为购物车图标位置。 3. 使用CSS3动画或JavaScript来实现动画效果,让购买按钮沿着贝塞尔曲线飞入购物车。 下面是一个简单的实现示例: ```html <template> <div> <button @click=&quot;addToCart&quot;>加入购物车</button> <div class=&quot;cart-icon&quot;></div> <div class=&quot;ball&quot;></div> </div> </template> <script> export default { methods: { addToCart() { const button = document.querySelector('button') const cartIcon = document.querySelector('.cart-icon') const ball = document.querySelector('.ball') const buttonRect = button.getBoundingClientRect() const cartIconRect = cartIcon.getBoundingClientRect() const deltaX = cartIconRect.left - buttonRect.left const deltaY = cartIconRect.top - buttonRect.top const controlPointX = (buttonRect.left + cartIconRect.left) / 2 const controlPointY = buttonRect.top - 100 ball.style.left = buttonRect.left + 'px' ball.style.top = buttonRect.top + 'px' const bezierPath = `M${buttonRect.left},${buttonRect.top} Q${controlPointX},${controlPointY} ${cartIconRect.left},${cartIconRect.top}` ball.animate( [ { transform: `translate(0,0)` }, { transform: `translate(${deltaX}px, ${deltaY}px)` } ], { duration: 500, easing: 'ease-out', fill: 'forwards' } ) ball.animate( [ { transform: `translate(${deltaX}px, ${deltaY}px)` }, { transform: `translate(0,0)` } ], { duration: 500, easing: 'ease-in', fill: 'forwards', delay: 500 } ) ball.animate( [ { opacity: 1 }, { opacity: 0 } ], { duration: 500, fill: 'forwards', delay: 1000 } ) const path = document.createElementNS('http://www.w3.org/2000/svg', 'path') path.setAttribute('d', bezierPath) path.setAttribute('fill', 'none') path.setAttribute('stroke', 'red') path.setAttribute('stroke-width', '2') document.querySelector('.container').appendChild(path) } } } </script> <style> .cart-icon { position: absolute; top: 20px; right: 20px; width: 50px; height: 50px; background: url('cart.png'); background-size: cover; } .ball { position: absolute; width: 20px; height: 20px; border-radius: 50%; background: red; } .container { position: relative; } </style> ``` 这里使用了CSS3动画和JavaScript动画结合的方式来实现购买按钮飞入购物车的效果。在addToCart方法中,首先获取购买按钮和购物车图标的位置,并计算出两者之间的距离。然后根据贝塞尔曲线的控制点计算出贝塞尔曲线路径,并创建一个SVG path元素来显示路径。最后使用CSS3动画和JavaScript动画来实现购买按钮沿着贝塞尔曲线飞入购物车的效果
评论 79
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值