基于canvas点击圆形爱心按钮,喷出爱心气泡动画特效。这是一款点赞喜欢爱心特效。

css代码

<style>body {background-color: rgba(255, 137, 164, 0.2);background-size: cover;background-repeat: no-repeat;}.liker {position: absolute;top: 0%;left: 50%;transform: translate(-50%, 0%);}.liker span {position: absolute;font-family: monospace;color: #F92A82;bottom: -70px;left: 50%;transform: translateX(-50%);}.btn {width: 50px;display: flex;justify-content: center;align-items: center;height: 50px;border-radius: 50%;border: none;position: absolute;cursor: pointer;left: 50%;transform: translate(-50%, -10%);background-color: #FF4D80;color: #fff;outline: none;transition: 0.3s ease;box-shadow: 0 3px 10px #F92A82;}.btn svg {fill: #fff;}.btn:hover {background-color: #F92A82;}</style>

html代码

<div class="liker"><canvas class="hearts-canvas"></canvas><button class="btn"><svg width="24" height="24" viewBox="0 0 24 24"><path d="M12,21.35L10.55,20.03C5.4,15.36 2,12.27 2,8.5C2,5.41 4.42,3 7.5,3C9.24,3 10.91,3.81 12,5.08C13.09,3.81 14.76,3 16.5,3C19.58,3 22,5.41 22,8.5C22,12.27 18.6,15.36 13.45,20.03L12,21.35Z"></path></svg></button><span>快来点赞吧</span>
</div>

javascript代码

<script>class HeartsFlow {constructor(data) {this.el = document.querySelector(data.canvasEl);this.w = 200;this.h = 400;this.ctx = this.el.getContext('2d');this.colors = ['255, 137, 164', //'#FF89A4','239, 121, 138', //'#EF798A','255, 77, 128', //'#FF4D80','249, 42, 130' //'#F92A82'];this.heartsAmount = data.amount;this.heartsList = [];this.isAnimate = false;this.raf = null;this.animate = this.animate.bind(this);this.paintHeart = this.paintHeart.bind(this);this.stopAnimation = this.stopAnimation.bind(this);this.init();}getRandomColor() {return this.colors[Math.floor(Math.random() * this.colors.length)];}getRandom(min, max) {return Math.floor(Math.random() * (max - min) + min);}setHeartsList() {let arr = [];for (let i = 0; i < this.heartsAmount; i++) {let currentSize = this.getRandom(10, 15);let dt = {x: this.w / 2,y: this.h,bx: this.w / 2,by: this.h,pos: this.h,_osp: this.getRandom(200, 400) / 100,osp: this.getRandom(11, 12) / 10,vsp: this.getRandom(currentSize, currentSize + i * 2) / 1000,size: currentSize,color: this.getRandomColor(),alfa: 1 };arr.push(dt);}this.heartsList = [...this.heartsList, ...arr];}getCoordinates({ x, y, size, color, bx, by, _osp, osp, vsp, pos, alfa }) {return {xst: x,yst: y + size / 2,x0: x - size / 1.4,y0: y + size / 4,x1: x - size / 1.3,y1: y - size / 1.3,_x0: x + size / 1.4,_y0: y + size / 4,_x1: x + size / 1.3,_y1: y - size / 1.3,xfn: x,yfn: y - size / 3,bx: bx,by: by,_osp: _osp,osp: osp,vsp: vsp,pos: pos,alfa: alfa,size: size,color: color };}paintHeart({ xst, yst, x0, y0, _x0, _y0, x1, y1, _x1, _y1, xfn, yfn, color, alfa }) {this.ctx.globalCompositeOperation = "lighter";this.ctx.beginPath();this.ctx.moveTo(xst, yst);this.ctx.bezierCurveTo(x0, y0, x1, y1, xfn, yfn);this.ctx.moveTo(xst, yst);this.ctx.bezierCurveTo(_x0, _y0, _x1, _y1, xfn, yfn);this.ctx.fillStyle = `rgba(${color}, ${alfa})`;this.ctx.strokeStyle = `rgba(${color}, ${alfa})`;this.ctx.fill();this.ctx.stroke();this.ctx.closePath();}mutateData() {this.heartsList = this.heartsList.map(item => {let pos = item.pos - 0.05;let x = item.x + Math.sin(pos * item._osp) * ((pos - item.by) / item.osp);let y = pos + (pos - item.by) / item.vsp * 1.6;let alfa = this.normalize0between1(0, this.h, y).toFixed(1);return {...item, x: x, y: y, pos: pos, alfa: alfa };});this.heartsList = this.heartsList.filter(item => item.y > 0);}normalize0between1(min, max, value) {return (value - min) / (max - min);}setCanvas() {this.el.width = this.w;this.el.height = this.h;}startAnimation() {if (!this.isAnimate) {this.isAnimate = true;console.log('start animation');this.setHeartsList();this.animate();} else {this.setHeartsList();}}stopAnimation() {this.isAnimate = false;console.log('stop animation');cancelAnimationFrame(this.raf);}animate() {this.ctx.clearRect(0, 0, this.w, this.h);if (this.isAnimate) {for (let i = 0, len = this.heartsList.length; i < len; i++) {let hrt = this.getCoordinates(this.heartsList[i]);this.paintHeart(hrt);}this.mutateData();}this.raf = requestAnimationFrame(this.animate);if (this.heartsList.length === 0 && this.isAnimate) {this.stopAnimation();}}init() {this.setCanvas();this.setHeartsList();this.animate();}}let ht = new HeartsFlow({canvasEl: '.hearts-canvas',amount: 20 });let btn = document.querySelector('.btn');btn.addEventListener('click', function () {ht.startAnimation();});
</script>

在这里我就不展示效果图了,大家到自己浏览器观看吧。

html5制作一款超好看的点赞爱心气泡特效相关推荐

  1. canvas 形状碰撞_【案例】如何用html5 制作canvas酷炫的网状图形动画特效

    点击上方[我分享我快乐]→[...]右上角→[设为星标⭐]即可第一时间获取最新设计资源 哈喽大家好,又到了每周二案例环节啦,在教学开始前先插播一条招聘信息~ 高薪招聘 杭州招聘(非技术) 公司背景: ...

  2. 如何制作一款HTML5 RPG游戏引擎——第四篇,情景对话

    今天我们来实现情景对话.这是一个重要的功能,没有它,游戏将变得索然无味.所以我们不得不来完成它. 但是要知道,使用对话可不是一件简单的事,因为它内部的东西很多,比如说人物头像,人物名称,对话内容... ...

  3. 如何制作一款HTML5 RPG游戏引擎——第五篇,人物人物特效

    上一次,我们实现了对话类,今天就来做一个游戏中必不可少的--人物类. 当然,你完全是可以自己写一个人物类,但是为了方便起见,还是决定把人物类封装到这个引擎里. 为了使这个类更有意义,我还给人物类加了几 ...

  4. 如何制作一款HTML5 RPG游戏引擎——第三篇,利用幕布切换场景

    开言: 在RPG游戏中,如果有地图切换的地方,通常就会使用幕布效果.所谓的幕布其实就是将两个矩形合拢,直到把屏幕遮住,然后再展开直到两个矩形全部移出屏幕. 为了大家做游戏方便,于是我给这个引擎加了这么 ...

  5. 如何制作一款HTML5 RPG游戏引擎——第二篇,烟雨+飞雪效果

    今天我们来实现烟雨+飞雪效果.首先来说,一款经典的RPG游戏难免需要加入天气的变化.那么为了使我们的RPG游戏引擎更完美,我们就只好慢慢地实现它. 本文为该系列文章的第二篇,如果想了解以前的文章可以看 ...

  6. 用Html5结合Qt制作一款本地化EXE游戏-太空大战(Space War)

    本次来说一说如何利用lufylegend.js引擎制作一款html5游戏后将其通过Qt转换成EXE程序.步骤其实非常简单,接下来就一步步地做一下解释和说明. 首先我们来开发一个有点类似于太空大战的游戏 ...

  7. Html5制作工具对比

    最近迫于老板的要求,要做一些Html5的宣传网页(原谅我用词可能不准,大家明白意思就好),介绍俺们的公司和产品--虽然说老板有点跟风,并且出手已经有点晚了,可是任务下来了还是得做. 先两句话介绍下背景 ...

  8. 电脑PHP动画制作画板,HTML_html5教程制作简单画板代码分享,HTML5制作简单画板 复制代码代 - phpStudy...

    html5教程制作简单画板代码分享 HTML5制作简单画板 复制代码代码如下: http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min ...

  9. 无水印的html5制作软件,无水印剪辑视频

    无水印剪辑视频是一款火爆的视频编辑软件,每一个功能都有着详细的操作说明,就算你是新手小白也能快速上手制作视频.超多酷炫的特效,海量的剪辑素材,不同的视频模板,让你能轻松的制作出各种各样的视频,如果你也 ...

最新文章

  1. 说说pgpool-II的 health check
  2. scaling之旅_机器学习算法之旅
  3. GIS热词:AR、VR、MR辨析
  4. 10个遥远但近在人间的天堂!
  5. python CGI编程Apache配置
  6. java怎么判断mysql中是否存在我们查找的索引_10张图告诉你,MySQL 是如何查找数据的?...
  7. jQuery常用语法笔记
  8. java如何面试别人_Java面试如何考察候选人
  9. 代理模式---论坛权限控制代理
  10. QQ空间美化高仿认证PS动态皮肤背景音乐添加快速聊天
  11. matlab 自制闹钟程序,想编一个每半小时提示的闹钟程序
  12. 在集体奋斗中实现自己的价值
  13. EuroBen Benchmark安装以及测试(By Robinvane Suen)
  14. 【Ubuntu20安装aria2以及配置web端】
  15. 女大学生出轨行为心理[组图]
  16. MessageSource简介
  17. 烤仔看世界 | 百度、谷歌、微软等巨头争相入局,一场改变AI格局的隐秘拍卖……...
  18. 独立按键控制继电器开关
  19. hacking 麦步手表之(2)命令行编译工程
  20. python二维数组的行和列_python 定义N行2列二维数组与赋值

热门文章

  1. 【音频播放】自制音频播放器—音视频基础概念,未完待续。。。
  2. UIScroll View无限循环的超级简单的实现
  3. GPS定位软件和定位器有什么区别?
  4. 大疆数字IC2019
  5. 计算机辅助专题地图,第九章几种主要类型专题地图的编制 专题地图编制——色彩设计编制的基本方法特点和计算机辅助专题地图制图.ppt...
  6. 最牛销售:把好处说够,把痛苦说透
  7. 众盟科技2020智能化白皮书:穿越新商业周期,读懂商业智能化的真义
  8. bp神经网络和神经网络,bp神经网络的应用领域
  9. laravel8.5的PHPUnit命令行解释(有时间翻译)
  10. java 置顶的后台代码_[置顶] 程序员喝酒