用canvas实现红心飘飘的动画效果

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

一、Bezier曲线运动轨迹

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

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

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

BezierMaker.prototype.bezier = function(t) { //贝塞尔公式调用
    var x = 0,
        y = 0,
        bezierCtrlNodesArr = this.bezierCtrlNodesArr,
        n = bezierCtrlNodesArr.length - 1,
        self = this
    bezierCtrlNodesArr.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 : -1
  return 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

时间: 2024-10-09 21:12:56

用canvas实现红心飘飘的动画效果的相关文章

多种方法实现Loading(加载)动画效果

当我们ajax提交一个按钮的时候,给那个按钮来个Loading效果会高端很多,体验也会上升个层次. 既能让用户知道正在提交中,也能防止二次提交,好处多多呢. 上面的这个圈圈是会滚动的.简单点的话,可以直接用GIF动态图片实现.不过现在已经有了CSS3和HTML5了,多了好几种高大上的实现方式. 这里先来介绍几个动画的在线demo,第一个是HTML5 Boilerplate中的Effeckt.css,第二个是Animate.css. 下面一一列出,如果要结合按钮的话,可自行修改下CSS或JS等文件

(转)多种方法实现Loading(加载)动画效果

当我们ajax提交一个按钮的时候,给那个按钮来个Loading效果会高端很多,体验也会上升个层次. 既能让用户知道正在提交中,也能防止二次提交,好处多多呢. 上面的这个圈圈是会滚动的.简单点的话,可以直接用GIF动态图片实现.不过现在已经有了CSS3和HTML5了,多了好几种高大上的实现方式. 这里先来介绍几个动画的在线demo,第一个是HTML5 Boilerplate中的Effeckt.css,第二个是Animate.css. 下面一一列出,如果要结合按钮的话,可自行修改下CSS或JS等文件

html5 canvas首屏自适应背景动画循环效果代码

模板描述:html5 canvas首屏自适应背景动画循环效果代码 由于动态图太大,怕以后服务器受不了,所以现在都改为静态图了,大家点击演示地址一样的,希望大家喜欢,你们的支持就是小海的动力!! 欢迎大家积极评论,给出宝贵意见 下 载 演示地址 本文地址:html5 canvas首屏自适应背景动画循环效果代码

用css3和canvas实现的蜂窝动画效果

近期工作时研究了一下css3动画和js动画.主要是工作中为了增强页面的趣味性,大家都有意无意的加入了非常多动画效果.当然大部分都是css3动画效果.能够gpu加速,这会降低移动端的性能需求. 今天主要说的是蜂窝效果.详细效果大家等下能够执行源代码.这里就不放gif图了. css3的原理非常easy,就是通过更改background-size,因为css3中的background中能够设置repeat属性,来使背景图片在x,y方向平铺.一開始先设置background-size:10%, 10%,

HTML5 Canvas动画效果实现原理

在线演示 使用HTML5画布可以帮助我们高速实现简单的动画效果.基本原理例如以下: 每隔一定时间绘制图形而且清除图形,用来模拟出一个动画过程,能够使用context.clearRect(0, 0, x, y)方法来刷新须要绘制的图形 首先是绘制图形的方法,例如以下: function myAnimation() { ctx.clearRect(0, 0, canvas_size_x, canvas_size_y); if (x_icon < 0 || x_icon > canvas_size_

使用JavaScript和Canvas实现下雪动画效果

该下雪动画效果使用了HTML5中Canvas画布实现,其中涉及了物理学中曲线运动的相关知识与运算. index.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta content="width=device-width,initial-scale=1.0,maximum-scale=1.0,user-scal

基于canvas实现物理运动效果与动画效果(一)

一.为什么要写这篇文章 某年某月某时某种原因,我在慕课网上看到了一个大神实现了关于小球的抛物线运动的代码,心中很是欣喜,故而写这篇文章来向这位大神致敬,同时也为了弥补自己在运动效果和动画效果制作方面的不足 二.几种简单的直线运动 这一部分主要讲解的是简单的运动效果的实现原理,其实所有的canvas动画效果的实现在核心思想是一致的:都是先定义个初始的状态,然后定义一个定时器,定时器内执行一个方法,记得在这个方法中要对当前的画面清除,然后在这个方法中重新绘制需要变化的效果,由于人眼存在残影,所以短时

7个惊艳的HTML5 Canvas动画效果及源码

HTML5非常强大,尤其是现在大部分浏览器都支持HTML5和CSS3,用HTML5制作的动画也多了起来.另外,Canvas上绘制图形非常简单,本文就分享了一些强大的HTML5 Cnavas动画,一起来看看. 1.HTML5 Canvas瀑布动画 超逼真 这是一个很逼真的HTML5瀑布动画,基于Canvas实现的,效果相当酷. 在线演示   /   源码下载 2.HTML5 Canvas彩色像素进度条动画 这也是一款基于HTML5 Canvas的动画特效,它是一个很有创意的HTML5进度条,大家可

必备的Canvas接口和动画效果大全

1.概述 <canvas>元素用于生成图像.它本身就像一个画布,JavaScript 通过操作它的 API,在上面生成图像.它的底层是一个个像素,基本上<canvas>是一个可以用 JavaScript 操作的位图(bitmap).它与 SVG 图像的区别在于,<canvas>是脚本调用各种方法生成图像,SVG 则是一个 XML 文件,通过各种子元素生成图像.使用 Canvas API 之前,需要在网页里面新建一个<canvas>元素. <canvas