Safari浏览器中Canvas绘制图像的阴影被截断该如何解决?
问题原因
Safari 对 Canvas 的 shadow 相关属性的渲染逻辑和 Chrome 存在差异:Safari 计算绘制元素的可视区域时,默认不会将 shadowBlur 产生的模糊延伸范围完全纳入计算,会直接裁剪元素原始边界外的阴影部分,导致阴影被截断。
修复方案
- 方案1:预留阴影边距
在绘制图像时,给图像的上下左右都预留至少等于shadowBlur数值的空白边距,同时保证图像的绘制位置距离 Canvas 画布边界的距离大于shadowBlur值,避免阴影被画布或 Safari 的默认裁剪区域截断。
以你的代码为例,shadowBlur为30,你可以调整绘制坐标,确保图像的所有边缘都有至少30px的空白空间:
ctx.shadowColor = 'white'; ctx.shadowBlur = 30; // 确保x/y坐标、图像右边缘和下边缘距离画布边界都≥30px即可 ctx.drawImage(ship, 100, 100, 50, 50);
- 方案2:使用 drop-shadow 滤镜(推荐)
直接替换 shadow 相关属性为 Canvas filter 的 drop-shadow,该属性在各浏览器的渲染逻辑更统一,不会出现 Safari 下的截断问题:
// drop-shadow参数顺序:水平偏移、垂直偏移、模糊半径、颜色,长度需带单位 ctx.filter = 'drop-shadow(0 0 30px white)'; ctx.drawImage(ship, 100, 100, 50, 50); // 绘制完成后重置滤镜,避免影响后续其他元素的绘制 ctx.filter = 'none';
- 方案3:离屏 Canvas 中转
如果需要兼容老旧版本 Safari,可以用离屏 Canvas 预先承载图像和阴影,再绘制到主画布:
// 创建离屏Canvas,尺寸 = 原图尺寸 + 2倍模糊半径 const offscreenCanvas = document.createElement('canvas'); const offCtx = offscreenCanvas.getContext('2d'); const blurSize = 30; offscreenCanvas.width = 50 + blurSize * 2; offscreenCanvas.height = 50 + blurSize * 2; // 把原图绘制到离屏Canvas中心,预留阴影空间 offCtx.drawImage(ship, blurSize, blurSize, 50, 50); // 主画布开启阴影,绘制离屏Canvas ctx.shadowColor = 'white'; ctx.shadowBlur = blurSize; ctx.drawImage(offscreenCanvas, 100 - blurSize, 100 - blurSize);
内容的提问来源于stack exchange,提问作者Fin
相关产品推荐
相关产品推荐

