簡體   English   中英

D3強制布局圖縮放功能

[英]D3 force layout graph zoom functionality

我是js的新手,無法解決自己面對的問題,因此,我將很高興為您提供任何建議或幫助。

在我的項目中,我創建了力布局圖。 我應該做的是為圖形添加放大和縮小功能。

我創建了一個小例子來說明我面臨的問題。

function myGraph(el){
this.addNode = function (id, category, opened, parentT, name, nodeType, countLinks, dob, country, childsCount) {
            var parent = [];
            parent.push(parentT);
            nodes.push({ "id": id, "category": category,    "opened": opened, "parent": parent, "name": name, "nodeType": nodeType, "countLinks": countLinks, "dob": dob, "country": country, "childCount": childsCount });
            update();
        }

this.addLink = function (sourceId, targetId, type) {
            var sourceNode = findNode(sourceId);
            var targetNode = findNode(targetId);

            if ((sourceNode !== undefined) && (targetNode !== undefined)) {
                links.push({ "source": sourceNode, "target": targetNode, "type": type });
                update();
            }
        }

var findNode = function (id) {
            for (var i = 0; i < nodes.length; i++) {
                if (nodes[i].id === id)
                    return nodes[i]
            };
        }

var w = 360,
            h = 200;


var vis = this.vis = d3.select(el).append("svg:svg")
            .attr("id", "mySvg")
            .attr("width", w)
            .attr("height", h)
            .attr("viewBox", "0 0 " + w + " " + h)
            .call(d3.behavior.zoom().scaleExtent([-0.5, 1]).on("zoom", redraw))

var g = vis.append('svg:g')
            function redraw(e) {
                if (!e) e = window.event;
                if (e.type == "wheel" || e.shiftKey == true) {
                    g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
                }
        }

var force = d3.layout.force()
            .gravity(0.05)
            .distance(100)
            .charge(-200)
            .size([w, h]);

var nodes = force.nodes(),
                links = force.links();
var hiddenType = [];

        g.append("g").attr("class", "links");
        g.append("g").attr("class", "nodes");

        var update = function () {
            for (var i=0; i<links.length; i++) {
                if (i != 0 &&
                    links[i].source == links[i-1].source &&
                    links[i].target == links[i-1].target) {
                        links[i].linknum = links[i-1].linknum + 1;
                    }
                else {links[i].linknum = 1;};
            };

            var myLink = g.select(".links").selectAll(".link");
            myLink.remove();
            var link = g.select(".links").selectAll(".link")
                .data(links);
            link.enter().append("polyline")
                .attr("class", "link")
                .attr("type", function (d) { return "link_" + d.type; })

            link.exit().remove();

            var node = g.select(".nodes").selectAll(".node")
                .data(nodes, function (d) { return d.id; })

            var nodeEnter = node.enter().append("g")
                .attr("class", "node")
                .attr("links", function (d) { return d.countLinks })
                .attr("type", function (d) { return d.nodeType })
                .on("mousedown", mousedown)
                .call(force.drag);

            nodeEnter.append("circle")
                .attr("r", "10px")
                .attr("x", "-8px")
                .attr("y", "-8px")
                .attr("width", "16px")
                .attr("height", "16px")
                .style("fill", "white")
                .style("stroke", "#ccc")

                        nodeEnter.append("rect")
                .attr("pointer-events", "none")
                .attr("class", "shape")
                .attr("width", "250px")
                .attr("height", "150px")
                .style("fill", "transparent")
            nodeEnter.append("text")
                .attr("pointer-events", "none")
                .attr("class", function (d) { return "nodetext_" + d.id })
                .attr("y", "-10")
                .text(function (d) { return d.id })

            nodeEnter.append("title")
                .text(function (d) { return d.id });

            node.exit().remove();

        function mousedown(d) {
                d.fixed = true;
            }

            force.on("tick", function () {

                link.attr("points", function(d){
                    if (d.source.y > d.target.y) {
                        return d.source.x + "," + d.source.y + " " + (d.source.x + ((d.target.x - d.source.x) / 2)) + "," + (d.target.y + ((d.source.y - d.target.y) / 2) + (15 * (d.linknum - 1))) + " " + d.target.x + "," + d.target.y;
                    }
                    if (d.source.y < d.target.y) {
                        return d.source.x + "," + d.source.y + " " + (d.source.x + ((d.target.x - d.source.x) / 2)) + "," + (d.source.y + ((d.target.y - d.source.y) / 2) + (15 * (d.linknum - 1))) + " " + d.target.x + "," + d.target.y;
                    }
                })

                node.attr("transform", function (d) {
                    if (d.fixed !== true) {
                        return "translate(" + d.x + "," + d.y + ")";
                    }
                    else {
                        return "translate(" + d.px + "," + d.py + ")";
                    }
                });
            });
                            force.start();
    }
          update();
}
graph = new myGraph("#graph");
graph.addNode("A")
graph.addNode("B")
graph.addNode("C")
graph.addLink("A", "B")
graph.addLink("A", "C")

https://jsfiddle.net/IMykytiv/nsxL8c52/

所以問題是:

在我的圖中,在該節點的位置固定之后,用戶可以向任意方向拖動節點。 當我添加縮放時,我無法拖動節點,因為縮放首先生效,因此我添加了僅在按下Shift鍵時縮放才起作用的條件。 所以現在我既可以拖動節點也可以縮放。

但是現在我遇到了一個問題,如果我拖動節點並嘗試使用鼠標滾輪進行縮放,則它不是從鼠標位置而是從另一點改變了變換,而我不明白為什么。 如果我刪除了Shift鍵,條件縮放將按預期進行。

我終於找到了解決方案,這非常容易。 我要做的只是在啟動Draggin節點事件時防止觸發縮放功能,而不是在按住Shift鍵的情況下添加條件:

    var drag = force.drag()
        .on("dragstart", function (d) {
            d3.event.sourceEvent.stopPropagation();
        });

在這里更新了jsfiddle: https ://jsfiddle.net/IMykytiv/nsxL8c52/2/

希望對任何人都有用:)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM