canvas实时滤镜核心是直接操作像素数组,流程为读取→计算→写回,不依赖外部库;需确保图像就绪再读像素,画布尺寸匹配原图,跨域图片设crossorigin="anonymous",遍历imagedata.data时步长为4。

Canvas实时滤镜的核心是直接操作像素数组,整个过程围绕 读取→计算→写回 展开,不依赖外部库,所有逻辑都在内存中完成。
图像数据准备要稳准
无论来源是 <img> 还是 <video></video>,必须等图像真正就绪再读像素:
-
<img>严格监听onload事件,之后再调用drawImage -
<video></video>推荐监听loadeddata或canplay,避免黑帧;iOS 上需加playsinline和muted - 画布宽高必须与原始图像一致,否则
getImageData的坐标会越界 - 跨域图片(如 CDN 图)务必设置
crossOrigin="anonymous",否则读像素会报安全错误
像素遍历与通道处理有讲究
ImageData.data 是一个 Uint8ClampedArray,长度为 width × height × 4,按 R→G→B→A 顺序排列。遍历时注意:
用户要生成可打印的中文字帖/练习纸、导出多页 A4 PDF 报告,或把 SVG 设计稿零误差还原到 Canvas 时使用。本技能是「Canvas 内容工厂闭环」的总控,编排:网格渲染引擎(13 种教育网格+拼音标注) → 多页 PDF 导出(A4 合成) → SVG 精准复刻(坐标误差<0.001px)。触发词:生成字帖、练习纸、导出 PDF、SVG 转 Canvas、印刷级还原、A4 报告、米字格田字格。
- 步长固定为 4:用
for (let i = 0; i ,直接定位每个像素的 R、G、B、A - R/G/B 通道分别处理,A 通道通常保持 255(不透明)或按需调整
- 灰度推荐加权法:
gray = (r * 0.299 + g * 0.587 + b * 0.114) | 0,比简单平均更符合人眼感知 - 反色只需三行:
data[i] = 255 - data[i]、data[i+1] = 255 - data[i+1]、data[i+2] = 255 - data[i+2] - 提前缓存
data.length,避免循环中反复读属性;不在循环内创建新对象或调用函数
卷积类滤镜(如浮雕)需边界处理
浮雕这类基于邻域运算的滤镜,不能直接遍历全部像素:
- 只处理非边界像素:x 范围为
1到width−2,y 为1到height−2 - 常用浮雕核如
[1, 1, 0, 1, 0, −1, 0, −1, −1],对每个像素取周围 3×3 区域加权求和 - 结果统一加 128 偏移(让中性灰落在 128),再用
Math.max(0, Math.min(255, value))截断 - 写回时注意索引:第
(y × width + x)个像素,R/G/B 分别对应index×4+0/1/2
实时渲染得控节奏
高频读写像素极易卡顿,必须主动节制:
- 用
requestAnimationFrame驱动,而非setInterval,与屏幕刷新率同步 - 视频流可设帧率限制,例如每 3 帧处理一次,用计数器或
performance.now()控时间间隔 - 大图先缩放(如 640×480)再处理,视觉影响小,性能提升明显
- 只处理可视区域或用户指定 ROI(感兴趣区域),跳过冗余计算
- 主线程持续掉帧时,考虑用 Web Worker 拆分计算,或迁移到 WebGL 加速复杂滤镜










