2

题记: d3学习交流。

本个例子技术点重点和难点:
1. 箭头如何显示在节点相连的直线上
2. 箭头与节点圆之间的距离由于缩放的动态原因如何控制,使箭头一直保持在圆外围
3. 鼠标中间键滚动带动图像缩放(此点若知事件则较易)
4. 鼠标拖拽控制条实现图像缩放。
5. 第3,4两个控件结合交替使用实现缩放效果(关键是两个事件的缩放数值倍数范围和在图中缩放距离范围要保持一致。

由于这个模型是从我在做的项目中抽取的模型例子,所以,界面比较丑,旁边的图拽条的 “+”,“-"图片我也没加上去。请输入图片描述

 <!DOCTYPE html>
<html>
  <head>
        <meta charset="utf-8">
        <title>network </title>
        <script type="text/javascript" src="d3.v3.min.js"></script> 
  </head>
  <body>
        <script type="text/javascript">
        var h=500;
        var w=800;

        var scale_max = 2.3;
        var scale_min = 0.2;
        var current_scale = 1.1; 
        var bar_len = 100;
        var border_len = 20 ; 
        var colors = d3.scale.category20() 
        //(1)定义节点和联系对象数组
        var dataset = {
        nodes:[//节点
                { name:"Peter",r:16},
                { name:"Bob",r:21},
                { name:"Tony",r:31},
                { name:"Davir",r:25},
                { name:"Edward",r:27},
                { name:"Army",r:19},
                { name:"Jonn",r:35},
                { name:"Hannah",r:33},
                { name:"Jack",r:29},
                { name:"Jerry",r:32} 
            ],
        edges:[//边
                { source:0,target:1,weight:1,color:1},
                { source:0,target:2,weight:3,color:4},
                { source:0,target:3,weight:4,color:6},
                { source:0,target:4,weight:6,color:65},
                { source:1,target:5,weight:3,color:76},
                { source:2,target:5,weight:8,color:879},
                { source:2,target:5,weight:7,color:989},
                { source:3,target:4,weight:9,color:643},
                { source:5,target:8,weight:1,color:54},
                { source:5,target:9,weight:3,color:54}, 
                { source:6,target:7,weight:4,color:45},
                { source:7,target:8,weight:0,color:43},
                { source:2,target:8,weight:8,color:243},
                { source:3,target:8,weight:1,color:43},
                { source:5,target:8,weight:5,color:13},
                { source:6,target:8,weight:3,color:351},
                { source:8,target:9,weight:1,color:1}
            ]
        }; 

        //(2)转化数据为适合生成力导向图的对象数组
        var force=d3.layout.force()
                    .nodes(dataset.nodes)//加载节点数据
                    .links(dataset.edges)//加载边数据
                    .size([w,h])//设置有效空间的大小
                    .linkDistance(150)//连线的长度
                    .charge(-500)  
                    .start();//设置生效
        var svg = d3.select("body")
                .append("svg")
                .attr("width",w)
                .attr("height",h)
                .attr("pointer-events","all")     .call(d3.behavior.zoom().on("zoom",redraw))//redraw
                .on("mousedown.zoom",null)
                .append('svg:g')
                .attr("cursor","pointer");

        var marker = d3.select("svg").append("svg:defs")
                       .selectAll("marker")
                       .data(dataset.nodes) //not edges
                       .enter()
                       .append("svg:marker");
                marker.attr({
                        id:function(d){
                            return "marker-" + d.r;
                        },
                        viewBox:"0 -5 10 10",
                        refX:function(d){
                            console.log("d.r:" + d.r);
                            return d.r ;
                        },
                        markerWidth:10,
                        markerHeight:10,
                        orient: "auto"
                       })
                       .append('svg:path')
                       .attr('d',"M0,-5L10,0L0,5")
                       .attr("fill",function(d){ 
                            return "black";
                       });
        var dtb = d3.select("svg")
                    .append("svg:g")
                    .attr({
                        heigth: bar_len,
                        width: 200 ,
                        x: 0,
                        y: 0 
                    });
            dtb.append('rect')//top
               .attr({
                    width:border_len,
                    height:border_len,
                    x: 10,
                    y: 10
               })
               .attr("fill",'black');
            dtb.append("rect") //bottom
               .attr({
                    width:border_len,
                    height:border_len,
                    x:10,
                    y:130
               })
               .attr("fill","black");
            dtb.append("rect")
                .attr({
                    width:4,
                    height:bar_len,
                    x:19,
                    y:30
                })
                .attr("fill","grey");

        var bar = dtb.append('rect')
                     .attr({
                        width:20,
                        height:5,
                        x: 10,
                        y: 82,
                        fill:"green",
                        cursor:"pointer"
                     })
                     .call(d3.behavior.drag().on("drag",dragmove));//dragmove


        //(3)创建作为连线的svg直线
        var edges = svg.append('g')
                .attr('cursor','pointer')
                .selectAll(".link")
                .data(dataset.edges)
                .enter()
                .append("line")
                .attr("class","link")
                .style("stroke",function(d){//  设置线的颜色
                    return colors(d.color);
                })
                .style("stroke-width",function(d,i){//设置线的宽度
                    return 1.5;
                }) 
                .attr("marker-end",function(d){  
                    return "url(#marker-" + (d.target.r) + ")";
                });
        //(4) 创建作为连线的svg圆形
        var nodes = svg.selectAll(".node")
                .data(dataset.nodes) 
                .enter().append('g')
                .attr('class','node')
                .call(force.drag);//可以拖动 

            nodes.append("svg:circle")
                .attr("r",function(d){    
                    return d.r;//the r of circle
                })
                .style("fill",function(d){
                    return colors(d.r*d.r*d.r);
                });
           nodes.append('text')
                .attr("text-anchor", "middle")
                .attr("font-size", "10px")
                .attr('stroke', 'black')
                .attr('stroke-width', function (d) {
                    return 0;
                })
                .text(function (d) {
                    return d.name;
                });

           nodes.append("title")
            .text(function (d) {
                return d.name;
            });


        //(5)打点更新,没有的话就显示不出来了
         force.on('tick',function(){
            edges.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;
            });
        //(6)设置节点坐标,节点先生成再确定坐标的
        nodes.attr("cx",function(d){//节点有坐标属性
                return d.x;
            })
            .attr("cy",function(d){
                return d.y;
            }).attr("transform", function (d) {
                    return "translate(" + d.x + "," + d.y + ")";
            }); 
        });

        var scale = 1.1;
        var currentY = 0;
        function redraw(){  //放大缩小 鼠标滑动   scale放大倍数,translate是转变,转换

            scale = d3.event.scale;
            if(scale > scale_max || scale < scale_min){  
                return ;
            }
            currentY = scale/(scale_max-scale_min)*bar_len + 18;
            bar.attr("y",currentY);
            console.log("scale:" + scale +",currentY:" + currentY); 
            svg.attr("transform","translate(" + d3.event.translate + ")" + "scale(" + scale + ")" ); 
        }        

        function dragmove(){ 
            var x = 0;   //not move in x axis
            var dy = d3.event.y; 
            var diffY = dy ;  //+currentY - 30 ; 

            if(diffY  > 130){//bar_len + border_len+ margin 
                diffY = 125;
                return ;
            }
            if(diffY < 30){ //border_len+ margin 
                diffY = 30;
                return ;
            }
            //console.log( "diffY:" + diffY + "dy:" + dy);
            scale = diffY /bar_len*(scale_max-scale_min);  
            //console.log("scale:" + scale); 
            bar.attr("y",diffY) 
            svg.attr("transform","translate(" + [(w/3)-(w*current_scale/3),(h/2) - (h*current_scale/2)] +")" + "scale(" + scale + ")" );
        } 

  </script>

    </body>
</html>

Amyding929
178 声望7 粉丝

好好学习。


引用和评论

0 条评论