D3.js缩放和触摸设备平滑
D3.js zoom and touch device smoothness
我使用d3. behavior。放大我的图表,桌面上一切正常。然而,当我在ipad上进行缩放时,缩放效果非常不稳定。有办法让我把它弄平吗?似乎我需要在缩放时取消翻译调用。
我试过几件事,但没有一件成功。
一个例子是在缩放处理程序中,我得到2个接触点x和y,然后得到它们之间的距离,并取决于它是否从我添加或减去0.05到d3.event的最后存储距离缩小或增长。在变换中使用的比例。
这是对的还是错了,需要考虑其他因素
帮助非常感谢
欢呼标记编辑:我想我应该在这里包括一些代码,因为我不能通过工作网络使用另一个服务
附加缩放处理程序
RadarDraw.ZoomListener = d3.behavior.zoom().scaleExtent([1, 5]).on("zoom", zoom);
// Create the SVG element, transforming the coordinates so (0,0) is at the centre
svg = d3.select("#radarContainer").append("svg")
.attr("viewBox", "0 0 " + _config.Width + " " + _config.Height + "")
.attr("id", "chartsvg")
.attr("width", _config.Width)
.attr("height", _config.Height)
//.call(zoom)
.append("g")
.attr("id", "svgGElm")
.attr("transform", "translate(" + _config.Width / 2 + "," + ((_config.Height - _config.Voffset) / 2 + _config.Voffset) + ")")
.call(_config.RadarType != "dash" ? RadarDraw.ZoomListener : function () { });
缩放处理程序
function zoom(){
if (d3.event.scale <= 1 || d3.event.scale >= 5) {
if (!tools.IsArcFocused) {
svg.attr("transform", "translate("
+ (d3.event.translate[0] + (_config.Width / 2)) + "," + (d3.event.translate[1] + (_config.Height / 2))
+ ")scale(" + d3.event.scale + ")");
}
//handle the zoom of arc that occurs from dblclick. this moves to arc and centers it and zooms in into it.
if (tools.IsArcFocused) {
svg.attr("transform", "translate(" + _config.Width / 2 + "," + _config.Height / 2 + ")scale(" + 5 + ")translate("
+ -RadarDraw.transPosX + "," + -RadarDraw.transPosY + ")");
}
debugInfoBar(" scale: " + d3.event.scale
+ " last distance: " + lastDistance
+ " current distance: " + currentDistance);
//detect mouse wheel
if(d3.event.sourceEvent != null)
{
if (d3.event.sourceEvent.type=='mousewheel' || d3.event.sourceEvent.type=='wheel' || d3.event.sourceEvent.type=='DOMMouseScroll')
{
//if we are zoom in on an arc only listen to zoom out command to exit the zoom
//if wheeldelta is forward and in focus mode then ignore it
if (d3.event.sourceEvent.wheelDelta > 0 && tools.IsArcFocused)
{
//make sure dots stay smallest zoomed in size
scaleDots(5);
return;
}
if (d3.event.sourceEvent.wheelDelta < 0) {
if ((tools.IsArcFocused && d3.event.scale >= 5) || (tools.IsArcFocused && d3.event.scale <= 1)) {
tools.ExitZoom(false);
}
//reset to 0,0 scale 1 as we want to zoom out fully
if (d3.event.scale <= 1 && tools.IsArcFocused)
{
svg.attr("transform", "translate(" + _config.Width / 2 + "," + _config.Height / 2 + ")scale(" + 1 + ")");
}
}
}
if (d3.event.sourceEvent.type == "mousemove" && tools.IsArcFocused)
{
d3.event.scale = 5;
scaleDots(5);
return;
}
if (d3.event.sourceEvent.type == "touchmove")
{
//need to handle zoom out via touch (like whats done with mouse wheel)
return;
}
//deal with stopping double tap and double click events via the zoom
if (d3.event.sourceEvent.type == 'dblclick' || d3.event.sourceEvent.type == 'touchstart')
{
if (typeof (d3.event.preventDefault) == "function") {
d3.event.preventDefault();
d3.event.stopPropagation();
}
return;
}
}
scaleDots(d3.event.scale);
if(tools.IsArcFocused)
previousZoomLevel = 5;
else
previousZoomLevel = 1;
return;
} else {
if (tools.IsArcFocused) {
svg.attr("transform", "translate(" + _config.Width / 2 + "," + _config.Height / 2 + ")scale(" + 5 + ")translate("
+ -RadarDraw.transPosX + "," + -RadarDraw.transPosY + ")");
}
inTouchZoom = false;
//detect forward scroll when zoomed in so it exits zoom
if(d3.event.sourceEvent != null)
{
if (d3.event.sourceEvent.type == 'mousewheel' || d3.event.sourceEvent.type == 'wheel' || d3.event.sourceEvent.type == 'DOMMouseScroll') {
if (d3.event.sourceEvent.wheelDelta == 120)
{
d3.event.scale += 0.05;
if (d3.event.scale > 4.9)
d3.event.scale = 4.9;
}
else if (d3.event.sourceEvent.wheelDelta -= 120)
{
d3.event.scale -= 0.05;
if (d3.event.scale < 1)
d3.event.scale = 1;
}
//previousZoomLevel -gets confused sometimes and is 1 when it should be >=5
if (tools.IsArcFocused && previousZoomLevel >= 5) {
tools.ExitZoom(false);
previousZoomLevel = d3.event.scale;
}
}
if (d3.event.sourceEvent.type == "touchmove") {
//if only one touch point then do translation for pan otherwise leave as is
if (d3.event.sourceEvent.touches.length > 1) {
inTouchZoom = true;
//dont update translate use what was take before
d3.event.translate = touchZoomTranslate;
//we have atleast 2 points so use the first 2
var currentDistance = PointDistance(d3.event.sourceEvent.touches[0].pageX, d3.event.sourceEvent.touches[0].pageY, d3.event.sourceEvent.touches[1].pageX, d3.event.sourceEvent.touches[1].pageY);
debugInfoBar(" scale: " + d3.event.scale
+ " tp1 X: " + d3.event.sourceEvent.touches[0].pageX + " tp1Y: " + d3.event.sourceEvent.touches[0].pageY
+ " tp2 X: " + d3.event.sourceEvent.touches[1].pageX + " tp2Y: " + d3.event.sourceEvent.touches[1].pageY
+ " last distance: " + lastDistance
+ " current distance: " + currentDistance);
if (currentDistance > lastDistance) {
d3.event.scale += 0.05;
if(d3.event.scale > 4.9)
d3.event.scale = 4.9;
lastDistance = currentDistance;
}
else {
d3.event.scale -= 0.05;
if (d3.event.scale < 1)
d3.event.scale = 1;
lastDistance = currentDistance;
}
svg.attr("transform", "translate(" + _config.Width / 2 + "," + _config.Height / 2 + ")scale(" + d3.event.scale + ")");
return;
}
}
if (d3.event.sourceEvent.type == "touchend") {
//wipe last distance and we have finished touch
lastDistance = 0;
}
//deal with stopping double tap and double click events via the zoom
if (d3.event.sourceEvent.type == 'dblclick' || (d3.event.sourceEvent.type == 'touchstart' && !inTouchZoom))
{
if (typeof (d3.event.preventDefault) == "function") {
d3.event.preventDefault();
d3.event.stopPropagation();
}
return;
}
}
if (!tools.IsArcFocused) {
svg.attr("transform", "translate("
+ (d3.event.translate[0] + (_config.Width / 2)) + "," + (d3.event.translate[1] + (_config.Height / 2))
+ ")scale(" + d3.event.scale + ")");
}
if (d3.event.scale > 1)
previousZoom = true;
//if we are zoomed in and our previous zoom level is 5 or above then exit zoom (we are either scrolling out or pinching out of zoom)
if (tools.IsArcFocused && previousZoomLevel >= 5) {
tools.ExitZoom(false);
}
scaleDots(d3.event.scale);
}
if (d3.event.scale > 4.9)
d3.event.scale = 4.9;
if(!inTouchZoom)
touchZoomTranslate = d3.event.translate;
}
我通过重写缩放处理程序来纠正这个问题,所以它有特定的触摸输入更新,在那里我处理缩放而不依赖于d3。我还监听了zoom中的触点事件但它没有触发我必须为zoomend附加另一个处理程序并以这种方式检测
无需所有计算即可实现缩放。
var onZoom = function() {
var scale = d3.event.scale,
translate = d3.event.translate;
elemToZoom.attr('transform', 'scale(' + scale + ')translate(' + translate + ')');
};
var zoom = d3.behavior.zoom().on('zoom', onZoom);
var elemToZoom = d3.select('#zoomable')
.call(zoom);
当你放大图形时,你可能需要重新绘制坐标轴、垂直线和水平线,这样它们就不会被放大了。
相关文章:
- Html页面上的多个Base64图像和平滑加载
- 触摸移动时切换到新元素
- Safari(Mac OS)上的jQuery平滑滚动问题
- 谷歌地图劫持了iphone's滚动(触摸事件)-如何恢复
- jquery平滑滚动问题
- ng消息仅在触摸时显示错误,并在错误的初始显示上转换
- 如何正确编程jQuery动画与平滑(导航栏)
- iOS 中的按钮触摸状态
- 如何在jquery中找到鼠标滚轮/触摸移动事件的走向
- 如何使用纯javascript的移动触摸事件
- 如何在c3js动态图表上进行平滑(水平)转换
- 如何使用javascript检测触摸设备浏览器与桌面
- 触摸启动事件未在iframe iOS 6中启动
- 使用CSS在选项卡更改时平滑颜色转换
- 如何平滑地设置twitter引导程序进度条的动画
- 如何检测滚动事件是否像在触摸设备上一样只触发一次
- SVG使用Javascript将形状平滑地变形为其他预定义的形状
- Sencha触摸:工具栏无法正常滚动
- 手势和触摸事件 - 平滑地调整正方形的大小
- D3.js缩放和触摸设备平滑