d3.js v4 中的缩放传播:当一根手指在子元素上时捏合缩放地图

d3.js zoom propagation in v4: pinch zooming a map when one finger is over a child element

我有一个交互式地图,其中的景点用 svg 圆圈表示。每个圆都有一个touchstart或者mousedown事件,后面的透明矩形绑定了d3.zoom()所以可以放大地图!如果您要检查元素,这里是设置:

<div id="map">
    <svg>
        <g><rect></rect></g> <!-- transparent rect bound to d3.zoom() -->
        <g>
            <circle></circle> <!-- places of interest with touchstart listeners -->
            <circle></circle>
            ...
        </g>
    </svg>
</div>

现在,如果我捏缩放,并且我的一根粗手指恰好在这些圆圈之一上,缩放将在我的 phone 上表现得很奇怪,除非我阻止在触摸圆圈时发生缩放像这样:

  selection.append("circle").on("touchstart mousedown",function(d,i){
       d3.event.preventDefault(); // no zoom for you
       // ... code to highlight circle or whatever 
  }

这样一来,如果用户不小心用一根手指在圆圈或感兴趣的地方缩放,圆圈会突出显示并取消缩放。从同一个讨论中阅读 this discussion and also issue 66 对我进行设置很有帮助。

只要用户在缩放时避开感兴趣的地方,缩放就可以了。

但是,我真正想做的是将此设置倒过来,并始终将缩放放在首位。

我试过将圆圈放在缩放矩形后面,但是当然圆圈不再接收触摸事件。这很不幸,因为当您无法再与感兴趣的地方互动时,地图会完美缩放。

我现在通过缩小感兴趣的地点来解决问题,这样我就可以增加用户只放大地图的机会。这当然是次优的。

也许有一天我会对触摸事件有一个直观的理解,但现在我谦虚地问一下我迷路时如何处理这个问题。非常感谢任何关于如何优先考虑缩放而不是我的地图的触摸启动的建议。感谢阅读。

所以这让我得到了我的风滚草徽章。我最终通过使用 canvas 构建所有圈子来解决这个问题。具有 d3 缩放功能的 svg 地图,但带有 canvas 个圆圈。如果您有一个 d3 元素,并且您将一根手指放在该元素上,另一根手指放在地图上并尝试捏合缩放,它将不起作用。使用 canvas 和指针跟踪可以解决这个问题。

这是完成的地图和项目https://pixelsandplans.com/live/flow/