Bootstrap

《Canvas修仙传·第二重天灵动境》 ——让图形学会七十二变的时空法则

各位道友久候!上回我们解锁了"静态造物"的奥义,今日将传授Canvas真正的灵魂所在——让图形拥有生命!(๑•̀ㅂ•́)و✧


章前渡劫测试

请回答以下问题检验筑基成果:

  1. 如何绘制带阴影的渐变文字?
  2. arc()方法第5个参数有何玄机?
  3. 绘制路径时必须配对使用的方法是什么?

(答案藏在文末渡劫大礼包中)


第一式:时间法则·动画轮回阵

核心心法: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()

🔥 渡劫要点

  1. 始终使用clearRect清空画布(否则会出现残影)
  2. 使用save()/restore()保护绘图状态(防止属性污染)
  3. 通过时间差计算进度(保障不同设备动画速度一致)

💡 高阶奥义

// 缓动函数库(让动画更自然)
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
;