如何在Konva或原生Canvas中实现背景模糊/毛玻璃效果?

原生Canvas实现方案
核心思路是先截取矩形覆盖区域的底层像素,模糊后再叠加半透填充层,步骤如下:
- 完成所有z轴低于半透明矩形的底层内容绘制后,暂停上层绘制
- 调用
getImageData(x, y, width, height)截取半透明矩形对应区域的画布像素,若画布做过高清适配,坐标和尺寸需要乘以devicePixelRatio做换算 - 创建离屏Canvas,将截取到的ImageData绘制到离屏Canvas上,给离屏Canvas元素设置
filter: blur(Npx)实现高斯模糊,也可以手动实现卷积模糊算法适配低版本浏览器 - 将模糊后的离屏Canvas内容绘制到主画布的对应坐标处,最后绘制原需求的半透明填充矩形即可
注意:如果底层内容是动态变化的,每次底层更新后都需要重新执行截取、模糊、绘制的流程,避免毛玻璃效果和底层内容脱节
Konva实现方案
Konva内置了滤镜、裁剪、缓存能力,实现起来更简洁,步骤如下:
- 将所有z轴低于毛玻璃矩形的元素统一放到同一个
Konva.Group或Konva.Layer中作为底层内容组 - 创建毛玻璃容器Group,设置和目标半透明矩形一致的坐标、宽高,同时设置
clip属性将容器裁剪为对应矩形尺寸 - 在容器内添加底层内容组的克隆实例,调整克隆实例的坐标为负的毛玻璃容器坐标,保证内容位置和底层完全对齐,再给克隆实例添加
Konva.Filters.Blur滤镜,调整模糊半径到预期效果 - 在容器最上层添加半透明填充矩形,调整填充透明度即可
- 若底层内容动态更新,只需调用容器的
cache()方法重新缓存即可自动更新毛玻璃效果
Konva示例代码
// 初始化底层内容组,所有z轴低于毛玻璃的元素都放在这里 const backgroundGroup = new Konva.Group(); // 往backgroundGroup中添加底层的图形、图片等内容... mainLayer.add(backgroundGroup); // 毛玻璃矩形参数配置 const glassParams = { x: 120, y: 80, width: 240, height: 180, fill: 'rgba(255, 255, 255, 0.35)', blurRadius: 10 }; // 创建毛玻璃裁剪容器 const glassContainer = new Konva.Group({ x: glassParams.x, y: glassParams.y, clip: { x: 0, y: 0, width: glassParams.width, height: glassParams.height } }); // 添加对齐后的模糊底层内容 const blurredBg = backgroundGroup.clone({ x: -glassParams.x, y: -glassParams.y, filters: [Konva.Filters.Blur], blurRadius: glassParams.blurRadius }); glassContainer.add(blurredBg); // 添加半透填充层 const glassFill = new Konva.Rect({ width: glassParams.width, height: glassParams.height, fill: glassParams.fill }); glassContainer.add(glassFill); mainLayer.add(glassContainer); mainLayer.draw();
内容的提问来源于stack exchange,提问作者hypnomaki
相关产品推荐
相关产品推荐

