功能点

d3.js饼图绘制,V3与V4.

2017-07-17  本文已影响645人  Kaidi_G

饼图的绘制稍微复杂一点点,主要是网上很多教程还是老版本d3.
这里用的是 D3 4.0 API Reference.

效果图

和上几篇文章写到的一样,首先新建svg,考虑缩放问题,
长高"100%",提供给后面svg使用.
在这里我直接给了两个list做数据了,一个是用来画饼图的数据,一个是上面的文字.
同时新建一个list存放你想要用的颜色列表.

var width = "100%";
    var hight = "100%";
    var radius = 150;                            //饼图半径,后面也用做图像相对于原点的偏移量
    var color = ["steelblue","steelblue"];     //颜色列表
    var gender_list = ["女性用户","男性用户"];
    var gender_list_value = ["30","40"];

接下来新建svg,我在id为gender_plotdiv下append了这个svg.
在这里饼图的结构是:<svg>内部一个<g>来装载整个饼图,这个<g>里面有数个<g>代表饼图的每一小片,而每个小片是由一个<path>和一个<text>组成的.
也就是说,饼图的每一部分是一个<path>!所有的样式都要针对<path>来设定.

直方图的话是一个rec

一个饼图的结构

和直方图不同的是,饼图没有比例尺了,
这里直接把数据绑定给svg:.data([gender_list_value])

    var gender_svg = d3.select("#gender_plot")
        .append("svg")              //创建svg
            .attr("width", width)  //长
            .attr("height", hight) //高
            .attr("viewBox","0 0 300 300") //视窗,因为上面饼图的半径为150,这里视窗就刚好设定为直径300
            .attr("preserveAspectRatio","xMaxYMax meet")
            .data([gender_list_value]) //关联数据,注意要加方括号
        .append("g")                //make a group to hold our pie chart
            .attr("transform", "translate(" + radius + "," + radius + ")");   //move the center of the pie chart from 0, 0 to radius, radius

接下来是根据每一片的弧度啊,半径啊,起始角啊什么的计算每一个<path>的路径.
用的是d3的arc()方法会帮你计算这些,返回的既是一条path中的d属性.
d属性具体说明在这里.
从某种意义上来讲,这里的arc()方法有点类似画直方图时的比例尺,只不过在调用的时候是,输入数据list后输出算出每一部分相应的path路径.

这里必须设定圆弧的外半径内半径. (不然没法算路径啊是吧...)
外半径就是饼图外圆圈的半径,内径一般为0,表示没有空心,但是如果你想画圆环图,这里的内径相应的给出就好.

    var arc = d3.arc()              //这里是用arc()方法来创建后面的path
        .outerRadius(radius)
         .innerRadius(0);

    var pie = d3.pie()           //pie方法,自动根据原数据list计算每一部分的扇形角度占比
        .value(function(d) { return d; });    //用无名函数给pie方法依次传输绑定的数据

    var arcs = gender_svg.selectAll("g.slice")     //给每个饼图的部分一个类名,叫slice
        .data(pie)                          //把pie方法传进来,用于放置饼图每一部分
        .enter()                            //用enter方法
            .append("g")                //补足g元素
                .attr("class", "slice");    //添加类名

接下来输入数据,根据输出的path路径依次生成path,并加入text部分:
enter方法参考之前的文章d3.js直方图与坐标轴基础.

 gender_svg.selectAll("g.slice")     //给每个饼图的部分一个类名,叫slice
        .data(pie)                          //把pie方法传进来,用于放置饼图每一部分
        .enter()                            //用enter方法
            .append("g")                //补足g元素
                .attr("class", "slice")    //添加类名
            .append("path") //加入path元素
                .attr("fill", function(d, i) { return color[i]; } )//颜色选择根据数据的索引按顺序给
                .attr("stroke","white")//设定描边的颜色,笔画粗线默认
                .attr("d", arc) //设定d属性!既Path的路径,由arc方法给出!
                .attr("opacity",0.4) //设定透明度
        .on("mouseover",function(d,i){ //鼠标交互动态效果
            d3.select(this)
                .attr("opacity",1);
        })
        .on("mouseout",function(d,i){
            d3.select(this)
                .transition()
                .duration(500)
                .attr("opacity",0.4);
        })
        .on("click",function () {

        });
                                 

        gender_svg.selectAll("g.slice").append("text")  //给饼图的每一部分添加text元素
                .attr("transform", function(d) {                   
                      d.innerRadius = 0; 
                      d.outerRadius = radius;
                      return "translate(" + arc.centroid(d) + ")";        //返回path的中心用于设置文字相对于(0,0)的偏移
                  })
                .attr("text-anchor", "middle") //文字居中
                .attr("font-size", "80%")//文字大小
                .text(function(d, i) { return gender_list[i]; }); //文字内容从数据list中根据index获取

到此,首图上的饼图就应该可以实现啦~
:)


这里是V3版本

主要只有两个地方的不同,既axis的语法和scale的语法.

var width = "100%";
    var hight = "100%";
    var radius = 150;                            //radius
    var color = ["steelblue","steelblue"];     //builtin range of colors
  var genders = {{gender_list}}

if (genders[0]== "f"){
  var gender_list = ["女性用户","男性用户"];
}
else if (genders[0]== "m"){
  var gender_list = ["男性用户","女性用户"];
}

    var gender_list = ["女性用户","男性用户"];
    var gender_list_value = {{gender_list_value}};

    var gender_svg = d3.select("#gender_plot")
        .append("svg")         
            .attr("width", width)          
            .attr("height", hight)
            .attr("viewBox","0 0 300 350")
            .attr("preserveAspectRatio","xMaxYMax meet")
            .data([gender_list_value])
          .append("g")             
            .attr("transform", "translate(" + radius + "," + radius + ")");   

    var arc = d3.svg.arc()       //这里语法不同       
        .outerRadius(radius)
            .innerRadius(0);

    var pie = d3.layout.pie()           //这里语法不同
        .value(function(d) { return d; });   

    gender_svg.selectAll("g.slice")     
        .data(pie)                         
        .enter()                          
            .append("g")               
                .attr("class", "slice")   
            .append("path")
                .attr("fill", function(d, i) { return color[i]; } )
                .attr("stroke","white")
                .attr("d", arc)
                .attr("opacity",0.4)
        .on("mouseover",function(d,i){
            d3.select(this)
                .attr("opacity",1);

          tooltip.html( parseInt(100*(gender_list_value[i]/(gender_list_value[0]+gender_list_value[1])))+"%")
                    .style("left", (d3.event.pageX+10) + "px")
                    .style("top", (d3.event.pageY - 10) + "px")
                    .style("opacity",1.0);
        })
        .on("mouseout",function(d,i){
            d3.select(this)
                .transition()
                .duration(500)
                .attr("opacity",0.4);
          tooltip.style("opacity",0.0);
        })
         .on("mousemove",function(d){
            tooltip.style("left", (d3.event.pageX+ 10) + "px")
                    .style("top", (d3.event.pageY - 10) + "px");
        })
        .on("click",function () {

        });
                                    

        gender_svg.selectAll("g.slice").append("text")                                     
                .attr("transform", function(d) {                   
                d.innerRadius = 0;
                d.outerRadius = radius;
                return "translate(" + arc.centroid(d) + ")";        
            })
            .attr("text-anchor", "middle")
                .attr("font-size", "80%")
            .text(function(d, i) { return gender_list[i]; });
上一篇 下一篇

猜你喜欢

热点阅读