4

我刚刚开始掌握 D3 及其为移动应用程序创建形状等的图形能力,并且我的缩放功能在桌面上运行良好,并通过遵循以下答案设法消除了双击缩放行为:如何禁用 d3.behavior.zoom 的双击缩放?

有没有办法为移动设备禁用它(双击)?双击缩放也停止触发形状上的双击事件,所以如果我不能禁用双击缩放,有没有办法确保所有事件都在双击时触发,而不是仅仅缩放(双击桌面的行为符合预期)?

非常感谢,贝基

4

2 回答 2

1

假设在移动设备上缩放应该使用捏合手势完成,您可以尝试检测缩放处理程序中的手指数量,如下所示:

if (d3.event.sourceEvent.touches.length == 1) 
    return
于 2015-03-09T02:28:47.780 回答
1

D3 控制touchstart.zoom您选择缩放的元素上的事件d3.behavior.zoom()()。您不能简单地替换此处理程序并有条件地调用原始 D3 处理程序,因为它的部分算法会添加和删除此处理程序,因此您的覆盖将被覆盖。

但是,您可以在上游进一步捕获此事件,并有条件地允许它传播到具有缩放行为的元素。为此,您需要将处理程序添加到子元素,以便它会冒泡到缩放元素。例如:

<g class="zoom_area">  <-- Element you called D3 zoom behaviour on
  <rect width=... height=... style="visibility:hidden; pointer-events:all" class="background">
    // Background rect that will catch all touch events missed by your elements
  </rect>
  <g class="content"> <-- Container for your elements
    ...  <-- Your SVG content
  </g>
</g>

设置正常的 D3 缩放行为:

var zoomer = d3.behavior.zoom();
zoomer(d3.select('g.zoom_area'));

然后设置你的双重触摸覆盖:

var last_touch_time = undefined;
var touchstart = function() {
    var touch_time = d3.event.timeStamp;
    if (touch_time-last_touch_time < 500 && d3.event.touches.length===1) {
        d3.event.stopPropagation();
        last_touch_time = undefined;
        return;
    }
    last_touch_time = touch_time;
};
d3.select('.background_rect').on('touchstart.zoom', touchstart);
d3.select('.content').on('touchstart.zoom', touchstart);

这是一个替代版本,它只会检测在类似位置发生轻敲的快速触摸。缺点是在不同位置快速点击仍会放大。好处是快速合法的平移/缩放手势仍然有效。

var last_touch_event = undefined;
var touchstart = function() {
    if (last_touch_event && d3.event.touches.length===1 &&
        d3.event.timeStamp - last_touch_event.timeStamp < 500 &&
        Math.abs(d3.event.touches[0].screenX-last_touch_event.touches[0].screenX) < 10 &&
        Math.abs(d3.event.touches[0].screenY-last_touch_event.touches[0].screenY) < 10) {
        d3.event.stopPropagation();
        last_touch_time = undefined;
    }
    last_touch_event = d3.event;
};
d3.select('.background_rect').on('touchstart.zoom', touchstart);
d3.select('.content').on('touchstart.zoom', touchstart);

使用这种方法,我已经看到dblclick双击触发的事件是正常的。

于 2016-01-25T18:13:32.437 回答