我有一个强制布局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
重新绑定它。
答案 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)