如何在HTML Canvas及WebGL中实现图片边缘模糊淡入效果
在Canvas中实现图片边缘模糊淡入效果
Canvas 2D 快速实现方案
不需要复杂逻辑,通过图层叠加就能实现仅边缘模糊的效果:
- 绘制清晰原图
先将原图按正常尺寸绘制到画布,作为底层清晰内容:
const canvas = document.getElementById('myCanvas'); const ctx = canvas.getContext('2d'); const img = new Image(); img.src = '你的图片路径'; img.onload = () => { canvas.width = img.width; canvas.height = img.height; // 绘制清晰原图 ctx.drawImage(img, 0, 0); // 添加边缘模糊效果 addEdgeBlur(ctx, img.width, img.height); };
- 叠加模糊边缘层
核心思路:先绘制模糊后的完整图片,再用径向渐变遮罩“保留边缘、挖去中间”,最后叠加到原图上:
function addEdgeBlur(ctx, width, height) { // 1. 创建离屏画布绘制模糊后的图片 const offscreenCanvas = document.createElement('canvas'); offscreenCanvas.width = width; offscreenCanvas.height = height; const offCtx = offscreenCanvas.getContext('2d'); offCtx.filter = 'blur(8px)'; offCtx.drawImage(img, 0, 0); // 2. 创建径向渐变遮罩:中间透明,边缘不透明 const gradient = ctx.createRadialGradient( width / 2, height / 2, width * 0.4, width / 2, height / 2, width / 2 ); gradient.addColorStop(0, 'transparent'); gradient.addColorStop(1, 'rgba(0,0,0,1)'); // 3. 用遮罩裁剪模糊层,只保留边缘部分 ctx.save(); ctx.globalCompositeOperation = 'destination-in'; ctx.fillStyle = gradient; ctx.fillRect(0, 0, width, height); ctx.drawImage(offscreenCanvas, 0, 0); ctx.restore(); }
调整径向渐变的width * 0.4参数可以控制模糊边缘的宽度:数值越小,模糊边缘越宽;反之则越窄。
WebGL 高性能方案(适合大尺寸/动态场景)
通过自定义片段着色器直接实现边缘模糊,性能比Canvas 2D离屏渲染更优:
- 顶点着色器(基础纹理映射)
attribute vec2 a_position; attribute vec2 a_texCoord; varying vec2 v_texCoord; void main() { gl_Position = vec4(a_position, 0.0, 1.0); v_texCoord = a_texCoord; }
- 片段着色器(实现边缘模糊+淡入)
核心逻辑:根据像素到图片中心的距离,动态调整模糊程度和透明度:
precision mediump float; uniform sampler2D u_texture; uniform vec2 u_resolution; varying vec2 v_texCoord; // 简易高斯模糊采样函数 vec4 blur(sampler2D tex, vec2 uv, vec2 resolution, float radius) { vec4 color = vec4(0.0); float total = 0.0; for (float x = -radius; x <= radius; x++) { for (float y = -radius; y <= radius; y++) { float weight = (1.0 - abs(x)/radius) * (1.0 - abs(y)/radius); color += texture2D(tex, uv + vec2(x, y)/resolution) * weight; total += weight; } } return color / total; } void main() { vec2 center = vec2(0.5, 0.5); float dist = distance(v_texCoord, center); // 控制模糊过渡范围:0.4为清晰区域半径,0.5为模糊区域边界 float blurRadius = smoothstep(0.4, 0.5, dist) * 8.0; // 边缘淡入透明度控制 float alpha = smoothstep(0.5, 0.45, dist); vec4 blurredColor = blur(u_texture, v_texCoord, u_resolution, blurRadius); vec4 originalColor = texture2D(u_texture, v_texCoord); // 混合清晰原图与模糊边缘 gl_FragColor = mix(originalColor, blurredColor, 1.0 - alpha); gl_FragColor.a = alpha; }
修改smoothstep(0.4, 0.5, dist)的参数可以调整模糊边缘的过渡宽度,*8.0对应你需要的最大模糊半径(8px)。
注意事项
- Canvas 2D方案适合快速验证、小尺寸图片场景;WebGL方案适合大图片或需要实时更新的交互场景。
- 两种方案都可通过调整参数匹配示例图的效果,多测试几组数值即可达到理想状态。
内容的提问来源于stack exchange,提问作者slowloris
相关产品推荐
相关产品推荐

