Есть ли способ увеличить масштаб графика компоновки D3 force?
D3 имеет направленную на силу компоновку здесь. Есть ли способ добавить масштабирование к этому графику? В настоящее время я смог захватить событие колеса мыши, но не совсем уверен, как написать саму функцию перерисовки. Есть предложения?
var vis = d3.select("#graph")
.append("svg:svg")
.call(d3.behavior.zoom().on("zoom", redraw)) // <-- redraw function
.attr("width", w)
.attr("height", h);
6 ответов:
обновление 6/4/14
см. также ответ Майка Бостока здесь для изменений в D3 V. 3 и по теме. Я думаю, что это, вероятно, заменяет ответ ниже.
обновление 2/18/2014
Я думаю, что ответ @ahaarnos предпочтительнее, если вы хотите, чтобы весь SVG перемещался и масштабировался. Вложенный элемент
gэлементы в моем ответе ниже действительно необходимы только если у вас есть элементы без масштабирования в том же SVG (не тот случай в исходном вопросе). Если вы do применить поведение кgэлемент, затем фонrectили подобный элемент необходим для того чтобы обеспечить чтоgполучает события указателя.Оригинальный Ответ
я получил эту работу на основе zoom-pan-transform пример-вы можете увидеть мой jsFiddle здесь:http://jsfiddle.net/nrabinowitz/QMKm3/
It было немного сложнее, чем я надеялся - вы должны вложить несколько
gэлементы, чтобы заставить его работать, установите SVG доall, а затем добавьте фоновый прямоугольник для получения событий указателя (в противном случае он работает только тогда, когда указатель находится над узлом или ссылкой). Элементredrawфункция сравнительно проста, просто установив преобразование на самом внутреннемg:var vis = d3.select("#chart") .append("svg:svg") .attr("width", w) .attr("height", h) .attr("pointer-events", "all") .append('svg:g') .call(d3.behavior.zoom().on("zoom", redraw)) .append('svg:g'); vis.append('svg:rect') .attr('width', w) .attr('height', h) .attr('fill', 'white'); function redraw() { console.log("here", d3.event.translate, d3.event.scale); vis.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")"); }это эффективно масштабирует весь SVG, поэтому он также масштабирует ширину хода, например увеличение изображения.
есть еще пример это иллюстрирует аналогичную технику.
почему вложенные
<g>' s?этот код ниже работает для меня (только один
<g>, без случайного большого белого<rect>:var svg = d3.select("body") .append("svg") .attr({ "width": "100%", "height": "100%" }) .attr("viewBox", "0 0 " + width + " " + height ) .attr("preserveAspectRatio", "xMidYMid meet") .attr("pointer-events", "all") .call(d3.behavior.zoom().on("zoom", redraw)); var vis = svg .append('svg:g'); function redraw() { vis.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")"); }где все элементы в вашем svg затем добавляются к
visэлемент.
предоставленные ответы работают в D3 v2, но не в v3. Я синтезировал ответы в чистое решение и решил проблему v3, используя ответ, приведенный здесь:почему d3.js v3 ломает мой график силы при реализации масштабирования, когда v2 этого не делает?
сначала основной код. Это очищенная версия ответа @ahaarnos:
var svg = d3.select("body") .append("svg") .attr("width", width) .attr("height", height) .call(d3.behavior.zoom().on("zoom", redraw)) .append('g'); function redraw() { svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")"); }теперь у вас есть панорамирование и масштабирование, но вы не сможете перетаскивать узлы, потому что функция панорамирования переопределит функция перетаскивания. Поэтому нам нужно сделать следующее:
var drag = force.stop().drag() .on("dragstart", function(d) { d3.event.sourceEvent.stopPropagation(); // to prevent pan functionality from //overriding node drag functionality. // put any other 'dragstart' actions here });вот скрипка @nrabinowitz, измененная для использования этой более чистой реализации масштабирования, но иллюстрирующая, как D3v3 разрывает перетаскивание узла:http://jsfiddle.net/QMKm3/718/
и вот та же скрипка модифицирована для работы с D3v3:http://jsfiddle.net/QMKm3/719/
Я получил свой график для работы без второго" svg:g " append.
[...].attr("pointer-events", "all") .attr("width", width2) .attr("height", height2) .append('svg:g') .call(d3.behavior.zoom().on("zoom", redraw));остальное то же самое.
Я получил решение для D3 force directed graph с опцией масштабирования.
var m = [40, 240, 40, 240], width = 960, height = 700, root; var svg = d3.select("body").append("svg") .attr("class", "svg_container") .attr("width", width) .attr("height", height) .style("overflow", "scroll") .style("background-color", "#EEEEEE") .append("svg:g") .attr("class", "drawarea") .append("svg:g") .attr("transform", "translate(" + m[3] + "," + m[0] + ")"); //applying zoom in&out for svg d3.select("svg") .call(d3.behavior.zoom() .scaleExtent([0.5, 5]) .on("zoom", zoom)); //zooming function zoom() { //zoom in&out function var scale = d3.event.scale, translation = d3.event.translate, tbound = -height * scale, bbound = height * scale, lbound = (-width + m[1]) * scale, rbound = (width - m[3]) * scale; // limit translation to thresholds translation = [ Math.max(Math.min(translation[0], rbound), lbound), Math.max(Math.min(translation[1], bbound), tbound) ]; d3.select(".drawarea") .attr("transform", "translate(" + translation + ")" + " scale(" + scale + ")"); }
Если вы хотите увеличить и переместить макет силы без изменения размера узла, попробуйте ниже. Вы также можете перетаскивать узлы без дрожи. Настоящий Кодекс основывается на оригинальный пример расположения сил. Что касается данных узлов и связей, пожалуйста, обратитесь к исходному образцу данных. http://bl.ocks.org/mbostock/4062045
Plz обратите внимание на переменные xScale и yScale, функции dragstarted(), dragged () и dragended(). Также была изменена функция tick ().
вы можете увидеть результат в http://steelblue.tistory.com/9 Язык на сайте-корейский. Однако вы можете легко найти результат в третьем примере на странице.
var graph = { "nodes": [ { "name": "Myriel", "group": 1 }, { "name": "Napoleon", "group": 1 }, // ...... { "name": "Mme.Hucheloup", "group": 8 } ], "links": [ { "source": 1, "target": 0, "value": 1 }, { "source": 2, "target": 0, "value": 8 }, // ....... { "source": 76, "target": 58, "value": 1 } ] }; var width = 640, height = 400; var color = d3.scale.category20(); var xScale = d3.scale.linear() .domain([0, width]) .range([0, width]); var yScale = d3.scale.linear() .domain([0, height]) .range([0, height]); var zoomer = d3.behavior.zoom().x(xScale).y(yScale).scaleExtent([0.1, 8]).on("zoom", zoom); function zoom() { tick(); }; var drag = d3.behavior.drag() .origin(function (d) { return d; }) .on("dragstart", dragstarted) .on("drag", dragged) .on("dragend", dragended); function dragstarted(d) { d3.event.sourceEvent.stopPropagation(); d.fixed |= 2; } function dragged(d) { var mouse = d3.mouse(svg.node()); d.x = xScale.invert(mouse[0]); d.y = yScale.invert(mouse[1]); d.px = d.x; d.py = d.y; force.resume(); } function dragended(d) { d.fixed &= ~6; } var force = d3.layout.force() .charge(-120) .linkDistance(30) .size([width, height]); var svg = d3.select("body").append("svg") .attr("width", width) .attr("height", height); svg.call(zoomer); force .nodes(graph.nodes) .links(graph.links) .start(); var link = svg.selectAll(".link") .data(graph.links) .enter().append("line") .attr("class", "link") .style("stroke-width", function (d) { return Math.sqrt(d.value); }); var node = svg.selectAll(".node") .data(graph.nodes) .enter().append("circle") .attr("class", "node") .attr("r", 5) .style("fill", function (d) { return color(d.group); }) .call(drag); node.append("title") .text(function (d) { return d.name; }); force.on("tick",tick); function tick(){ link.attr("x1", function (d) { return xScale(d.source.x); }) .attr("y1", function (d) { return yScale(d.source.y); }) .attr("x2", function (d) { return xScale(d.target.x); }) .attr("y2", function (d) { return yScale(d.target.y); }); node.attr("transform", function (d) { return "translate(" + xScale(d.x) + "," + yScale(d.y) + ")"; }); };
Comments