缓动动画
缓动动画,指带有一定缓冲的动画,物体在一定时间内渐进加速或者减速,从而使动画更加的真实和自然。
- 制作缓动动画共五步:
- 定义 0-1 的缓动系数 easing
- 计算物体距离终点的距离
- 计算当前的速度:距离 X 缓动系数
- 计算新的位置:当前位置 + 当前速度
- 重复执行 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缓动动画学习结束,道阻且长,行则将至。与诸君共勉。 ⭐️