01 · 离屏是什么意思
const tile = new OffscreenCanvas(180, 100);这块画布不直接作为页面元素显示,但可以取得 2D 上下文并绘制。
点击生成海报:同一块离屏图像绘制三次,位置和缩放各不相同。
const tile = new OffscreenCanvas(180, 100);这块画布不直接作为页面元素显示,但可以取得 2D 上下文并绘制。
const brush = tile.getContext('2d');
brush.fillRect(0, 0, 180, 100);brush 与 ctx 分别属于两块画布,状态不会互相替代。
ctx.drawImage(tile, 230, 60, 144, 80);drawImage 不只接收图片,也能接收另一块画布;这里指定目标位置与显示大小。
把画布改为 OffscreenCanvas 后,绘制就一定在后台线程运行吗?三次 drawImage 会自动建立三个 HTML 元素吗?
都不会。本例仍在主线程执行;要把工作移到 Worker,需要另行组织线程与消息。三次绘制只是向同一可见画布写入像素,没有创建三个可独立点击的 DOM 元素。
现代绘图路径:OffscreenCanvas 可与 Worker 配合;本例仅展示离屏复用,不宣称已经实现多线程加速。
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>先在另一块画布上画,再合成</title>
<style>
body { margin:16px; color:#183347; background:white; font:20px/1.5 "Times New Roman",SimSun,serif; }
h1,h2 { font-family:"Times New Roman",SimHei,sans-serif; }
button,input,select { font:inherit; max-width:100%; }
button { margin:4px 0; cursor:pointer; }
pre { white-space:pre-wrap; overflow-wrap:anywhere; font:18px/1.5 Consolas,SimSun,monospace; }
:focus-visible { outline:3px solid #b56220; outline-offset:3px; }
canvas { display:block; width:100%; max-width:640px; border:1px solid #abc3c5; margin-top:12px; }
</style>
</head>
<body>
<button id="draw" type="button">生成海报</button>
<canvas id="poster" width="640" height="300">三张黄梅戏活动卡片。</canvas>
<p id="state" role="status">
</p>
<script>
const canvas = document.querySelector('#poster');
const ctx = canvas.getContext('2d');
document.querySelector('#draw').addEventListener('click', () => {
const supported = typeof OffscreenCanvas === 'function';
const tile = supported ? new OffscreenCanvas(180, 100) : document.createElement('canvas');
tile.width = 180; tile.height = 100;
const brush = tile.getContext('2d');
brush.fillStyle = '#166b60'; brush.fillRect(0, 0, 180, 100);
brush.fillStyle = 'white'; brush.font = '24px SimSun';
brush.fillText('黄梅戏', 20, 56);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(tile, 20, 20);
ctx.drawImage(tile, 230, 60, 144, 80);
ctx.drawImage(tile, 410, 100, 216, 120);
document.querySelector('#state').textContent = supported ? '使用 OffscreenCanvas 合成' : '使用普通离屏 canvas 后备方案';
});
</script>
</body>
</html>