使用组的子元素来夹住或覆盖其他元素

Use child element of group to clip or cover other element

我正在制作 SVG 蓝图,但 运行 遇到了一些问题。

我认为问题的出现是因为我不得不将两个半透明元素组合在一起,这样当它们重叠时,它们看起来就像是一个实体单元。

Here is an MCVE, which should be viewed in Chrome since I didn't use "absolute" values for one element's transform-origin.

leftRoomFill.style.fill = '#fff';
leftRoomDoorFill.style.fill = '#fff';
leftRoomFill.style.opacity = '1';
leftRoomDoorFill.style.opacity = '1';
console.log(window.getComputedStyle(leftRoomFill).opacity);
console.log(window.getComputedStyle(leftRoomDoorFill).opacity);

问题是,即使它正在记录以控制台元素的不透明度设置为 1,看起来元素的不透明度似乎根本没有改变,仍然是 0。

我已经尝试了以下方法,这进一步巩固了我的信念,即问题是不透明的问题。

rightRoomFill.style.zIndex = '1';
leftRoomFill.style.zIndex = '2';
leftRoomDoorFill.style.zIndex = '2';

有人知道为什么上面的代码似乎没有任何效果吗?

我想做的是使用门填充元素裁剪门延伸到的房间的填充。

我知道我可以简单地取消填充元素的组合并使用没有不透明度的颜色,但我真的很想保持能够使用半透明填充的灵活性。

有什么想法吗?

不清楚你在问什么。为什么你认为房间的不透明度为 0?在 Chrome 中它们对我来说变得可见(绿色)。所以“1”的价值对我来说似乎是正确的。应该发生什么却没有发生?

关于您的 zIndex 问题:您可能必须使用不同的方法。 z-index 目前不适用于 SVG 元素。它已添加到 SVG 2 中,但我认为还没有任何浏览器支持它。

zIndex 属性 不会重新排列 SVG 元素(至少现在还没有)。

您似乎希望在将鼠标悬停在右侧房间楼层上时,让左侧房间组的门填充 "cover" 右侧房间楼层。但是,您只想拥有一个门填充的副本,在这种情况下,它与门打开的楼层(即左侧楼层)组合在一起。您似乎不想在 <defs> 部分创建主门填充,然后使用 <use> 元素多次复制它。虽然我不确定这是最好的策略,但如果您真的想这样做,一种方法是将当前可见的地板(即鼠标悬停的地板)移动到 SVG 地板堆栈的可见底部,即到楼层父节点的代码顶部。每当将鼠标悬停在特定楼层上时,您都可以使用以下代码 运行 执行此操作:myFloorNode.parentNode.insertBefore(myFloorNode, myFloorNode.parentNode.firstChild);。然后与该楼层重叠的任何其他门填充将 "cover" 它,"cutting out" 楼层的那一部分。

我觉得这种方法有点混乱,因为它需要不断地调整地板元素。这不一定是致命的。然而,这确实让我有点不安,因为如果重新洗牌变得更加复杂,它可能会造成一些混乱。它还要求您将门填充设置为完全不透明,这可能会或可能不会被接受。无论如何,这只是我的直觉,具体取决于您如何实施它。

您可以通过如下修改代码来简单地实施此策略:

function setFillOpacity(){
  this.style.opacity = '0.5';

  // *** add the following line:
  this.parentNode.insertBefore(this, this.parentNode.firstChild);

  if (this.id === 'right-room-fill'){...

但是请注意,仅通过这一更改,即使门冲程处于 "open" 位置,有时您的门填充似乎处于 "closed" 位置。它似乎最终会自行解决,通过 "open" 在门关闭然后重新打开的动态动画结束时播放。但是,我认为您必须处理代码以确保门 fill starts 在正确的位置。我会把这个问题留给你解决。