You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在HTML5 Canvas中对指定路径区域的图像应用亮度滤镜

Canvas局部区域亮度调整方案

可以实现仅对图像局部区域提升亮度,你之前的代码无效是因为用透明描边路径的方式不对——滤镜是作用在实际绘制的像素内容上的,而非路径本身。下面提供两种可行的实现方案:

方案一:使用裁剪路径(clip)

通过裁剪路径限定滤镜的作用范围,步骤如下:

  1. 重置画布并重新绘制原图
  2. 创建并设置裁剪路径,只保留需要调整的区域
  3. 应用亮度滤镜后重新绘制原图(此时仅裁剪区域内的内容会被滤镜处理)
  4. 重置裁剪路径和滤镜,避免影响后续绘制

修改后的核心代码:

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)

利用合成模式限定滤镜作用区域,步骤如下:

  1. 重新绘制原图
  2. 绘制需要调整亮度的区域形状(填充)
  3. 设置合成模式为source-atop,此时后续绘制的内容只会出现在已有像素的区域内
  4. 应用滤镜后绘制原图,仅形状覆盖的区域会被滤镜处理

核心代码示例:

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 05:10:20