2017-10-16 87 views
-1

我用D3 js实现了缩放,所以无论何时鼠标悬停在画布上,缩放事件都会触发并允许用户使用鼠标滚轮放大和缩小。如何使用叠加和Ctrl +滚动事件实现像Google Map一样的D3鼠标滚轮缩放?

演示:https://diversity.rcc.uchicago.edu/collapsible_tree

但我想,以防止D3变焦的这种默认行为,并需要强制执行用户到用户按Ctrl +滚轮像谷歌地图将会放大画布:http://jsfiddle.net/maunovaha/jptLfhc8/

反正我们可以显示覆盖图以请求用户使用该组合,然后仅允许缩放。

我变焦代码是这样的:

var svg = d3.select("#collapsible-tree") 
    .append("svg") 
    .attr("width", width + margin.right + margin.left) 
    .attr("height", height + margin.top + margin.bottom) 
    .call(zm = d3.behavior.zoom().scaleExtent([0.1, 3]).on("zoom", redraw)) 
    .append("g") 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 

//Redraw for zoom 
function redraw() { 
    //console.log("here", d3.event.translate, d3.event.scale); 
    svg.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")"); 
} 
+0

请参加https://stackoverflow.com/a/47421474/1111654 –

回答

1

我几个星期前,有同样的问题。但我用了dagreD3。我使用的功能来自D3。这是我的工作小提琴。

JS Fiddle

// Create a new directed graph 
var g = new dagreD3.graphlib.Graph().setGraph({}) 
    .setDefaultEdgeLabel(function() { 
    return {}; 
    }); 
// Disable Browserzoom with strg + mousewheel 
$(document).keydown(function(event) { 
    if (event.ctrlKey == true && (event.which == '61' || event.which == '107' || event.which == '173' || event.which == '109' || event.which == '187' || event.which == '189')) { 
    alert('disabling zooming'); 
    event.preventDefault(); 
    } 
}); 

$(window).bind('mousewheel DOMMouseScroll', function(event) { 
    if (event.ctrlKey == true) { 
    event.preventDefault(); 
    } 
}); 

// Check if strg is pressed 
var ctrlPressed = false; 
$(window).keydown(function(evt) { 
    if (evt.which == 17) { 
    ctrlPressed = true; 
    console.log("pressed"); 
    } 
}).keyup(function(evt) { 
    if (evt.which == 17) { 
    ctrlPressed = false; 
    console.log("not pressed"); 
    } 
}); 

//adding nodes and edges 

g.setNode(0, { 
    label: "TOP", 
}); 
g.setNode(1, { 
    label: "S", 
}); 
g.setNode(2, { 
    label: "NP", 
}); 
g.setNode(3, { 
    label: "DT", 
}); 
g.setNode(4, { 
    label: "This", 
}); 
g.setNode(5, { 
    label: "VP", 
}); 
g.setNode(6, { 
    label: "VBZ", 
}); 
g.setNode(7, { 
    label: "is", 
}); 
g.setNode(8, { 
    label: "NP", 
}); 
g.setNode(9, { 
    label: "DT", 
}); 
g.setNode(10, { 
    label: "an", 
}); 
g.setNode(11, { 
    label: "NN", 
}); 
g.setNode(12, { 
    label: "example", 
}); 
g.setNode(13, { 
    label: ".", 
}); 
g.setNode(14, { 
    label: "sentence", 
}); 

g.setEdge(3, 4); 
g.setEdge(2, 3); 
g.setEdge(1, 2); 
g.setEdge(6, 7); 
g.setEdge(5, 6); 
g.setEdge(9, 10); 
g.setEdge(8, 9); 
g.setEdge(11, 12); 
g.setEdge(8, 11); 
g.setEdge(5, 8); 
g.setEdge(1, 5); 
g.setEdge(13, 14); 
g.setEdge(1, 13); 
g.setEdge(0, 1); 

// Round the corners of the nodes 
g.nodes().forEach(function(v) { 
    var node = g.node(v); 
    node.rx = node.ry = 5; 
}); 

//makes the lines smooth 
g.edges().forEach(function(e) { 
    var edge = g.edge(e.v, e.w); 
    edge.lineInterpolate = 'basis'; 
}); 

// Create the renderer 
var render = new dagreD3.render(); 
var width = 500, 
    height = 1000, 
    center = [width/2, height/2]; 
// Set up an SVG group so that we can translate the final graph. 
var svg = d3.select("svg"), 
    inner = svg.append("g"); 
var zoom = d3.behavior.zoom() 
    .on("zoom", zoomed); 

function zoomed() { 
    inner.attr("transform", "translate(" + zoom.translate() + ")scale(" + zoom.scale() + ")"); 
} 
svg.call(zoom) 
svg.on("wheel.zoom", null); 
svg.on("dblclick.zoom", null); 
svg.call(zoom.event); 
document.getElementById("container").addEventListener("wheel", myFunction); 

function myFunction(event) { 
    if (ctrlPressed == true) { 
    if (event.wheelDelta > 0) { 
     zoom_by(1.03); 
    } else if (event.wheelDelta < 0) { 
     zoom_by(1/1.03); 
    } 
    } 
} 

function zoom_by(factor) { 
    var scale = zoom.scale(), 
    extent = zoom.scaleExtent(), 
    translate = zoom.translate(), 
    x = translate[0], 
    y = translate[1], 
    target_scale = scale * factor; 

    // If we're already at an extent, done 
    if (target_scale === extent[0] || target_scale === extent[1]) { 
    return false; 
    } 
    // If the factor is too much, scale it down to reach the extent exactly 
    var clamped_target_scale = Math.max(extent[0], Math.min(extent[1], target_scale)); 
    if (clamped_target_scale != target_scale) { 
    target_scale = clamped_target_scale; 
    factor = target_scale/scale; 
    } 

    // Center each vector, stretch, then put back 
    x = (x - center[0]) * factor + center[0]; 
    y = (y - center[1]) * factor + center[1]; 

    // Enact the zoom immediately 
    zoom.scale(target_scale) 
    .translate([x, y]); 
    zoomed(); 
} 
// Run the renderer. This is what draws the final graph. 
render(inner, g); 

// Center the graph 
var initialScale = 1.0; 
zoom.translate([(svg.attr("width") - g.graph().width * initialScale)/2, 20]) 
    .scale(initialScale) 
    .event(svg); 
svg.attr("height", g.graph().height * initialScale + 40); 
+0

感谢一下我的回答让我们看看D3爱好者可以建议! – Milson

+0

也许有一个更简单的解决方案:) – 2017-10-16 15:24:53

0

您可以通过设置特定事件为null禁用需要D3缩放事件。

svg.call(zoom) // zoom disable 
       .on("wheel.zoom", null) 
       .on("mousedown.zoom", null) 
       .on("touchstart.zoom", null) 
       .on("touchmove.zoom", null) 
       .on("touchend.zoom", null); 
相关问题