D3入门学习

D3是一个数据可视化工具,都说挺好。但是我个人这两天的体验来看,D3想要入门不是太简单,至少至少都要有HTML和JavaScript基础才行,对JavaScript的DOM要求也有点高。
其实网上也能找到很多学习资源。下面是我搜集的一些教程:
这里写图片描述

D3呢就是一个js库,使用它主要是用来做数据可视化的,官网上有很多酷炫的例子。
D3的官网

我最近学习的教程:
慕课网:使用D3制作图表
极客学院:D3.js入门教程

这两个教程对于初学者还是比较友好的,我前两天对D3还是一无所知,现在已经可以get到用D3画线图,面积图,柱状图,饼状图的方法了。


下面是我对画这几种图表的笔记:

线性图表

线性图表应该是最简单的图表了,我们从小学起就会画了,它可以用来描述两个变量之间的对应关系。
这里写图片描述
在绘制线性图表之前先在HTML文档中添加一个container容器,不要忘了引入D3的库文件。

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>D3-test-1</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <div id="container"></div>

    <script src="http://d3js.org/d3.v3.js"></script>
    <script src="js/index.js"></script>
</body>
</html>

index.js

var width = 500,
height = 250,
margin = {left:50, top:30, right:20, bottom:20},
g_width = width - margin.left - margin.right,
g_height = height - margin.top - margin.bottom;
//svg
var svg = d3.select("#container")   //选择container容器
.append("svg")  //添加svg元素
//定义宽高
.attr("width",width)    
.attr("height",height);

var g = d3.select("svg")
.append("g")
.attr("transform","translate("+margin.left+","+margin.top+")");//g元素偏移

//数据
var data = [1, 2, 4, 8, 3, 2, 5];

// 缩放函数,X轴线性缩放
var scale_x = d3.scale.linear()
.domain([0,data.length-1])  // 输入范围
.range([0,g_width]);    //输出范围
//Y轴缩放函数
var scale_y = d3.scale.linear()
.domain([0,d3.max(data)])
.range([g_height,0]);//倒着写是为了让纵坐标在显示的时候是从下往上增大的(因为浏览器的左边原点在左上而数学习惯是在左下)  

//绘制函数,line_generator是我们指定的绘制函数
var line_generator = d3.svg.line()
.x(function(d,i) { return scale_x(i);})//X轴的点用数据的下标来表示
.y(function(d) { return scale_y(d);})
.interpolate("cardinal");//指定拟合方式,如果没有它,图是折线形式的,有了它就很圆润了

//添加path路径,就可以绘图啦
d3.select("g")
.append("path")
.attr("d",line_generator(data));

//绘制X轴和Y轴
var x_axis = d3.svg.axis().scale(scale_x),
y_axis = d3.svg.axis().scale(scale_y).orient("left");   //orient("left")确定左边方向

g.append("g")
.call(x_axis)
.attr("transform","translate(0,"+g_height+")"); //偏移

g.append("g")
.call(y_axis)
//添加文字元素
.append("text")
.text("Price($)")
.attr("transform","rotate(-90)")    //Y轴旋转-90°
.attr("text-anchor","end")
.attr("dy","1em");

js文件我都写了详细的注释。
style样式文件用来定义container容器,path路径以及坐标轴的一些样式。

style.css

#container {
    background-color: #ccc;
    width: 500px;
    height: 250px;
}
path {
    fill: none;
    stroke: #468284;
    stroke-width: 2;
}
.domain, .tick line {
    stroke: gray;
    stroke-width: 1;
}

我觉得比较重要的就是选择元素select()和插入元素append() 操作,还有缩放函数的方法和定义X轴、Y轴的方法。这些都是基础又基础的东西!


面积图表

面积图表是在线性图表的基础上绘制的
这里写图片描述

将绘制函数改为area()函数:

//绘制函数,面积图用D3的area()函数绘制
var area_generator = d3.svg.area()
.x(function(d,i) { return scale_x(i);})
.y0(g_height)
.y1(function(d) { return scale_y(d);})
.interpolate("cardinal");

这个时候图表已经成为一个闭合的图形了:
这里写图片描述

在绘制图形后在添加一个填充样式.style("fill","#468284"):

d3.select("g")
.append("path")
.attr("d",area_generator(data))
.style("fill","#468284");

一个面积图表就完成了。


柱状图表

这里写图片描述

柱状图的要点是添加矩形元素。这里跟上面线性图表的代码风格不太一样,是因为我觉得这个demo更直观,更清晰。

<html>  
<head>  
    <meta charset="utf-8">  
    <title>完整的柱形图</title>  
</head> 

<style>
    .axis path,
    .axis line{
        fill: none;
        stroke: black;
        shape-rendering: crispEdges;
    }

    .axis text {
        font-family: sans-serif;
        font-size: 11px;
    }

    .MyRect {
        fill: steelblue;
    }

    .MyText {
        fill: white;
        text-anchor: middle;
    }
</style>

