sourcecode

D3 힘 레이아웃 그래프를 확대하는 방법이 있습니까?

codebag 2023. 10. 15. 17:18
반응형

D3 힘 레이아웃 그래프를 확대하는 방법이 있습니까?

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/4/14

D3 v.3의 변화와 관련된 예에 대해서는 여기 Mike Bostock의 답변을 참조하십시오.저는 이것이 아마도 아래의 답변을 대체할 것이라고 생각합니다.

업데이트 2/18/2014

SVG 전체를 pan and zoom 하려면 @ahaarnos의 답변이 더 좋을 것 같습니다.내포된g아래의 제 답변에 있는 요소들은 (원래 질문의 경우가 아닌) 동일한 SVG에 줌이 아닌 요소가 있는 경우에만 정말로 필요합니다.만약 당신이 그 행동을 A에 적용한다면,g요소, 그 다음에 배경rect또는 이와 유사한 요소가 필요합니다.g포인터 이벤트를 수신합니다.

원답

줌-팬-transform(zoom-pan-pan-pan-pan-pan-pan-pan-pan-pan-pan-pan-pan-pan-pan-pan-pan)

내가 기대했던 것보다 좀 더 복잡했어요. 여러 개를 둥지로 틀어야 해요.g요소들을 작동시켜 SVG의 기능을 설정합니다.pointer-events에 귀속시키다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>의?

아래의 코드는 나에게 잘 맞았습니다 (단 한개만).<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 문제를 해결했습니다.v2가 그렇지 않은데 d3.js v3가 줌을 구현할 때 내 힘 그래프가 깨지는 이유는 무엇입니까?

먼저 메인코드.이것은 @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의 fiddle이지만 D3v3가 노드 드래그를 해제하는 방법을 보여줍니다. http://jsfiddle.net/QMKm3/718/

여기 D3v3와 함께 작동하도록 수정된 동일한 fiddle이 있습니다. http://jsfiddle.net/QMKm3/719/

두번째 "svg:g" 부록 없이 그래프를 작동시켰습니다.

[...].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

xScale 및 yScale 변수, 함수 dragstart(), dragd() 및 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) + ")";
        });


    };

언급URL : https://stackoverflow.com/questions/7871425/is-there-a-way-to-zoom-into-a-d3-force-layout-graph

반응형