HTML5 Canvas 的玻璃折射是像素级偏移模拟的视觉假象,非真实光学计算;核心流程为:离屏绘制背景→依灰度位移图计算采样坐标→getImageData/putImageData高效合成;动态化靠sin波或鼠标位移场驱动位移图更新;性能优化需局部渲染、降采样或改用backdrop-filter,复杂场景应转向WebGL。

HTML5 Canvas 本身不提供“玻璃折射”这类声明式滤镜,所谓动态折射效果,是靠像素级采样与偏移模拟出来的视觉假象,不是真实光学计算。它适合中低复杂度场景(如按钮悬停、卡片浮层),但无法替代 WebGL 级别的物理渲染。
用位移贴图模拟折射核心流程
本质是:把背景图预先画在离屏 canvas 上,再对主 canvas 的每个像素,根据一张灰度图(位移贴图)决定从背景图哪个位置取色。
- 准备两张图:一张背景图(需设 crossOrigin="anonymous" 防跨域报错),一张位移贴图(灰度图,越亮表示向右/下偏移越大)
- 读取位移图的 R/G 通道值,转为偏移量:dx = (r - 128) × scale,scale 通常取 0.2~0.6,避免偏移过大导致黑边
- 计算目标采样坐标:srcX = clamp(x + dx, 0, width-1),同理算 srcY;clamp 是防止越界
- 用 getImageData() 读背景像素,putImageData() 批量写回结果——千万别用 fillRect 逐点画,性能会断崖下跌
让折射“动起来”的关键技巧
静态玻璃没质感,动态才像真玻璃。常见做法是让位移贴图随时间或鼠标变化:
将 Markdown 文章转换为微信公众号兼容的纯 HTML 格式。当用户要求"转成微信格式"、"生成公众号文章 HTML"、"排版到微信草稿箱"、"微信粘贴格式"时触发。输出带内联样式的纯 HTML,微信编辑器可直接渲染,无需额外适配。支持标题、段落、列表、粗体、行内代码、表格、引用块、代码块、配图的完整转换。
- 用 Math.sin(time + x * 0.01) × 30 生成波动位移,叠加在原贴图上,形成水波纹式折射扰动
- 监听 mousemove,以鼠标为中心生成圆形位移衰减场:dx = (mouseX - x) / distance × intensity,distance 越大衰减越快
- 每帧只更新位移图的 ImageData.data 数组,不重建 canvas,减少内存分配
- 动画必须用 requestAnimationFrame 驱动,避免 setInterval 导致掉帧或卡顿
性能瓶颈与务实替代方案
Canvas 像素操作在 800×600 以上分辨率就明显吃力,尤其还要实时合成多层。别硬扛:
- 限制折射区域:只对 UI 元素(如一个 card 容器)做局部 canvas 渲染,而非全屏
- 降采样处理:用一半尺寸做位移计算,再放大绘制,视觉损失小,性能提升明显
- 轻量需求直接用 backdrop-filter: blur(6px) contrast(1.1) 模拟毛玻璃感——它不折射,但够用且零成本
- 需要真实反射+折射交互(比如拖拽玻璃球),请转向 Three.js + ShaderMaterial,Canvas 不是为此设计的
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!










