【干货】Canvas 旋转最佳实践:离屏快照 + requestAnimationFrame 平滑方案

离屏画布、Promise 队列、requestAnimationFrame,这套方案帮你彻底解决 Canvas 旋转过程中画质模糊、旋转错乱、卡顿延迟等常见问题。

目录

🌟 效果演示

1️⃣ 常规写法痛点

2️⃣ 方案设计思路

3️⃣ 核心方案完整实现

3.1 核心类封装

3.2 核心旋转逻辑

3.3 快速重置

4️⃣ Bonus:下载旋转后图片(调试神器)

📝 整体优势总结

 完整源码


🌟 效果演示

注:暂不支持任意角度(非90°倍数)的连续旋转。 


1️⃣ 常规写法痛点

常规旋转代码:

ctx.rotate(angle) 
ctx.drawImage(img, x, y) 

实际踩坑:

❌ 宽高不适配导致图片截断
❌ 瞬间旋转频繁触发闪烁

真实项目中旋转效果👇

  • 图片锯齿严重

  • 页面一顿一顿的

本套高性能 Canvas 旋转方案,核心亮点:

✅ 离屏画布快照
✅ 自动计算旋转尺寸
✅ Promise 队列避免多次触发冲突
✅ requestAnimationFrame 丝滑渲染
✅支持动态角度旋转,旋转后图像清晰


2️⃣ 方案设计思路

核心原则:

先拍快照 -> 计算旋转尺寸 -> 离屏旋转 -> 主线程绘制

整体思路:

  • snapshot 离屏 Canvas 负责记录当前画布;

  • offscreen 离屏 Canvas 负责旋转后结果;

  • Promise 队列 确保多个旋转顺序执行;

  • requestAnimationFrame 避免旋转阻塞渲染。


3️⃣ 核心方案完整实现

直接上代码,按需 copy👇

3.1 核心类封装

export default class CanvasRotationHelper {
  constructor() {
    this.snapshot = document.createElement("canvas")
    this.snapshotCtx = this.snapshot.getContext("2d")

    this.offscreen = document.createElement("canvas")
    this.offscreenCtx = this.offscreen.getContext("2d")

    this._rotationQueue = Promise.resolve()
  }
}


3.2 核心旋转逻辑

  • 队列控制_rotationQueue.then() 保证串行执行旋转,防抖 + 防错乱

rotateCanvas(canvas, degrees) {
  this._rotationQueue = this._rotationQueue.then(() => {
    return new Promise((resolve, reject) => {
      try {

      } catch (e) {
        reject(e)
      }
    })
  })
  return this._rotationQueue
}
  • 快照记录:

const ow = canvas.width
const oh = canvas.height

this.snapshot.width = ow
this.snapshot.height = oh
this.snapshotCtx.setTransform(1, 0, 0, 1, 0, 0)
this.snapshotCtx.clearRect(0, 0, ow, oh)
this.snapshotCtx.drawImage(
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值