html5如何在Canvas中实现自定义路径动画示例


Posted in HTML / CSS onSeptember 18, 2017

在最近的项目中笔者需要做一个新需求:在canvas中实现自定义的路径动画。这里所谓的自定义路径不单单包括一条直线,也许是多条直线的运动组合,甚至还包含了贝塞尔曲线,因此,这个动画也许是下面这个样子的:

html5如何在Canvas中实现自定义路径动画示例

那么如何才能在canvas中实现这种动画效果呢?其实很简单,对于路径的处理svg非常在行,因此在canvas中实现自定义路径动画,我们需要借助svg的力量。

创建Path

制作动画前,先要拿到动画的路径,对此我们可以直接使用svg的path定义规则,比如我们定义了一条较为复杂的路径(它到底长什么样大家可以自己试试,这里就不展示了),然后,我们需要将定义好的路径导入进一个新生成的path元素中(我们只是借助svg的api,因此并不需要将其插到页面内)

const path = 'M0,0 C8,33.90861 25.90861,16 48,16 C70.09139,16 88,33.90861 88,56 C88,78.09139 105.90861,92 128,92 C150.09139,92 160,72 160,56 C160,40 148,24 128,24 C108,24 96,40 96,56 C96,72 105.90861,92 128,92 C154,93 168,78 168,56 C168,33.90861 185.90861,16 208,16 C230.09139,16 248,33.90861 248,56 C248,78.09139 230.09139,96 208,96 L48,96 C25.90861,96 8,78.09139 8,56 Z';

const pathElement = document.createElementNS('http://www.w3.org/2000/svg',"path"); 
pathElement.setAttributeNS(null, 'd', path);

getTotalLength与getPointAtLength

SVGPathElement提供的这两个api很关键,可以说它是实现路径动画的最为核心的地方(在svg内实现自定义路径动画一般也是通过这两个api去解决)详情请戳:SVGPathElement MDN

getTotalLength方法可以获取SVGPathElement的总长度

getPointAtLength方法,传入一个长度x,将返回距离SVGPathElement起点的长度为x的终点坐标。

利用这两个api,通过循环的方式不断去更新canvas内所绘制的图形坐标,即可实现路径动画:

const length = pathElement.getTotalLength();
const duration = 1000; // 动画总时长
const interval = length / duration;
const canvas = document.querySelector('canvas');
const context = canvas.getContext('2d');
let time = 0, step = 0; 

const timer = setInterval(function() {
  if (time <= duration) {
    const x = parseInt(pathElement.getPointAtLength(step).x);
    const y = parseInt(pathElement.getPointAtLength(step).y);
    move(x, y);  // 更新canvas所绘制图形的坐标
    step++;
  } else {
    clearInterval(timer)
  }
}, interval);

function move(x, y) {
   context.clearRect(0, 0, canvas.width, canvas.height);
   context.beginPath();
   context.arc(x, y, 25, 0, Math.PI*2, true);
   context.fillStyle = '#f0f';
   context.fill();
   context.closePath();
}

最后,我们把它封装一下,即可实现一个在canvas中实现自定义动画的简易函数啦:

function customizePath(path, func) {
    const pathElement = document.createElementNS('http://www.w3.org/2000/svg',"path"); 
    pathElement.setAttributeNS(null, 'd', path);
      const length = pathElement.getTotalLength();
    const duration = 1000; 
    const interval = length / duration;
    let time = 0, step = 0; 
  
      const timer = setInterval(function() {
        if (time <= duration) {
              const x = parseInt(pathElement.getPointAtLength(step).x);
              const y = parseInt(pathElement.getPointAtLength(step).y);
              func(x, y);
              step++;
        } else {
              clearInterval(timer)
        }
     }, interval);
}

const path = 'M0,0 C8,33.90861 25.90861,16 48,16 C70.09139,16 88,33.90861 88,56 C88,78.09139 105.90861,92 128,92 C150.09139,92 160,72 160,56 C160,40 148,24 128,24 C108,24 96,40 96,56 C96,72 105.90861,92 128,92 C154,93 168,78 168,56 C168,33.90861 185.90861,16 208,16 C230.09139,16 248,33.90861 248,56 C248,78.09139 230.09139,96 208,96 L48,96 C25.90861,96 8,78.09139 8,56 Z';
const canvas = document.querySelector('canvas');
const context = canvas.getContext('2d');
function move(x, y) {
      context.clearRect(0, 0, canvas.width, canvas.height);
    context.beginPath();
      context.arc(x, y, 25, 0, Math.PI*2, true);
      context.fillStyle = '#f0f';
      context.fill();
      context.closePath();
}
customizePath(path, move);

