Canvas进阶-6、缓动动画

缓动动画

缓动动画,指带有一定缓冲的动画,物体在一定时间内渐进加速或者减速,从而使动画更加的真实和自然。

  • 制作缓动动画共五步:
  1. 定义 0-1 的缓动系数 easing
  2. 计算物体距离终点的距离
  3. 计算当前的速度:距离 X 缓动系数
  4. 计算新的位置:当前位置 + 当前速度
  5. 重复执行 2 - 4 步,直到达到目标

请添加图片描述

      <canvas id="myCanvas" width="1000"></canvas>
   init() {
      class Ball {
        constructor(x, y, radius, color) {
          this.x = x
          this.y = y
          this.radius = radius
          this.color = color
          this.vx = Math.random() * 3 - 1 // 添加随机速度
          this.vy = Math.random() * 3 - 1
          this.opacity = 1
          this.lifeTime = 400 // 添加生命周期属性(毫秒)
          this.birthTime = Date.now() // 记录小球创建的时间
        }
        fill(context) {
          context.save()
          context.globalAlpha = this.opacity
          context.beginPath()
          context.arc(this.x, this.y, this.radius, 0, Math.PI * 2)
          context.fillStyle = this.color
          context.fill()
          context.closePath()
          context.restore()
        }
      }
      const cnv = document.getElementById('myCanvas')
      const ctx = cnv.getContext('2d')
      const ball = new Ball(0, cnv.height / 2, 30)
      // 定义终点坐标
      const targetX = cnv.width * (3 / 4)
      // 定义缓动系数
      const easing = 0.05
      // 定义容差值
      const tolerance = 0.1
      ;(function frame() {
        window.requestAnimationFrame(frame)
        ctx.clearRect(0, 0, cnv.width, cnv.height)
        const vx = (targetX - ball.x) * easing
        ball.x += vx
        //  因为浮点数问题,ball.x,targetX永不相等
        // console.log(ball.x, 'ball.x')
        // console.log(targetX, 'targetX')
        // 判断是否到达终点
        if (ball.x >= targetX - tolerance) {
          // 重置小球位置
          ball.x = 0
        }
        ball.fill(ctx)
      })()
    },

由实验可知,小球的速度是一个由快到慢的过程,原理很简单,距离越短,距离与方向的乘积越小,那么方向速度就越来越小。

缓动系数使 0-1的数,越接近1,小球移动速度越快。

因为缓动动画的每一帧的速度都不同,所以它更加的自然。

任意方向缓动

请添加图片描述

      const ball = new Ball(20, 20, 30)
      // 定位终点坐标
      const targetX = cnv.width * (3 / 4)
      const targetY = cnv.height * (3 / 4)
      // 定义缓动系数
      const easing = 0.05
      // 定义容差值
      const tolerance = 0.1

      ;(function frame() {
        window.requestAnimationFrame(frame)
        ctx.clearRect(0, 0, cnv.width, cnv.height)

        const vx = (targetX - ball.x) * easing
        const vy = (targetY - ball.y) * easing
        ball.x += vx
        ball.y += vy

        if (ball.x >= targetX - tolerance && ball.y >= targetY - tolerance) {
          ball.x = 20
          ball.y = 20
        }

        ball.fill(ctx)
      })()

花里胡哨心随我动 ✨✨

请添加图片描述

 init() {
      class Ball {
        constructor(x, y, radius, color) {
          this.x = x
          this.y = y
          this.radius = radius
          this.color = color
          this.vx = Math.random() * 3 - 1 // 添加随机速度
          this.vy = Math.random() * 3 - 1
          this.opacity = 1
          this.lifeTime = 400 // 添加生命周期属性(毫秒)
          this.birthTime = Date.now() // 记录小球创建的时间
        }
        fill(context) {
          context.save()
          context.globalAlpha = this.opacity
          context.beginPath()
          context.arc(this.x, this.y, this.radius, 0, Math.PI * 2)
          context.fillStyle = this.color
          context.fill()
          context.closePath()
          context.restore()
        }
      }
      const getMouse = element => {
        let mouse = { x: 0, y: 0 }
        element.addEventListener('mousemove', e => {
          let x = e.pageX
          let y = e.pageY

          mouse.x = e.clientX - element.getBoundingClientRect().left // 使用clientX和getBoundingClientRect计算鼠标位置
          mouse.y = e.clientY - element.getBoundingClientRect().top
        })
        return mouse
      }

      const cnv = document.getElementById('myCanvas')
      const ctx = cnv.getContext('2d')
      // 定义缓动系数
      const easing = 0.1
      const mouse = getMouse(cnv)
      const balls = []
      for (let i = 0; i < 30; i++) {
        const radius = 30 - i * 2 // 逐渐减小半径
        const x = cnv.width / 2 // 初始x位置为鼠标位置
        const y = cnv.height / 2 // 初始y位置为鼠标位置
        const color = `hsl(${Math.random() * 360}, 50%, 50%)` // 随机颜色
        balls.push(new Ball(x, y, radius, color))
      }

      ;(function frame() {
        window.requestAnimationFrame(frame)
        ctx.clearRect(0, 0, cnv.width, cnv.height)

        let preX = null
        let preY = null
        let vx
        let vy
        balls.forEach((ball, index) => {
          if (preX) {
            vx = (preX - ball.x) * easing
            vy = (preY - ball.y) * easing
          } else {
            vx = (mouse.x - ball.x) * easing
            vy = (mouse.y - ball.y) * easing
          }

          preX = ball.x
          preY = ball.y
          ball.x += vx
          ball.y += vy
          ball.fill(ctx)
        })
      })()
    }

到此canvas缓动动画学习结束,道阻且长,行则将至。与诸君共勉。 ⭐️

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值