【问题标题】:Which pointer-events value of SVG should be used for a specific scernarioSVG 的哪个指针事件值应该用于特定场景
【发布时间】:2020-12-15 22:52:47
【问题描述】:

在一个 svg 中有两个带有 id 的矩形 - “蓝色”和“透明”。透明的 reactangle 在蓝色之上。

<svg width="1000" height="1000">
  <rect id="blue"   x="150" y="0" width="100" height="300" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
  <rect id="transparent" pointer-events="visible" x="100" y="100" width="300" height="100" style="fill:none;stroke-width:3;stroke:rgb(0,0,0)" />
</svg>

我已关联透明矩形的鼠标悬停事件以显示 工具提示文本,说“透明”。现在我有一个要求,当用户鼠标悬停时 透明矩形 事件应该在透明矩形上执行,但是当 用户单击透明矩形和蓝色矩形之间的相交区域事件 应该执行与蓝色矩形关联的。

如果我为透明矩形设置了 pointer-events="visiblePainted" 则没有任何事件 透明矩形(我想捕获鼠标悬停事件)被捕获并且蓝色反应角 下面捕获所有事件。有没有办法在制作后指定允许移动事件 透明矩形的 pointer-events="visiblePainted"。

提前致谢。

【问题讨论】:

    标签: javascript html css svg


    【解决方案1】:

    您可以使用为透明矩形绘制的指针事件,

    document.getElementById('transparent').addEventListener('mouseover', (e) => {
      console.log('transparent');
    });
    
    document.getElementById('blue').addEventListener('click', (e) => {
      console.log('blue');
    });
    <svg width="1000" height="1000">
      <rect id="blue"   x="150" y="0" width="100" height="300" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)" />
      <rect id="transparent" pointer-events="painted" x="100" y="100" width="300" height="100" style="fill:none;stroke-width:3;stroke:rgb(0,0,0)" />
    </svg>

    【讨论】:

      【解决方案2】:

      这只能通过 Javascript 来实现。鼠标事件要么被一个元素捕获,要么被另一个元素捕获,CSS 无法检测到交叉点。

      手续有点繁琐:

      • 检测鼠标事件在屏幕坐标中的位置
      • 将它们转换为蓝色矩形的局部坐标
      • 测试该点是否在蓝色矩形的填充或描边内
      • 做出相应的反应

      const svg = document.querySelector('svg');
      const blue = document.querySelector('#blue');
      
      function onBlueClick () {
          console.log('Blue clicked!')
      }
      blue.addEventListener('click', onBlueClick)
      
      document.querySelector('#transparent').addEventListener('click', function (event) {
          const transform = blue.getScreenCTM().inverse();
          const cursor = svg.createSVGPoint();
          cursor.x = event.clientX;
          cursor.y = event.clientY;
      
          const point = cursor.matrixTransform(transform);
          if (blue.isPointInFill(point) || blue.isPointInStroke(point)) {
              onBlueClick();
          }
      });
      <svg width="1000" height="1000">
        <rect id="blue"   x="150" y="0" width="100" height="300" style="fill:rgb(0,0,255);stroke-width:3;stroke:rgb(0,0,0)">
          <title>Transparent</title>
        </rect>
        <rect id="transparent" pointer-events="visible" x="100" y="100" width="300" height="100" style="fill:none;stroke-width:3;stroke:rgb(0,0,0)" />
      </svg>

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-01-20
        • 1970-01-01
        • 2014-05-04
        • 1970-01-01
        • 2014-08-13
        • 1970-01-01
        相关资源
        最近更新 更多