如何在 div 上构建 SVG 叠加层以给每一侧一个放置目标?

问题描述 投票:0回答:1

我正在尝试创建一个叠加层以放置在 任意大小

div
上,为其提供四个放置目标 - 每个对应于
div
矩形的一侧。放置目标的几何形状应该使得放置的元素将到达 div 的 closest 侧。这意味着短而宽的
div
将具有梯形顶部和底部放置目标以及三角形左右放置目标,而高而窄的 div 将具有三角形顶部和底部放置目标以及梯形左右放置目标(以及正方形div 将包含所有三角形)。

这是我尝试用于覆盖的嵌套 SVG 以及它覆盖的 HTML 及其 CSS:


#overlaid {
  position: relative;
  width: 450px;
  height: 300px;
  border: 5px solid lightgray;
}

#overlay {
  --overlay-visibility: visible;

  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
  z-index: 999999;
  visibility: var(--overlay-visibility, hidden);
}

svg {
  stroke: black;
}

path:hover {
  fill: yellow;
}
<div id="overlaid">
  <svg id="overlay">

    <svg viewbox="0 0 100 50" preserveAspectRatio="xMidYMin">
      <path id="above-zone" d="M 0,0
                               L 100,0 50,50
                               z" fill="rgba(0,127,255,0.5)" />
    </svg>

    <svg viewbox="0 0 50 100" preserveAspectRatio="xMinYMid">
      <path id="before-zone" d="M 0,0
                                L 50,50 0,100
                                z" fill="rgba(255,0,127,0.5)" />
    </svg>

    <svg viewbox="0 0 50 100" preserveAspectRatio="xMaxYMid">
      <path id="after-zone" d="M 50,0
                               L 50,100 0,50
                               z" fill="rgba(0,255,127,0.5)" />
    </svg>

    <svg viewbox="0 0 100 50" preserveAspectRatio="xMidYMax">
      <path id="below-zone" d="M 0,50
                               L 50,0 100,50
                               z" fill="rgba(255,127,0,0.5)" />
    </svg>

  </svg>
</div>

我有两个问题不知道如何解决。首先,当任意大小的

#overlaid {
  position: relative;
  width: 450px;
  height: 300px;
  border: 5px solid lightgray;
}

#overlay {
  --overlay-visibility: visible;

  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  width: 100%;
  height: 100%;
  z-index: 999999;
  visibility: var(--overlay-visibility, hidden);
}

svg {
  stroke: black;
}

path:hover {
  fill: yellow;
}
不是正方形(它可以是任何大小——并且可以改变)时,我不知道如何将较长边上的三角形剪成沿
<div id="overlaid">
  <svg id="overlay">

    <svg viewbox="0 0 100 50" preserveAspectRatio="xMidYMin">
      <path id="above-zone" d="M 0,0
                               L 100,0 50,50
                               z" fill="rgba(0,127,255,0.5)" />
    </svg>

    <svg viewbox="0 0 50 100" preserveAspectRatio="xMinYMid">
      <path id="before-zone" d="M 0,0
                                L 50,50 0,100
                                z" fill="rgba(255,0,127,0.5)" />
    </svg>

    <svg viewbox="0 0 50 100" preserveAspectRatio="xMaxYMid">
      <path id="after-zone" d="M 50,0
                               L 50,100 0,50
                               z" fill="rgba(0,255,127,0.5)" />
    </svg>

    <svg viewbox="0 0 100 50" preserveAspectRatio="xMidYMax">
      <path id="below-zone" d="M 0,50
                               L 50,0 100,50
                               z" fill="rgba(255,127,0,0.5)" />
    </svg>

  </svg>
</div>
中心向下的梯形。这是我用上面的代码得到的:

这个问题可能会导致第二个问题,即当

div
相对于它的宽度是非常短或非常高时,较长边上的嵌套SVG开始缩小(大概是因为它们撞到外部 SVG 的另一侧(而不是溢出)。这就是我在上面的代码中将上面的
div
div
设置为
#overlaid
时得到的结果:

那么,如何将重叠的三角形剪裁成梯形,这样它们就不会在中间重叠,以及如何让三角形溢出外部 SVG 而不是收缩?

也欢迎使用其他方法,但请记住,覆盖的矩形大小是任意的,放置目标需要能够接收放置事件。我还想对这些放置目标应用样式以指示它们何时处于活动状态并指示它们何时被悬停,因此请确保您的方法不会阻止这种情况。

这是它短于宽度时的样子(在本例中为 400x200)。

这是当外层

height
被拉伸得更高以使其呈正方形(在本例中为 400x400)时的样子。

最后,这是当外部

200px
拉伸得比宽度高(在本例中为 400x800)时的样子。

svg overflow clip-path
1个回答
0
投票

形状重叠不是问题,因为指针事件只会被最上面的处理。因此,您只需要关心形状的堆叠方式,即对于每一侧,预期的三角形和梯形区域都位于所有其他区域之上。

为了抵消左右两侧三角形的重叠,如果 div 的纵横比低于 1,它们将与顶部和底部矩形交换。为此,您必须利用新的 container查询功能。它现在已在所有浏览器中实现,但请务必检查最低版本.

div
div
const overlay = document.querySelector('#overlay');
const feedback = document.querySelector('#feedback')

overlay.addEventListener('mouseover', (event) => {
  const side = [...event.target.classList]
               .find(cl => cl.endsWith('zone'));
  if (side) {
    feedback.textContent = side;
  }
});

overlay.addEventListener('mouseleave', (event) => {
  feedback.textContent = '';
});

© www.soinside.com 2019 - 2024. All rights reserved.