各位道友久候!上回我们解锁了"静态造物"的奥义,今日将传授Canvas真正的灵魂所在——让图形拥有生命!(๑•̀ㅂ•́)و✧
章前渡劫测试
请回答以下问题检验筑基成果:
- 如何绘制带阴影的渐变文字?
arc()
方法第5个参数有何玄机?- 绘制路径时必须配对使用的方法是什么?
(答案藏在文末渡劫大礼包中)
第一式:时间法则·动画轮回阵
核心心法:requestAnimationFrame
🕹️ 术语解谜:
- 帧率(FPS): 每秒钟画面更新次数(凡人肉眼极限约24FPS)
- 回调地狱: 动画嵌套调用形成的代码旋涡
- 时间戳: 动画启动后的毫秒数(破解帧率波动的关键)
// 基础动画模板
let startTime = null
function animate(timestamp) {
if (!startTime) startTime = timestamp
const progress = timestamp - startTime // 已修炼时间
// 在此施展动画仙术
drawRotatingSword(progress)
requestAnimationFrame(animate) // 轮回召唤
}
function drawRotatingSword(time) {
ctx.clearRect(0, 0, canvas.width, canvas.height)
ctx.save()
ctx.translate(200, 200)
ctx.rotate(time * 0.005) // 时间驱动旋转(0.005控制转速)
ctx.fillStyle = '#2ecc71'
ctx.fillRect(-50, -10, 100, 20) // 绘制剑身
ctx.restore()
}
// 启动轮回阵
animate()
🔥 渡劫要点:
- 始终使用
clearRect
清空画布(否则会出现残影) - 使用
save()
/restore()
保护绘图状态(防止属性污染) - 通过时间差计算进度(保障不同设备动画速度一致)
💡 高阶奥义:
// 缓动函数库(让动画更自然)
function easeInOutQuad(t) {
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t
}
// 应用示例
const duration = 2000 // 动画周期2秒
const currentProgress = Math.min(progress, duration)
const t = currentProgress / duration
const easedT = easeInOutQuad(t)
const currentX = startX + (endX - startX) * easedT
第二式:空间法则·矢量移形换影
坐标变换三连击:translate
/rotate
/scale
📐 变换矩阵原理:
Canvas维护着一个变形矩阵栈,所有绘制操作都会经过矩阵运算
// 绘制旋转的七芒星阵
function drawStar() {
ctx.save()
ctx.translate(centerX, centerY) // 坐标系平移
ctx.rotate(currentAngle) // 坐标系旋转
ctx.scale(1 + Math.sin(currentAngle)*0.2, 1) // 动态缩放
// 绘制星体
ctx.beginPath()
for(let i=0; i<14; i++){
const angle = i * Math.PI/7
const radius = i%2 === 0 ? 30 : 15
ctx