Vikram Singh Jadon
Vikram Singh Jadon

Reputation: 1047

Making Horizontally draggable graphs using D3

I want to make a graph, that is only horizontally draggable. when I drag svg container in which the graph is, it should drag only horizontally. I am using D3 to make the graph. I am following a sample graph from this fiddle.

The Javascript code in the fiddle is :

    var graph = {
    "nodes":[
        {"name":"1","rating":90,"id":2951},
        {"name":"2","rating":80,"id":654654},
        {"name":"3","rating":80,"id":6546544},
        {"name":"4","rating":1,"id":68987978},
        {"name":"5","rating":1,"id":9878933},
        {"name":"6","rating":1,"id":6161},
        {"name":"7","rating":1,"id":64654},
        {"name":"8","rating":20,"id":354654},
        {"name":"9","rating":50,"id":8494},     
        {"name":"10","rating":1,"id":6846874},
        {"name":"11","rating":1,"id":5487},
        {"name":"12","rating":80,"id":"parfum_kenzo"},
        {"name":"13","rating":1,"id":65465465},
        {"name":"14","rating":90,"id":"jungle_de_kenzo"},
        {"name":"15","rating":20,"id":313514},
        {"name":"16","rating":40,"id":36543614},
        {"name":"17","rating":100,"id":"Yann_YA645"},
        {"name":"18","rating":1,"id":97413},
        {"name":"19","rating":1,"id":97414},
        {"name":"20","rating":100,"id":976431231},
        {"name":"21","rating":1,"id":9416},
        {"name":"22","rating":1,"id":998949},
        {"name":"23","rating":100,"id":984941},
        {"name":"24","rating":100,"id":"99843"},
        {"name":"25","rating":1,"id":94915},
        {"name":"26","rating":1,"id":913134},
        {"name":"27","rating":1,"id":9134371}
    ],
    "links":[
        {"source":6,"target":5,"value":6, "label":"publishedOn"},
        {"source":8,"target":5,"value":6, "label":"publishedOn"},
        {"source":7,"target":1,"value":4, "label":"containsKeyword"},
        {"source":8,"target":10,"value":3, "label":"containsKeyword"},
        {"source":7,"target":14,"value":4, "label":"publishedBy"},
        {"source":8,"target":15,"value":6, "label":"publishedBy"},
        {"source":9,"target":1,"value":6, "label":"depicts"},
        {"source":10,"target":1,"value":6, "label":"depicts"},
        {"source":16,"target":1,"value":6, "label":"manageWebsite"},
        {"source":16,"target":2,"value":5, "label":"manageWebsite"},     
        {"source":16,"target":3,"value":6, "label":"manageWebsite"},
        {"source":16,"target":4,"value":6, "label":"manageWebsite"},
        {"source":19,"target":18,"value":2, "label":"postedOn"},
        {"source":18,"target":1,"value":6, "label":"childOf"},
        {"source":17,"target":19,"value":8, "label":"describes"},
        {"source":18,"target":11,"value":6, "label":"containsKeyword"},
        {"source":17,"target":13,"value":3, "label":"containsKeyword"},
        {"source":20,"target":13,"value":3, "label":"containsKeyword"},
        {"source":20,"target":21,"value":3, "label":"postedOn"},
        {"source":22,"target":20,"value":3, "label":"postedOn"},
        {"source":23,"target":21,"value":3, "label":"manageWebsite"},
        {"source":23,"target":24,"value":3, "label":"manageWebsite"},
        {"source":23,"target":25,"value":3, "label":"manageWebsite"},
        {"source":23,"target":26,"value":3, "label":"manageWebsite"}
    ]
}


var margin = {top: -5, right: -5, bottom: -5, left: -5};
        var width = 500 - margin.left - margin.right,
    height = 400- margin.top - margin.bottom;

        var color = d3.scale.category20();

    var force = d3.layout.force()
            .charge(-200)
            .linkDistance(30)
            .size([width + margin.left + margin.right, height + margin.top + margin.bottom]);

        var zoom = d3.behavior.zoom()
            .scaleExtent([1, 10])
            .on("zoom", zoomed);

        var drag = d3.behavior.drag()
            .origin(function(d) { console.log(d);return d; })
            .on("dragstart", dragstarted)
            .on("drag", dragged)
            .on("dragend", dragended);


        var svg = d3.select("#map").append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.right + ")")
            .call(zoom);

        var rect = svg.append("rect")
            .attr("width", width)
            .attr("height", height)
            .style("fill", "none")
            .style("pointer-events", "all");

        var container = svg.append("g");

