Gahing's blog Gahing's blog
首页
知识体系
  • 前端基础
  • 应用框架
  • 工程能力
  • 应用基础
  • 专业领域
  • 业务场景
  • 前端晋升 (opens new window)
  • Git
  • 网络基础
  • 算法
  • 数据结构
  • 编程范式
  • 编解码
  • Linux
  • AIGC
  • 其他领域

    • 客户端
    • 服务端
    • 产品设计
软素质
  • 面试经验
  • 人生总结
  • 个人简历
  • 知识卡片
  • 灵感记录
  • 实用技巧
  • 知识科普
  • 友情链接
  • 美食推荐 (opens new window)
  • 收藏夹

    • 优质前端信息源 (opens new window)
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Gahing / francecil

To be best
首页
知识体系
  • 前端基础
  • 应用框架
  • 工程能力
  • 应用基础
  • 专业领域
  • 业务场景
  • 前端晋升 (opens new window)
  • Git
  • 网络基础
  • 算法
  • 数据结构
  • 编程范式
  • 编解码
  • Linux
  • AIGC
  • 其他领域

    • 客户端
    • 服务端
    • 产品设计
软素质
  • 面试经验
  • 人生总结
  • 个人简历
  • 知识卡片
  • 灵感记录
  • 实用技巧
  • 知识科普
  • 友情链接
  • 美食推荐 (opens new window)
  • 收藏夹

    • 优质前端信息源 (opens new window)
关于
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 前端基础

  • 应用框架

  • 工程能力

  • 应用基础

  • 专业领域

    • 服务端

    • 跨端技术

    • Web IDE

    • 中后台

    • 动效渲染

      • Canvas

        • 浅谈 Canvas 性能分析与渲染优化
          • 前言
          • 性能分析
          • 优化策略
            • 分层绘制
            • 通过计算避免无效绘制
            • 离屏绘制
            • 合理使用 API
            • 可交互画布
            • 判断点的位置
            • 获取点击区域
            • 避免使用 canvas 实现文本编辑控件
          • 总结
          • 拓展阅读
      • WebGL

      • WebGPU

      • Web动画

      • 动效方案

    • 可视化

    • 埋点监控

    • 多媒体

    • 桌面技术

    • 游戏互动

    • 编辑器

    • 虚拟化与容器化

    • 设计系统

  • 业务场景

  • 大前端
  • 专业领域
  • 动效渲染
  • Canvas
gahing
2020/03/16
目录

浅谈 Canvas 性能分析与渲染优化

# 前言

接上文 面试官问:什么是 canvas 污染 (opens new window)

本文仅讨论 Canvas 2D

网上这类的文章已经很多了,本文仅仅是一个记录与总结。

推荐文末的拓展阅读

# 性能分析

Canvas 规范 (opens new window)

渲染也是在 UI Render 中进行

context 是一个状态栈

状态包括

  • 当前应用的变形
  • strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation 的值
  • 当前的裁切路径(clipping path)

# 优化策略

# 分层绘制

单一清除策略,适合同层物体矩形框不重叠的情况

如果同层2个物体重叠,上一策略在清除时会清掉另一物体的部分像素。

此时应该判断两者是否重叠,若重叠两者合并得到一个脏矩形,清空脏矩形,并重绘两个物体

更具体的细节可以查看 利用分层优化 HTML5 画布渲染 (opens new window)

# 通过计算避免无效绘制

通过计算判断所绘制元素可见与否,是否需要绘制

计算性能与渲染性能的平衡

# 离屏绘制

将常用图像绘制在另一个 canvas 中

// 在离屏 canvas 上绘制
var canvasOffscreen = document.createElement('canvas');
canvasOffscreen.width = dw;
canvasOffscreen.height = dh;
canvasOffscreen.getContext('2d').drawImage(image, sx, sy, sw, sh, dx, dy, dw, dh);

// 在绘制每一帧的时候,绘制这个图形
context.drawImage(canvasOffscreen, x, y);
1
2
3
4
5
6
7
8

摘自 《Canvas 最佳实践(性能篇)》

还可以借助 worker 进行优化

// main.js
const offscreenCanvas = document.getElementById("c").transferControlToOffscreen();
worker.postMessage(offscreenCanvas, [offscreenCanvas]);


// worker.js 
let ctx, pos = 0;
function draw(dt) {
  ctx.clearRect(0, 0, 100, 100);
  ctx.fillRect(pos, 0, 10, 10);
  pos += 10 * dt;
  requestAnimationFrame(draw);
}

self.onmessage = function(ev) {
  const transferredCanvas = ev.data;
  ctx = transferredCanvas.getContext("2d");
  draw();
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

引自 https://html.spec.whatwg.org/multipage/imagebitmap-and-animations.html#animation-frames

# 合理使用 API

减少耗时 api 的使用

减少改变 context 的状态

避免非法赋值

# 可交互画布

# 判断点的位置

ctx.isPointInPath

使用 isPointinPath 方法检查某点是否在当前路径 path (Path2D) 内

但很多情况下我们没有保存这个 path ,此时自己采用射线法计算判断

# 获取点击区域

addHitRegion

有兼容性问题, Safari 等不支持

# 避免使用 canvas 实现文本编辑控件

这个不用说了, canvas 难以实现

参照 Best practices (opens new window)

# 总结

  1. 将渲染开销转嫁到计算开销
  2. 利用分层渲染复杂场景
  3. 固定内容采用离屏渲染
  4. 合理使用 API 并管理状态

# 拓展阅读

  • 利用分层优化 HTML5 画布渲染 (opens new window)
  • Canvas 最佳实践(性能篇) (opens new window)
  • canvas的优化 (opens new window)
编辑 (opens new window)
#Canvas
上次更新: 2024/09/01, 23:56:56
微前端-从入门到放弃
WebGL 光照

← 微前端-从入门到放弃 WebGL 光照→

最近更新
01
浅谈代码质量与量化指标
08-27
02
快速理解 JS 装饰器
08-26
03
Vue 项目中的 data-v-xxx 是怎么生成的
09-19
更多文章>
Theme by Vdoing | Copyright © 2016-2024 Gahing | 闽ICP备19024221号-1
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式