【问题标题】:add mouse event to svg <pattern>, detect grid hover将鼠标事件添加到 svg <pattern>,检测网格悬停
【发布时间】:2018-08-11 01:01:17
【问题描述】:

我有一个复杂的问题。我正在尝试通过 svg 呈现网格,然后将事件侦听器添加到网格中。目前我正在通过&lt;pattern&gt; 元素渲染网格。我对渲染网格的其他途径持开放态度,但它需要可扩展/高性能,因为这个网格很容易成为数千个正方形的 10 个。将其视为平面图或蓝图。

我想要什么:我希望能够将一个事件监听器附加到网格的每个方格

我做了什么:我查阅了 svg 文档,尝试了很多不同的东西(如 onclick 处理程序、svg 属性,如指针事件......等),但没有运气。我可能可以让它与鼠标客户端坐标一起工作,但是我想尽可能避免使用这种方法,因为这个 svg 将具有缩放和平移功能.. 这会使坐标变换变得很痛苦。

基本 svg 代码(针对这个问题进行了简化):

<svg viewBox="0 0 100 100">
  <g className="view-control">
    <defs>
      <pattern id="grid" width="10" height="10" patternUnits="userSpaceOnUse">
        <path d="M 10 0 L 0 0 0 10" fill="none" stroke="gray" strokeWidth="0.5"/>
      </pattern>
    </defs>
    <rect width="100%" height="100%" fill="url(#grid)" />
  </g>
</svg>

Fiddle to play with

【问题讨论】:

  • 如果您为每个较小的正方形使用一个rect 元素,那么您只需将一个鼠标悬停在侦听器上,即可通过event.target 找出悬停在哪个组元素上。但我不确定你是否喜欢这样,因为你说你可能需要数千个正方形。

标签: javascript reactjs svg


【解决方案1】:

我不确定您对“鼠标客户端坐标”的反对意见是什么,但它非常简单,并且符合您的要求。

  1. 向网格矩形添加一个点击处理程序。我在这个演示中使用了一个点击处理程序。但是如果你想基于悬停,你可以使用 mousemove 事件。

    <rect width="200%" height="200%" fill="url(#grid)" onClick={(e) => handleClick(e)}/>
    
    function handleClick(e) {
      var pos = getSVGPosition(e);
      createRectAt(pos);
    }
    
  2. 将鼠标坐标转换为 svg 坐标的函数如下所示:

    function getSVGPosition(e) {
      var svg = e.nativeEvent.target.ownerSVGElement;
      var pt = svg.createSVGPoint();
      pt.x = e.nativeEvent.clientX;
      pt.y = e.nativeEvent.clientY;
      pt = pt.matrixTransform(svg.getScreenCTM().inverse());
      return {svg: svg, x: pt.x, y: pt.y};
    }
    
  3. 然后出于演示的目的,我在相关网格位置创建一个正方形

    function createRectAt(pos) {
      var rect = document.createElementNS(pos.svg.namespaceURI, "rect");
      rect.setAttribute("x", Math.floor(pos.x / 10) * 10);
      rect.setAttribute("y", Math.floor(pos.y / 10) * 10);
      rect.setAttribute("width", 10);
      rect.setAttribute("height", 10);
      rect.setAttribute("fill", "green");
      pos.svg.appendChild(rect);
    }
    

https://jsfiddle.net/tp530748/31/

【讨论】:

  • 是的,在这个问题的范围内,使用鼠标位置并不是一个复杂的问题。但是,这是一个交互式 svg。我已经编写了控件来让用户缩放和平移 svg。我希望不使用鼠标坐标的原因是因为当用户平移/缩放新矩形的书写位置时不在正确的位置。
  • 实现缩放和平移的常用方法是通过操作viewBox。如果您这样做,那么我的代码应该可以正常工作。
【解决方案2】:

如果您将网格设置为&lt;pattern&gt;,那么您将无法在图案上注册任何鼠标事件。模式命中框将覆盖整个&lt;rect&gt;

我建议自己根据&lt;svg&gt; 的大小、viewBox 和网格的间距来计算方格的坐标。将任何鼠标事件附加到 SVG 元素

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-18
    • 1970-01-01
    • 2023-01-09
    • 1970-01-01
    • 2018-08-13
    • 2011-01-01
    相关资源
    最近更新 更多