//d3.json('http://blt909.free.fr/wd/map2.json', function(error, graph) {

                force
                    .nodes(graph.nodes)
                    .links(graph.links)
                    .start();



        var link = container.append("g")
                        .attr("class", "links")
                        .selectAll(".link")
            .data(graph.links)
                        .enter().append("line")
            .attr("class", "link")
            .style("stroke-width", function(d) { return Math.sqrt(d.value); });

        var node = container.append("g")
                        .attr("class", "nodes")
                        .selectAll(".node")
            .data(graph.nodes)
            .enter().append("g")
            .attr("class", "node")
                        .attr("cx", function(d) { return d.x; })
                        .attr("cy", function(d) { return d.y; })
                        .call(drag);

        node.append("circle")
            .attr("r", function(d) { return d.weight * 2+ 12; })
            .style("fill", function(d) { return color(1/d.rating); });


                force.on("tick", function() {
                    link.attr("x1", function(d) { return d.source.x; })
                        .attr("y1", function(d) { return d.source.y; })
                        .attr("x2", function(d) { return d.target.x; })
                        .attr("y2", function(d) { return d.target.y; });

                    node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
                });

                var linkedByIndex = {};
                graph.links.forEach(function(d) {
                    linkedByIndex[d.source.index + "," + d.target.index] = 1;
                });

                function isConnected(a, b) {
                    return linkedByIndex[a.index + "," + b.index] || linkedByIndex[b.index + "," + a.index];
                }

        node.on("mouseover", function(d){

                        node.classed("node-active", function(o) {
                            thisOpacity = isConnected(d, o) ? true : false;
                            this.setAttribute('fill-opacity', thisOpacity);
                            return thisOpacity;
                        });

                        link.classed("link-active", function(o) {
                            return o.source === d || o.target === d ? true : false;
                        });

                        d3.select(this).classed("node-active", true);
                        d3.select(this).select("circle").transition()
                                .duration(750)
                                .attr("r", (d.weight * 2+ 12)*1.5);
                })

        .on("mouseout", function(d){

                        node.classed("node-active", false);
                        link.classed("link-active", false);

                        d3.select(this).select("circle").transition()
                                .duration(750)
                                .attr("r", d.weight * 2+ 12);
                });


        function dottype(d) {
          d.x = +d.x;
          d.y = +d.y;
          return d;
        }

        function zoomed() {
          container.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
        }

        function dragstarted(d) {
          d3.event.sourceEvent.stopPropagation();
          console.log("drag started");
          d3.select(this).classed("dragging", true);
          force.start();
        }

        function dragged(d) {
          console.log("dragged");
          d3.select(this).attr("cx", d.x = d3.event.x).attr("cy", d.y = d3.event.y);

        }

        function dragended(d) {
          console.log("draggend");
          d3.select(this).classed("dragging", false);
        }

In the graph of above fiddle, I can drag it in all directions by dragging the container, whereas I want it to be dragged only horizontally and not in every direction. I have tried but could not find the code that makes the whole graph draggable.

The functions dragstart, dragged, dragend are to drag the nodes, there is no function for dragging the whole graph.

Upvotes: 0

Views: 1841

Answers (2)

Fernando
Fernando

Reputation: 11

I know this post is old but, in case anyone still wants to restrict the vertical movement from the transform, allowing a horizontal-only scrolling:

    function zoomed() {
        container.attr("transform", "translate(" + d3.event.transform.x + ",0) scale(" + d3.event.transform.k + ")")
    }

worked for me because I seem to be using d3.v4.

Upvotes: 1

D Malan
D Malan

Reputation: 11414

The whole graph is being translated in the zoomed() function. To only allow horizontal translation, change the zoomed() function to:

function zoomed() {
    container.attr("transform", "translate(" + d3.event.translate[0] + ",0)scale(" + d3.event.scale + ")");
}

d3.event.translate[0] is the mouse's horizontal movement.

Upvotes: 2

Related Questions