canvas主要有2d和webgl两种上下文:2d用于ui图形、图表等二维绘图,api直观易用;webgl面向高性能3d渲染,需手动管理gpu资源,二者不可混用,且须适配dpr以确保清晰显示。

Canvas 上下文类型直接决定你能画什么、怎么画、性能如何,不是“选一个就行”,而是要按目标场景匹配。
2D 上下文:适合 UI 图形、图表和轻量动画
这是最常用也最易上手的上下文,提供 fillRect、arc、drawImage、text 等命令式绘图 API。它基于 CPU 渲染,逻辑直观,调试方便,适合绘制按钮、进度条、折线图、文字标签等。
- 不支持深度、光照、纹理采样等 3D 概念,纯二维像素操作
- 抗锯齿默认开启,但可通过
ctx.imageSmoothingEnabled = false关闭以提升清晰度(尤其图标/像素风) - 文字渲染受
textBaseline和textAlign控制,高 DPR 设备需配合ctx.scale(dpr, dpr)避免偏移 - 多次调用
fillText或频繁清空重绘时,注意避免 layout thrashing —— 建议用clearRect而非重设width/height
WebGL 上下文:面向高性能图形与复杂视觉效果
它暴露的是底层 GPU 接口,本质是运行着色器程序(vertex + fragment shader),适合游戏、粒子系统、3D 可视化、滤镜处理等对性能和效果要求高的场景。
- 必须手动管理缓冲区、着色器编译、纹理绑定、状态切换,学习成本高
- 初始化可能失败:旧版 Safari 不支持 WebGL2,IE 完全不支持,企业内网常禁用硬件加速 → 务必检查
getContext('webgl')返回值是否为null - 配置项影响大:
antialias: false可提升低端设备帧率;preserveDrawingBuffer: true才能安全调用readPixels或toDataURL - 坐标系是归一化设备坐标(NDC),x/y ∈ [-1, 1],需自己搭建矩阵栈或使用库(如 glMatrix)
上下文不可混用:一次绑定,终身有效
Canvas 元素一旦成功获取某类上下文(比如先调了 getContext('webgl')),后续再请求其他类型(如 '2d')将返回 null。这不是浏览器 bug,而是规范强制行为。
- 不要在同一个
<canvas></canvas>上反复切换上下文类型 - 若需同时用 2D 标注 + WebGL 渲染,应使用两个 canvas 叠加:底层 WebGL,上层 2D 用于 UI 层
- 检测失败时别静默跳过,加一行
if (!ctx) { console.error('Context unavailable'); return; }
高分辨率设备渲染:上下文之外的关键环节
即使上下文选对了,忽略设备像素比(DPR)也会导致模糊、线条虚化、文字错位。这和上下文类型无关,但直接影响最终输出质量。
- 设置 canvas 实际尺寸:用
canvas.width = canvas.offsetWidth * dpr,而非仅改 CSS - 缩放绘图坐标系:
ctx.scale(dpr, dpr)后,所有 x/y 坐标仍按 CSS 像素写,逻辑不变 - WebGL 中需同步调整 viewport:
gl.viewport(0, 0, width * dpr, height * dpr) - iOS Safari 在 tab 切换或页面未激活时可能延迟初始化,建议监听
visibilitychange重置 canvas
不复杂但容易忽略。选对上下文只是第一步,初始化健壮性、DPR 适配、错误兜底,才是让 Canvas 稳定落地的关键。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











