一些d3.js的图


布局:layout

作用: 将不适合用于绘图的数据转换成了适合用于绘图的数据。所以说,布局的作用可以解释为:数据转换。

今天选力导向图(Force)和饼状图(Pie)作为例子。


力导向图:

在二维或三维空间里配置节点,节点之间用线连接,称为连线。各连线的长度几乎相等,且尽可能不相交。节点和连线都被施加了力的作用,力是根据节点和连线的相对位置计算的。根据力的作用,来计算节点和连线的运动轨迹,并不断降低他们的能量,最终达到一种能量很低的安定状态。力导向图能表示节点之间多对多的关系。

现在我们拿到了这样的一些初始数据:

            var nodes = [ { name: "计科"    }, { name: "经管" },
                      { name: "法学"    }, { name: "文艺"   },
                      { name: "理学"   }, { name: "信息"    },
                         { name: "土建"    } ];
                     
            var edges = [  { source : 0  , target: 1 } , { source : 0  , target: 2 } ,
                       { source : 0  , target: 3 } , { source : 1  , target: 4 } ,
                       { source : 1  , target: 5 } , { source : 1  , target: 6 }  ];    

这两个数组分别是表示节点和连线。

要作图,我们首先需要在页面中定义一块svg画布。

// 定义一下svg的宽和高。
 var height = 1000;
 var width = 1000;
var svg = d3.select("body").append("svg").attr("width",width).attr("height",height); // 添加一块svg画布

接下来需要一个力导向图的布局:

var force = d3.layout.force()
                     .nodes(nodes)
                     .links(links)
                     .size([width,height])
                     .linkDistance(150)
                     .charge([400]);
force.start()// 开始作用

上面的代码中 nodes:指定节点数组 links :指定连线数组 size : 指定作用范围 linkDistance:指定连线长度 charge: 相互之间的作用力


转换后,节点对象里多了一些变量。其意义如下:
index - 节点的索引号
px, py - 节点上一个时刻的坐标
x, y - 节点的当前坐标
weight - 节点的权重


接下来,绘制的图形元素有:

  • line 线段,连线
  • cilcle 圆,表示节点
  • text 文字,描述节点
//添加连线 
 var svg_edges = svg.selectAll("line")
     .data(edges)
     .enter()
     .append("line")
     .style("stroke","#ccc")  //线的颜色
     .style("stroke-width",1); // 线的宽度
 
 var color = d3.scale.category20(); //产生随机颜色
 
 //添加节点 
 var svg_nodes = svg.selectAll("circle")
     .data(nodes)
     .enter()
     .append("circle")
     .attr("r",20)  // 圆的半径
     .style("fill",function(d,i){
         return color(i);   // 填充圆的颜色
     })
     .call(force.drag);  //使得节点能够拖动

 //添加描述节点的文字
 var svg_texts = svg.selectAll("text")
     .data(nodes)
     .enter()
     .append("text")
     .style("fill", "black")
     .attr("dx", 20)
     .attr("dy", 8) // 如果不要这两行,字会出现在节点的右上角
     .text(function(d){
        return d.name;
     });

最后,在监听器里完成刷新:

force.on("tick", function(){ //对于每一个时间间隔
    //更新连线坐标
    svg_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; });
 
    //更新节点坐标
    svg_nodes.attr("cx",function(d){ return d.x; })
        .attr("cy",function(d){ return d.y; });

    //更新文字坐标
    svg_texts.attr("x", function(d){ return d.x; })
       .attr("y", function(d){ return d.y; });
 });

下面是饼状图的代码:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>一个饼状图</title>
    </head>
    <body>
        <script src="http://d3js.org/d3.v3.min.js" charset="UTF-8"></script>>
        <script>
            var dataset = [40,23,15,34,55,23];
            var dataset2 = ["土建","法学","经管","计科","制造","文艺"];
            
            var width = 1000;
            var height = 1000;
            
            var svg = d3.select("body")
                        .append("svg")
                        .attr("width",width)
                        .attr("height",height);
                        
            var color = d3.scale.category20();
            
            var pie = d3.layout.pie() //创建一个pie布局,他拥有处理数据的能力
                        
            var piedata = pie(dataset); // 把数据交给pie来处理,结果保存在piedata中
            
            var outR = 300;  //设置饼状图的内径
            var innerR = 100; // 外径
            
            //现在我们需要一个弧生成器
            var arc = d3.svg.arc()        
                        .innerRadius(innerR)
                        .outerRadius(outR);
            
            //svg中添加几个g元素,每个用于放一段弧
            var arcs =svg.selectAll("g")
                         .data(piedata)
                         .enter()
                         .append("g")
                         .attr("transform","translate("+(width/2)+","+(width/2)+")"); 
            //平移,这里是指向右和向下各平移width/2;
            //给每个g添加一个path
            arcs.append("path")
                .attr("fill",function(d,i){
                    return color(i);
                })
                .attr("d",function(d,i){
                    return arc(d); arc(d)的d是被绑定的数据,arc(d)返回值赋给路径的d属性
                });
                
            arcs.append("text")
                .attr("transform",function(d){
                    return "translate("+arc.centroid(d)+")" // 弧线中心
                })
                .attr("text-anchor","middle") //居中
                .text(function(d,i){
                    return dataset2[i]; // 这里将要添加的文本放入便可以了
                })
        </script>
    </body>
</html>

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容