Skip to main content

如何一次对多个图形应用透明度?

能否同时对多个图形使用不透明度(opacity)?

你可以使用 opacity 属性来改变任何 Konva 节点的 alpha 通道。由于 canvas 的工作原理,所有的图形都具有各自独立的不透明度值。

这意味着,如果你有一个包含多个图形的组,并且该组设置了 group.opacity(0.5),它的效果与你让每个内部图形都设置 shape.opacity(0.5) 且组的透明度保持 group.opacity(1) 是完全一样的。这会导致这些图形的重叠区域变得透明。

如果我们不希望看到透明图形的重叠区域怎么办?

有一种办法可以修正这种默认行为。你只需使用 group.cache() 缓存整个组。缓存组会将其转换为位图,并绘制到外部画布上。在下一次绘制调用时,Konva 会用这个生成的画布来绘制整个组,并将不透明度应用于整个图像。

因此,在 Konva 为这样的组生成位图缓存的同时,它会忽略内部形状的透明度,只绘制内部形状的内容。

请记住:如果某个组被缓存,那么它有一些缓存节点的限制。比如你对内部的形状属性进行了更改,你需要重新缓存该组。这个操作较为耗费性能,不建议频繁使用,比如在动画中或每次鼠标移动时都进行。

在下面的示例中,左侧展示默认行为,右侧展示缓存后修正的行为。

试着拖动两组,观察透明度的效果差异。左侧组展示默认的行为,具有可见的重叠区域;右侧组则通过缓存,使整个组作为一个单一的透明单元处理。

import Konva from 'konva';
// 舞台设置
const width = window.innerWidth;
const height = window.innerHeight;

const stage = new Konva.Stage({
  container: 'container',
  width: width,
  height: height,
});

const layer = new Konva.Layer();
stage.add(layer);

// 创建一个包含两个重叠图形的默认组
const group1 = new Konva.Group({
  opacity: 0.5,
  x: 50,
  y: 50,
  draggable: true,
});
group1.add(
  new Konva.Rect({
    width: 100,
    height: 100,
    fill: 'red',
  })
);
group1.add(
  new Konva.Circle({
    x: 100,
    y: 100,
    radius: 70,
    fill: 'green',
  })
);
layer.add(group1);

// 创建第二个组
const group2 = group1.clone({ x: 250 });
layer.add(group2);

// 要改变不透明度行为,只需要缓存整个组
group2.cache();