实现思路大致如上所述,然而这并不是最终成果。当我们决定要在canvas制作自定义路径动画时,我们不仅要考虑如何实现,更要考虑性能优化,比如在这个实现思路中,我们是否可以减少不必要的渲染次数?帧率如何控制达到最优?等等。

虽然它们并不在这篇文章的讨论范围中,当也应当值得我们思考。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

HTML / CSS 相关文章推荐
纯CSS3实现3D旋转书本效果
Mar 21 HTML / CSS
CSS3等相关属性制作分页导航实现代码
Dec 24 HTML / CSS
css3进行截取替代js的substring
Sep 02 HTML / CSS
CSS3中Animation属性的使用详解
Aug 06 HTML / CSS
通过一张图教会你CSS3倒影的实现
Sep 26 HTML / CSS
HTML最新标准HTML5总结(必看)
Jun 13 HTML / CSS
Canvas绘制浮动球效果的示例
Dec 29 HTML / CSS
HTML中table表格拆分合并(colspan、rowspan)
Apr 07 HTML / CSS
css display table 自适应高度、宽度问题的解决
May 07 HTML / CSS
CSS filter 有什么神奇用途
May 25 HTML / CSS
HTML中的表单元素介绍
Feb 28 HTML / CSS
使用 CSS 构建强大且酷炫的粒子动画效果
Aug 14 HTML / CSS
HTML5在线预览PDF的示例代码
Sep 14 #HTML / CSS
HTML5 拖放(Drag 和 Drop)详解与实例代码
Sep 14 #HTML / CSS
HTML5页面中尝试调起APP功能
Sep 12 #HTML / CSS
html5使用canvas实现弹幕功能示例
Sep 11 #HTML / CSS
基于HTML5+CSS3实现简单的时钟效果
Sep 11 #HTML / CSS
html5超简单的localStorage实现记住密码的功能实现
Sep 07 #HTML / CSS
HTML5本地存储和本地数据库实例详解
Sep 05 #HTML / CSS
You might like
xajax写的留言本
2006/11/25 PHP
一个PHP日历程序
2006/12/06 PHP
php下载文件超时时间的设置方法
2016/10/06 PHP
PHP网页缓存技术优点及代码实例
2020/07/29 PHP
javascript英文日期(有时间)选择器
2007/05/02 Javascript
iframe父页面获取子页面参数的方法
2014/02/21 Javascript
js实现获取当前时间是本月第几周的方法
2015/08/11 Javascript
谈谈我对JavaScript DOM事件的理解
2015/12/18 Javascript
jQuery操作iframe中js函数的方法小结
2016/07/06 Javascript
PHP捕捉异常中断的方法
2016/10/24 Javascript
浅谈express 中间件机制及实现原理
2017/08/31 Javascript
微信小程序页面跳转功能之从列表的item项跳转到下一个页面的方法
2017/11/27 Javascript
javascript实现最长公共子序列实例代码
2018/02/05 Javascript
vue中手机号,邮箱正则验证以及60s发送验证码的实例
2018/03/16 Javascript
vue2.0+koa2+mongodb实现注册登录
2018/04/10 Javascript
Python中Collection的使用小技巧
2014/08/18 Python
Python实现删除当前目录下除当前脚本以外的文件和文件夹实例
2015/07/27 Python
Python中字符串格式化str.format的详细介绍
2017/02/17 Python
Python利用ElementTree模块处理XML的方法详解
2017/08/31 Python
Python+PIL实现支付宝AR红包
2018/02/09 Python
详解python3中的真值测试
2018/08/13 Python
python 使用事件对象asyncio.Event来同步协程的操作
2020/05/04 Python
python类共享变量操作
2020/09/03 Python
Python计算矩阵的和积的实例详解
2020/09/10 Python
使用css3制作动感导航条示例
2014/01/26 HTML / CSS
HTML5在微信内置浏览器下右上角菜单的调整字体导致页面显示错乱的问题
2021/01/19 HTML / CSS
css animation配合SVG制作能量流动效果
2021/03/24 HTML / CSS
事业单位辞职信范文
2014/01/19 职场文书
仓库主管岗位职责
2014/03/02 职场文书
养牛场项目建议书
2014/05/13 职场文书
个人先进事迹材料
2014/12/29 职场文书
五四青年节活动总结
2015/02/10 职场文书
离婚撤诉申请书范本
2015/05/18 职场文书
小学四年级作文之人物作文
2019/11/06 职场文书
Django框架模板用法详解
2022/06/10 Python
oracle设置密码复杂度及设置超时退出的功能
2022/06/28 Oracle