如何在HTML5 Canvas中对指定路径区域的图像应用亮度滤镜
Canvas局部区域亮度调整方案
可以实现仅对图像局部区域提升亮度,你之前的代码无效是因为用透明描边路径的方式不对——滤镜是作用在实际绘制的像素内容上的,而非路径本身。下面提供两种可行的实现方案:
方案一:使用裁剪路径(clip)
通过裁剪路径限定滤镜的作用范围,步骤如下:
- 重置画布并重新绘制原图
- 创建并设置裁剪路径,只保留需要调整的区域
- 应用亮度滤镜后重新绘制原图(此时仅裁剪区域内的内容会被滤镜处理)
- 重置裁剪路径和滤镜,避免影响后续绘制
修改后的核心代码:
function setBrightness(value) { // 重置画布,重新绘制原图 ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(image, 0, 0); // 创建裁剪路径 let clipPath = new Path2D(); clipPath.arc(170, 60, 50, 0, 2 * Math.PI); ctx.save(); // 保存当前画布状态 ctx.clip(clipPath); // 设置裁剪路径 // 应用亮度滤镜,重新绘制原图(仅裁剪区域生效) ctx.filter = `brightness(${value + 100}%)`; ctx.drawImage(image, 0, 0); // 恢复画布状态,重置滤镜和裁剪 ctx.restore(); ctx.filter = 'none'; }
方案二:使用全局合成模式(globalCompositeOperation)
利用合成模式限定滤镜作用区域,步骤如下:
- 重新绘制原图
- 绘制需要调整亮度的区域形状(填充)
- 设置合成模式为
source-atop,此时后续绘制的内容只会出现在已有像素的区域内 - 应用滤镜后绘制原图,仅形状覆盖的区域会被滤镜处理
核心代码示例:
function setBrightness(value) { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(image, 0, 0); // 绘制目标区域形状 ctx.fillStyle = 'white'; // 颜色不影响,只要是不透明填充即可 let shapePath = new Path2D(); shapePath.arc(170, 60, 50, 0, 2 * Math.PI); ctx.fill(shapePath); // 设置合成模式,后续绘制仅作用于已有像素区域 ctx.globalCompositeOperation = 'source-atop'; // 应用滤镜绘制原图 ctx.filter = `brightness(${value + 100}%)`; ctx.drawImage(image, 0, 0); // 重置合成模式和滤镜 ctx.globalCompositeOperation = 'source-over'; ctx.filter = 'none'; }
完整可运行代码
Brightness<input id="slider" type="range" min="-100" max="400" value="0" step="1"></input><span id="val"></span><br> <canvas id="canvas"></canvas> <script> const imageUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Carl_Friedrich_Gauss_1840_by_Jensen.jpg/800px-Carl_Friedrich_Gauss_1840_by_Jensen.jpg"; const ctx = canvas.getContext("2d"); const slider = document.getElementById('slider'); const val = document.getElementById('val'); let slideOldVal = 0; ctx.fillText("Please wait loading image..",20,20); const image = new Image; image.src = imageUrl; image.onload = () => { canvas.width = image.width; canvas.height = image.height; ctx.drawImage(image, 0, 0); val.textContent = slider.value; slider.addEventListener("input", () => { if (slider.value !== slideOldVal) { setBrightness(Number(slider.value)); } val.textContent = slider.value; slideOldVal = Number(slider.value); }); } // 使用裁剪路径的实现 function setBrightness(value) { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.drawImage(image, 0, 0); let clipPath = new Path2D(); clipPath.arc(170, 60, 50, 0, 2 * Math.PI); ctx.save(); ctx.clip(clipPath); ctx.filter = `brightness(${value + 100}%)`; ctx.drawImage(image, 0, 0); ctx.restore(); ctx.filter = 'none'; } </script>
内容的提问来源于stack exchange,提问作者Him
相关产品推荐
相关产品推荐

