跳到主要内容

Brightness 亮度

Brightness 是 CSS 兼容的亮度滤镜:把每个通道乘以 brightness。 中性值是 1,大于 1 变亮,小于 1 变暗。

node.cache();
node.filters([Konva.Filters.Brightness]);
node.brightness(1.5); // 亮 50%

和 Brighten 的关系:同一个属性,相反的语义​

这是本页最需要记住的一件事。

Konva 10 起 Konva.Filters.Brighten 被标记为弃用, 官方建议改用 Brightness。但两者共用同一个 brightness() 属性, 计算方式却完全不同:

公式中性值brightness(0) 的结果
Brighten(已弃用)通道 += brightness × 2550不变
Brightness(推荐)通道 ×= brightness1全黑

所以只把滤镜名换掉、不改数值,画面会静默出错。 下面是在真实浏览器里对 rgb(100,100,100) 的纯色块逐像素采样的结果:

写法采样到的颜色
Brighten + brightness(0)100,100,100(不变)
Brightness + brightness(0)0,0,0(全黑)
Brighten + brightness(0.5)228,228,228(加了 127.5)
Brightness + brightness(0.5)50,50,50(乘了 0.5)
Brighten + brightness(1)255,255,255(加满溢出)
Brightness + brightness(1)100,100,100(不变)

迁移时的换算不是简单的加一:Brighten 是绝对增量,Brightness 是相对比例, 两者数学上不等价,对暗部和亮部的影响方式根本不同。 只能按视觉效果重新调,不能靠公式换算。

未设置时的默认值有个陷阱​

brightness 这个属性的访问器由 Brighten 注册,默认值是 0。 但 Brightness 滤镜在读取时做了特殊处理: 如果这个属性从未被设置过,它按 1 计算。

实测可以看到这个不一致:

new Konva.Rect({}).brightness(); // 读到 0
// 但是:
node.filters([Konva.Filters.Brightness]);
// 不设 brightness → 画面不变(按 1 处理)
node.brightness(0);
// 显式设成 0 → 全黑

也就是说 node.brightness() 读到的 0 和"当前实际生效的亮度"不是一回事。 不要依赖读取这个属性来判断当前状态,自己维护一份值。

常见问题​

我该用 Brightness 还是 Brighten?​

新代码一律用 Brightness。Brighten 已弃用, 而且乘法的行为和 CSS 的 filter: brightness() 一致, 在和 CSS 滤镜混用时不会打架。

存量代码不急着改——Brighten 目前仍然可用。 要改的话必须同时调整数值并目视确认, 批量替换滤镜名是最危险的做法。

为什么加了滤镜没反应?​

九成是忘了 cache()。Konva 的滤镜作用在缓存画布上, 没有缓存就没有可供滤镜处理的像素数据,filters() 设了也没用。

node.cache(); // 必须
node.filters([Konva.Filters.Brightness]);
node.brightness(1.5);

另外,改了节点的尺寸、内容之后需要重新 cache(), 否则滤镜还作用在旧的缓存上。

亮度调到很大为什么图片变成白块?​

乘法会让通道值超过 255,超出部分被裁切到 255。 原图里稍亮的区域会先饱和成纯白,细节就丢了——这是不可逆的。

想保留亮部细节,用 Contrast 或 HSL 的 luminance 更合适, 它们对已经很亮的像素更温和。

性能提示​

Brightness 是最便宜的滤镜之一:每个像素三次乘法和三次比较, 没有邻域采样、没有额外内存。成本几乎全在 cache() 本身—— 建一张与节点等大的离屏画布,并在其上重绘一遍。

所以真正要控制的是缓存的面积和频率,不是滤镜本身:

  • 只给需要滤镜的节点加缓存,不要图省事缓存整个图层。
  • 节点被放大显示时,cache({ pixelRatio: 2 }) 会让缓存画布面积变成四倍, 滤镜耗时也随之四倍。不需要高清就别提高它。
  • 做亮度动画(比如悬停渐亮)时,不要每帧 cache()。 缓存一次,之后只改 brightness() 并 layer.draw()—— Konva 会在已有缓存上重跑滤镜,不会重建缓存。
  • 如果只是要一个整体变亮的视觉效果而不需要像素级控制, 用 CSS 滤镜字符串通常更快, 它走的是浏览器的原生实现而不是 JS 循环。