D3js(三):force实例

Data-Driven Documents理解

首先它是js,js本质就是dom(Document Object Model,简称DOM)的增删查改,dom的本质就是一棵树,d3本质也是对一棵树进行操作。

selections

对dom操作,最开始就是定位,也就是选择哪一块,哪一颗子树

d3.selectAll("p").style("color", "blue");

selections操作

// Update…
var p = d3.select("body")
  .selectAll("p")
  .data([4, 8, 15, 16, 23, 42])
    .text(function(d) { return d; });

// Enter…
p.enter().append("p")
    .text(function(d) { return d; });

// Exit…
p.exit().remove();

直接上码:

导入库,这里使用d3.v3,d3.v5可能有差异:

<script src="http://d3js.org/d3.v3.min.js"></script>

建立画布,并把画布svg添加到html的body或者div里

    var width = 960,
        height = 960

    var svg = d3.select("body").append("svg")
        .attr("width", width)
        .attr("height", height);

建立力矩图

    var force = d3.layout.force()
        .gravity(.05)
        .charge(-240)
        .linkDistance(160)
        .size([width, height]);

读取json数据

    d3.json("graph.json", function(error, json) {

        if (error) throw error;
        }

把数据放进force里,force就可以直接使用自己的数据了

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

依次把边添加到svg

selectAll(".link")相当于占位符,添加"line"标签,设置该line标签的属性

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

依次把节点添加到svg

节点包括node和text两部分,使用group包起来,先添加g标签再添加circle和text标签

        var node = svg.selectAll(".node")
            .data(json.nodes)
            .enter().append('g')
            .attr("class", "node")
            .style("fill","red")
            .on("mouseover", mouseover)
            .on("mouseout", mouseout)
            .call(force.drag);

        node.append("circle")
            .attr("r", 8);
        
        node.append("text")
            .attr("dy", ".35em")
            .text(function(d) { return d.name; });

定义事件 mouseover, mouseout

mouseover, mouseout为基本事件
transition变换过渡效果

        function mouseover() {
            d3.select(this).select("circle").transition()
                .duration(750)
                .attr("r", 80);
        }

        function mouseout() {
            d3.select(this).select("circle").transition()
                .duration(750)
                .attr("r", 8);
        }

定义事件 tick

实际就是补充div的属性


        force.on("tick", tick);
        function tick() {
            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 + ")"; });
        };

拖拽固定

相当于重写了drag函数

        var node_drag = d3.behavior.drag()
            .on("dragstart", dragstart)
            .on("drag", dragmove)
            .on("dragend", dragend);

        var node = svg.selectAll(".node")
            .data(json.nodes)
            .enter().append('g')
            .attr("class", "node")
            .style("fill","red")
            .on("mouseover", mouseover)
            .on("mouseout", mouseout)
            //.call(force.drag);
            .call(node_drag);
        function dragstart(d, i) {
            force.stop() // stops the force auto positioning before you start dragging
        }

        function dragmove(d, i) {
            d.px += d3.event.dx;
            d.py += d3.event.dy;
            d.x += d3.event.dx;
            d.y += d3.event.dy;
            tick(); // this is the key to make it work together with updating both px,py,x,y on d !
        }

        function dragend(d, i) {
            d.fixed = true; // of course set the node to fixed so the force doesn't include the node in its auto positioning stuff
            tick();
            force.resume();
        }

zoom

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

        var svg = d3.select("body").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);

        //specify what to do when zoom event listener is triggered
        function zoomed() {
            g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
        }

完整code:

<!DOCTYPE html>
<meta charset="utf-8">
<style>
    .link {
        stroke: #777;
        stroke-opacity: 0.5;
    }

</style>
<body>

<script src="http://d3js.org/d3.v3.min.js"></script>
<script>



    d3.json("graph.json", function(error, json) {

        if (error) throw error;

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

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

        var svg = d3.select("body").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 force = d3.layout.force()
            .gravity(.05)
            .charge(-240)
            .linkDistance(160)
            .size([width, height]);


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

        var g = svg.append("g")
            .attr("class", "everything");

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

        // var node_drag = d3.behavior.drag()
        //     .on("dragstart", dragstart)
        //     .on("drag", dragmove)
        //     .on("dragend", dragend);

        var node = g.append("g")
            .attr("class", "nodes")
            .selectAll(".node")
            .data(json.nodes)
            .enter().append('g')
            .attr("class", "node")
            .style("fill","red")
            .on("mouseover", mouseover)
            .on("mouseout", mouseout)
            .call(force.drag);
            //.call(node_drag);

        node.append("circle")
            .attr("r", 8);

        node.append("text")
            .attr("dy", ".35em")
            .text(function(d) { return d.name; });


        force.on("tick", tick);

        function tick() {
            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 + ")"; });
        };


        function mouseover() {
            d3.select(this).select("circle").transition()
                .duration(750)
                .attr("r", 80);
        }

        function mouseout() {
            d3.select(this).select("circle").transition()
                .duration(750)
                .attr("r", 8);
        }


        // function dragstart(d, i) {
        //     force.stop() // stops the force auto positioning before you start dragging
        // }
        //
        // function dragmove(d, i) {
        //     d.px += d3.event.dx;
        //     d.py += d3.event.dy;
        //     d.x += d3.event.dx;
        //     d.y += d3.event.dy;
        //     tick(); // this is the key to make it work together with updating both px,py,x,y on d !
        // }
        //
        // function dragend(d, i) {
        //     d.fixed = true; // of course set the node to fixed so the force doesn't include the node in its auto positioning stuff
        //     tick();
        //     force.resume();
        // }

        //specify what to do when zoom event listener is triggered
        function zoomed() {
            g.attr("transform", "translate(" + d3.event.translate + ")scale(" + d3.event.scale + ")");
        }


    });


</script>

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值