两周前,项目里需要实现一个红心飘飘的点赞效果。抓耳挠腮了老半天,看了几篇大佬的文章,终于算是摸了个七七八八。不禁长叹一声,还是菜啊。先来看一下效果:(传送门进去点一波)

一、Bezier曲线运动轨迹

其实用大白话描述一下需求就是让一个红心图片沿着贝塞尔曲线的轨迹走,然后边走边消失。核心在于得到贝塞尔曲线上的一系列点。本文不会讲解贝塞尔曲线的原理,因为大佬们已经讲过了,而且讲的比我好。参考文章如下:

  • 用canvas绘制一个曲线动画——深入理解贝塞尔曲线
  • bezierMaker.js——N阶贝塞尔曲线生成器

其中第二篇文章讲到了生成二阶和三阶贝塞尔曲线可以使用canvas自带的方法:quadraticCurveTobezierCurveTo,而高阶的则先得到曲线上一系列的点,然后顺次连接这些点来拟合高阶的贝塞尔曲线。没错,我们要的就是这一系列的点,有了这些点,就可以控制红心的轨迹了。下面是我基于作者的BezierMarker.js写的一个demo,可以直观地看出高阶贝塞尔曲线上的点:

See the Pen XyWZXj by imgss (@imgss) on CodePen.

上面100个曲线上的点坐标是由下面这段代码计算得出的:

BezierMaker.prototype.bezier = function(t) { //贝塞尔公式调用var x = 0,y = 0,bezierCtrlNodesArr = this.bezierCtrlNodesArr,n = bezierCtrlNodesArr.length - 1,self = thisbezierCtrlNodesArr.forEach(function(item, index) {if(!index) {x += item.x * Math.pow(( 1 - t ), n - index) * Math.pow(t, index) y += item.y * Math.pow(( 1 - t ), n - index) * Math.pow(t, index) } else {x += self.factorial(n) / self.factorial(index) / self.factorial(n - index) * item.x * Math.pow(( 1 - t ), n - index) * Math.pow(t, index) y += self.factorial(n) / self.factorial(index) / self.factorial(n - index) * item.y * Math.pow(( 1 - t ), n - index) * Math.pow(t, index) }})return {x: x,y: y}
}

这个方法就是对贝塞尔公式的实现。以3阶贝塞尔公式为例(见下图),它的方程需要四个控制点(P1,P2,P3,P4)和一个t值,就能计算出曲线上的某一点的坐标。


根据给定的t值,结合控制点的坐标,算出相应t值下的贝塞尔曲线上的点的坐标。拿下图(来自第一篇文章)来说,给定t值为0.25,就可以得到B点的坐标

当将t由0递增到1时,就可以得到100个曲线上的点,进而拟合出相应的曲线。当我们拿到这一系列点时,其实问题已经解决了一大半了。

二、使红心飘起来

拿到拟合点数组后,绘制轨迹就是从数组中依次拿出坐标,并将红心图片绘制到相应的坐标上。并根据当前拟合点在曲线数组中的位置,改变图片的不透明度,就可以让红心飘起来了,上一部分代码,讲解见注释:

