d3.behaviour.zoom在仅使用一根手指时禁用触摸屏上的平移

时间:2016-01-29 13:08:39

标签: javascript d3.js

我有一个强制布局d3图表,我正在使用d3.behaviour.zoom来启用缩放和平移。

一切都很好但是因为我的图表在iPad上填满了屏幕,所以当我的触摸只是平移图表时,就无法向下滚动页面。

我想在触摸设备上保持捏缩放行为。

touchmove.zoom时是否可以取消d3.event.touches.length === 1事件

这只会禁用所有触摸互动 - 因此滚动效果不错,但我无法再缩放图表:

selection.call(zoom)
    .on('touchstart.zoom', null)
    .on('touchmove.zoom', null)
    .on('touchend.zoom', null);

我还尝试添加另一个touchmove侦听器,如下所示:

selection.call(zoom)
    .on('touchmove', function () {
        if (d3.event.touches.length === 1) {
            d3.event.stopPropagation();
            // i've also tried d3.event.preventDefault() but it doesn't do anything         
        }
    });

我不认为我可以在d3中访问默认的缩放touchmove侦听器吗?我想知道我是否可以删除touchstart上的监听器,然后如果用户只使用一次触摸就在touchend重新绑定它。

2 个答案:

答案 0 :(得分:0)

听起来你需要比使用内置事件更精细的事件控制。尝试创建处理标准事件的对象并将其转换为自定义事件(根据您选择的规则,例如仅触摸1次)。然后,您可以在d3调度机制的帮助下监听这些自定义事件。

Events = function() {

// custom event set up using d3 dispatch
var dispatch = d3.dispatch("drag", "drag2");

//listen for standard event on containing DOM element
var events = function (g) {
//g is the container DOM element

// register the standard events required
g.on("touchmove", touchmove)

return events;
};

//function that handles the touchmove standard event
function touchmove(d,i) {

//stop the default event going any further
d3.event.stopPropagation();

//depending on your conditions choose which custom event you trigger
if(condition1)
{       
    dispatch.drag.call(d3.event.target, d, i);
}
else if(condition2)
{       
    dispatch.drag2.call(d3.event.target, d, i);
}
}

//add events defined in d3 dispatch function to events object and return   
return d3.rebind(events, dispatch, "on");
}

在代码的其他地方创建events对象并监听其自定义事件:

events = new Events();

//Set the containing element the events object should be registering event listeners to
d3.select(container).call(events);

events.on("drag", function (d, i, position) {
    //do something here
})

events.on("drag2", function (d, i, position) {
    //do something else here
})

答案 1 :(得分:0)

不使用d3调度的一种方法是使用原始的touchstart事件监听器而不是d3。通过event.touches.length,您可以统计屏幕上检测到的触摸次数。

通过添加侦听器并进一步检查触摸计数是否为1 in d3.behaviour.zoom,当手指在图形上时,它可以防止平移,并且默认情况下将改为正常滚动页面。

let touchCount = 0;

// Only necessary to add listener when running on mobile/tablet
// (assuming you already have some detection set up)

if (isMobileSize) {
    document.querySelector('.your-svg').addEventListener('touchstart', (e) => {
        touchCount = e.touches.length;
    });
}


let selection = d3.select('.your-svg');
let zoom = d3.behavior.zoom().on('zoom', () => {

    // When 1 finger, do not zoom
    if (touchCount === 1) {
        d3.event.sourceEvent.stopPropagation();
        return;
    }

    // Otherwise run zoom/move
    // ... zoom logic goes here....
})

selection.call(zoom)