<body>  
    <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>  
    <script>

    //画布大小
    var width = 400;
    var height = 400;

    //在 body 里添加一个 SVG 画布   
    var svg = d3.select("body")
    .append("svg")
    .attr("width", width)
    .attr("height", height);

    //画布周边的空白
    var padding = {left:30, right:30, top:20, bottom:20};

    //定义一个数组
    var dataset = [10, 20, 30, 40, 33, 24, 12, 5];

    //x轴的比例尺
    var xScale = d3.scale.ordinal()
    .domain(d3.range(dataset.length))
    .rangeRoundBands([0, width - padding.left - padding.right]);

    //y轴的比例尺
    var yScale = d3.scale.linear()
    .domain([0,d3.max(dataset)])
    .range([height - padding.top - padding.bottom, 0]);

    //定义x轴
    var xAxis = d3.svg.axis()
    .scale(xScale)
    .orient("bottom");

    //定义y轴
    var yAxis = d3.svg.axis()
    .scale(yScale)
    .orient("left");

    //矩形之间的空白
    var rectPadding = 4;

    //添加矩形元素
    var rects = svg.selectAll(".MyRect")
    .data(dataset)
    .enter()
    .append("rect")
    .attr("class","MyRect")
    .attr("transform","translate(" + padding.left + "," + padding.top + ")")
    .attr("x", function(d,i){
        return xScale(i) + rectPadding/2;
    } )
    .attr("y",function(d){
        return yScale(d);
    })
    .attr("width", xScale.rangeBand() - rectPadding )
    .attr("height", function(d){
        return height - padding.top - padding.bottom - yScale(d);
    });

    //添加文字元素
    var texts = svg.selectAll(".MyText")
    .data(dataset)
    .enter()
    .append("text")
    .attr("class","MyText")
    .attr("transform","translate(" + padding.left + "," + padding.top + ")")
    .attr("x", function(d,i){
        return xScale(i) + rectPadding/2;
    } )
    .attr("y",function(d){
        return yScale(d);
    })
    .attr("dx",function(){
        return (xScale.rangeBand() - rectPadding)/2;
    })
    .attr("dy",function(d){
        return 20;
    })
    .text(function(d){
        return d;
    });

    //添加x轴
    svg.append("g")
    .attr("class","axis")
    .attr("transform","translate(" + padding.left + "," + (height - padding.bottom) + ")")
    .call(xAxis); 

    //添加y轴
    svg.append("g")
    .attr("class","axis")
    .attr("transform","translate(" + padding.left + "," + padding.top + ")")
    .call(yAxis);

</script>  
</body>  
</html>  

要特别注意的地方是理解enter() 的用法,在极客学院的教程上是这样讲的:

有数据,而没有足够图形元素的时候,使用此方法可以添加足够的元素。
如果数组为 [3, 6, 9, 12, 15],将此数组绑定到三个 p 元素的选择集上。可以想象,会有两个数据没有元素与之对应,这时候 D3 会建立两个空的元素与数据对应,这一部分就称为 Enter。而有元素与数据对应的部分称为 Update。如果数组为 [3],则会有两个元素没有数据绑定,那么没有数据绑定的部分被称为 Exit。示意图如下所示。

这里写图片描述

外部数据文件的读取

慕课网的教程讲到了外部数据文件的读取,我觉得挺有用的
值得注意的一点是浏览器读取本地文件,它有一个跨域请求的问题,会报如下的错误:
这里写图片描述
解决办法是使用server提供的一种访问机制,用Python启用服务器,你要是想运行呢,首先你要安装python,下面是python2.到3以下版本执行的命令

python -m SimpleHTTPServer 8888 &

3以上用下面的命令

python -m http.server 8888 &

启用服务是在当前图表文件内运行的,启用服务后在浏览器中输入localhost:8888 就可以访问自己写的图表了
我们要读取的数据文件名为data.csv

year,population
1953,5.94
1964,6.95
1982,10.08
1990,11.34
2000,12.66
2010,13.40

6次人口普查的数据,这里用到了D3的d3.csv(url[,accessor][,callback])函数,以下面的函数为例,第一个参数是必选的,是我们要读取的csv文件的路径;第二个参数是数据的处理,定义一个type函数将字符串转换为数值的形式;第三个参数用一个函数调用的方式使用数据,把最终的数据放到data数组当中。

d3.csv("data.csv",type,function(data) {
    console.log(data);
    ···
});

function type(d) {
    d.population =+ d.population;
    return d;
}

这里写图片描述

饼状图表

这里写图片描述

饼状图表的要点就是:第一我们要用d3.svg.arc() 画圆的函数;第二就是起始角度的设置:
HTML还是像线性图表一样定义一个container容器即可

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>饼状图表</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <div id="container"></div>

    <script src="http://d3js.org/d3.v3.js"></script>
    <script src="js/index.js"></script>
</body>
</html>

数据文件data.csv

education,population
大专及以上,11964
高中和中专,18799
初中,51966
小学,35876
文盲人口,5466

index.js

d3.csv("data.csv",type,function(data) {

    var width = 400,
    height = 400;
    // 添加svg画布
    var svg = d3.select("#container")
    .append("svg")
    .attr("width",width)
    .attr("height",height);
    // 添加g元素
    var g = svg.append("g")
    .attr("transform","translate(200,200)");

    // 定义一个饼状图
    var arc_generator = d3.svg.arc()
    .innerRadius(0)
    .outerRadius(200);

    // 起始角度
    var angle_data = d3.layout.pie()
    .value(function(d) {return d.population;});

    // 颜色
    var color = d3.scale.category10();

    // 绑定数据
    g.selectAll("path")
    .data(angle_data(data))
    .enter()
    // 添加path元素
    .append("path")
    .attr("d",arc_generator)
    .style("fill",function(d,i){return color(i);});

    // 添加文字标签
    g.selectAll("text")
    .data(angle_data(data))
    .enter()
    // 添加text元素
    .append("text")
    .text(function(d) {return d.data.education;})
    .attr("transform", function(d){return "translate("+arc_generator.centroid(d)+")";})
    .attr("text-anchor","middle");

});
function type(d) {
    d.population = +d.population;
    return d;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值