// 生成随机数
function rnd () {let flag = Math.random() > 0.5 ? 1 : -1return 80 * Math.random() * flag
}class FlyHeart {constructor (ctx, img) {this.ctx = ctx;this.img = heart;// 拿到红心的运动轨迹,一系列拟合点坐标this.bezierArr = new BezierMaker(ctx, [{x: 187, y: 245},{x: 170 + rnd(), y: 200},{x: 200 + rnd() , y: 120}, {x: 140 + rnd(), y: 60}], 90).bezierArr //90表示拟合点的数量,rnd使红心的轨迹有一定的随机性}draw () {// 依次取出轨迹的每个点let position = this.bezierArr.shift();// 清除上次画的this.clear();if (position) {this.ctx.save()// 根据当前数组长度算出透明度this.ctx.globalAlpha = this.bezierArr.length / 30;this.ctx.drawImage(this.img, position.x , position.y, 20, 20);this.ctx.restore();this.prevPosition = position;}}// 清除上次画的clear () {if (this.prevPosition) {this.ctx.clearRect(this.prevPosition.x, this.prevPosition.y, 20, 20);}}
}

接下来就是给body添加点击事件,当点击时,就新生成一个红心:

  document.body.addEventListener('click', function() {heartArr.push(new FlyHeart(ctx, heart));})let heartArr = []const cvs = document.getElementById('cvs')const ctx = cvs.getContext('2d')const heart = document.getElementById('heart') //图片function draw () {if(heartArr.length) {for(let heart of heartArr) {heart.draw();if(heart.bezierArr.length === 0) {heart.clear();let index = heartArr.indexOf(heart)heartArr.splice(index, 1)}}}requestAnimationFrame(draw)}draw()

三、后记

当时看到这个需求的时候,真的是一筹莫展,看到n阶贝塞尔曲线时更是一头雾水,但是看不懂也要看,然后看着看着,看多了也就慢慢明白了。希望没浪费大家的时间,各位看官看完后有所收获(完)

转载于:https://www.cnblogs.com/imgss/p/9949401.html

用canvas实现红心飘飘的动画效果相关推荐

  1. 74行代码实现浪漫的红心下落的动画效果

    七夕节快到了,让我们使用 74 行的纯 HTML/JavaScript 代码,实现一个浪漫的红心下落的动画效果吧. 将下列代码粘贴到一个空白的 html 文件里,用浏览器本地打开即可. <htm ...

  2. php3D动画,html5的canvas实现几何模型3D运动动画效果

    html5的canvas实现几何模型3D运动动画效果 JS片段: var {atan2,sqrt,sin,cos,PI,acos} = Math; function project3D(x,y,z,v ...

  3. 7 款基于 HTML5 Canvas 的超炫 3D 动画效果

    在以前,想要在浏览器中实现3D动画效果是非常困难的,但是自从HTML5诞生之后,这就变得十分简单了.遗憾的是,目前的浏览器对3D渲染效果还不是非常理想,尤其是渲染速度,可能用chrome和safari ...

  4. html动画变圆,HTML5 canvas制作圆形的万花筒动画效果

    Canvas圆形万花筒动画效果 window.οnlοad=function(){ var canvas = document.getElementById("canvas"); ...

  5. 【Canvas】js用canvas绘制一个钟表时钟动画效果

    学习JavaScript的看过来,有没有兴趣用Canvas画图呢,可以画很多有趣的事物,自由发挥想象,收获多多哦,旋转角度绘图这个重点掌握到了吗,这里有一个例子,如何用canvas画钟表时钟动图效果, ...

  6. 简单的Canvas刮刮乐带动画效果的实例

    今天做了个刮刮乐领奖品的小活动,感觉挺有用的,整理在这儿记录下 上个效果图先: 加了个简单的 css 动画效果 下面贴上主要代码: index.html <!DOCTYPE html> & ...

  7. Android 中通过Canvas 与线程结合实现动画效果

    前段时间在公司做了一个模块,不使用第三方动画效果类,直接通过Canvas 进行图像的绘制,并通过Thread实现动画的效果 该模块主要是实现车辆运行时候的道路运行效果,在进行实施前做了一个相关的Dem ...

  8. 【Canvas】js用Canvas绘制漩涡螺旋图动画效果

    学习JavaScript编程,会用Canvas画图吗,学会它,能画很多有趣的事物,可自由发挥想象,会发现图形学的美,收获很多,这里有一个例子,如何用canvas画漩涡螺旋图动图效果,接下来开始讲,边学 ...

  9. H5 Canvas绘制圆形进度条动画效果

    效果如图 效果比较简单 html结构部分 <canvas id="canvas" width="110" height="110"&g ...

最新文章

  1. 升级python2.6.6到python2.7导致pip命令不可用
  2. C++中关于配置文件的问题
  3. 解读鸿蒙轻内核的监控器:异常钩子函数
  4. PostgreSQL存储引擎源码分析五(原创,不断更新)
  5. ifttt.com:让你的网络行为能引发连锁反应
  6. 中文语句分词 -- HanLP词性
  7. 独热向量编码(one-hot encoding)原理详解与实现
  8. 均匀带电直线外一点的场强
  9. matlab crg格式,MatLab和FlightGear环境的配置及样例
  10. centos7 安装sogou输入法
  11. oracle数据库中视图是什么,orcl数据库视图是什么
  12. WPF高性能绘图之DrawingCanvas、DrawingVisual、Button的同时使用
  13. 经典的Times 33 哈希算法
  14. S3C44B0 寄存器描述
  15. 7种将字符串反转的 Java 方法
  16. Python中的sin和cos函数
  17. 二分查找法--有序表
  18. javafx 实现绘图板
  19. CSDN便捷编辑收藏内容和删除收藏夹(网页版)
  20. php exec 执行php脚本

热门文章

  1. 多年上网觅疏7地后一野团圆(图)
  2. 算法导论附录C.4-1
  3. 使用Qt编写CUDA程序
  4. java 驼峰映射工具类
  5. C/C++豪华3d版圣诞树代码
  6. 使用Python开发DeFi项目
  7. [品味生活]10个让人生更美好的必须技能
  8. 支付宝支付模拟demo
  9. 51单片机(STC89C52RC) lcd1602 4线接法+经典IO扩展综合实验
  10. Django 中使用locals()函数的技巧