安装和配置
安装d3js
在d3js的官网上可以直接下载d3js的文件,其中包含一个完整版和mini版,差别并不是很大。调试的时候可以使用完整版,发布的时候可以使用mini版,提高加载速度
本地服务器调试
可以利用python创建本地服务器进行调试,也可以安装Apache软件进行调试。使用python进行本地调试注意:
- python2.0 python -m SimpleHTTPServer 8888
- python3.0 python -m Http.server 8888
基本操作
数据
加载数据
- 加载csv数据,可以通过d3.csv(data,function) 进行操作
- 加载json数据,跟上面是一样的,只需要将csv改为json就行
d3.csv('winemag-data-130k-v2.csv',function(data) {console.log(data)})
d3.json('winemag-data-130k-v2.json',function(data){console.log(data)})
绑定数据
上述操作将数组的数据和段落进行绑定
将上述代码最后一段修改,可以将传入的数据输出
SVG
条形图
绘制SVG并将数据绑定到图形上
//Width and height
var w = 500;
var h = 50;
//Data
var dataset = [ 5, 10, 15, 20, 25 ];
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", 500)
.attr("height", 50);
var circles = svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle");
circles.attr("cx", function(d, i) {
return (i * 50) + 25;
})
.attr("cy", h/2)
.attr("r", function(d) {
return d;
});
绘制条形图,并且根据数组的大小和长度调整柱形图的宽度
//Width and heightvar
w = 500;var h = 100;var dataset = [];
//Initialize empty array
for (var i = 0; i < 25; i++) { //Loop 25 times var newNumber = Math.random() * 20; //New random number (0-30)
dataset.push(newNumber); //Add new number to array}
/Create SVG elementvar
svg = d3.select("body").append("svg")
.attr("width", 500)
.attr("height", 100)
var bar = svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr('x',0)
.attr('y',0)
.attr('height',50)
.attr('width',20)
bar.attr("x", function(d, i) {
return (i *(w/dataset.length))
})
.attr('y',function(d) {
return h-d*4
})
.attr('width',function(d){
return w/dataset.length-2
})
.attr("height", function(d) {
return d*4; });
//加标签
svg.selectAll('text').data(dataset)
.enter()
.append('text')
.text(function(d) {
return d })
.attr("x", function(d,i) { return i* (w/dataset.length)+2})
.attr("y",function(d) {return h-(d*4)+10})
.attr('font-family','sans-serif')
.attr('font-size','11px') .attr('fill','white')
散点图
散点图的画法实际上与前面的是一致的,只是需要更改的是circle和设置x,y以及半径
var dataset_2 = [[5, 20], [480, 90], [250, 50], [100, 33], [330, 95],[410, 12], [475, 44], [25, 67], [85, 21], [220, 88] ];
var svg2=d3.selectAll('body').append('svg')
.attr("height",h)
.attr("width",w)
svg2.selectAll('circle').data(dataset_2)
.enter().append('circle')
.attr("cx", function(d) {return d[0]})
.attr("cy", function(d) {return d[1]})
.attr('r',function(d){return Math.sqrt(h-d[1])})
svg2.selectAll('text').data(dataset_2).enter().append('text').text(function(d) {return d[0]+','+d[1]})
.attr('x',function(d){return d[0]+3}) .attr('y',function(d) {return d[1]+3}) .attr('font_size','2px')
定义坐标轴
d3中的call函数会取得代码链中传递过来的元素,然后再把它交给其他函数(括号里面的函数)
//Width and height
ar w = 500;
var h = 300;
var padding = 20
;var dataset = [ [5, 20], [480, 90], [250, 50], [100, 33], [330, 95], [410, 12], [475, 44], [25, 67], [85, 21], [220, 88], [600, 150] ];
//Create scale functions
var xScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[0]; })])
.range([padding, w - padding * 2]);
var yScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })])
.range([h - padding, padding]);
var rScale = d3.scaleLinear() .domain([0, d3.max(dataset, function(d) { return d[1]; })])
.range([2, 5]);//Define X axis
var xAxis = d3.axisBottom() .scale(xScale)
.ticks(5);
var yAxis = d3.axisLeft() .scale(yScale)
.ticks(5);
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Create circles
svg.selectAll("circle")
.data(dataset)
.enter()
.append("circle")
.attr("cx", function(d) { return xScale(d[0]); }) .attr("cy", function(d) { return yScale(d[1]); }) .attr("r", function(d) { return rScale(d[1]); });
//Create labels
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function(d) { return d[0] + "," + d[1]; }) .attr("x", function(d) { return xScale(d[0]); })
.attr("y", function(d) { return yScale(d[1]); }) .attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "red")
;//Create X axis
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(0," + (h - padding) + ")")
call(xAxis);
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate("+padding+ ",0)")
.call(yAxis);
更新视图
对于视图的更新书中所讲的是d3.v3的使用,v5的版本貌似对此有过更改,此代码只能更新数据,但是更新过程中缺少动画效果。
对于常见的更新数据主要有以下常规步骤
- 设置图像基本信息
- 生成初始数据
- 生成比例尺
- 生成坐标轴
- 生成绘图元素(圆或者矩阵和标签
- 设置监听器或者定时器
- 将获取数据和设置比例尺,标签部分重写一遍
//Width and height
var w = 1000;
var h = 300;
var padding = 20;
// 生成随机数
valueNum=100
var dataset=[]
for (var i=0;i < 100;i++){
var num=Math.floor(Math.random()*100)
dataset.push(num)
}
// 生成比例尺
var xScale=d3.scaleOrdinal().domain(d3.range(dataset.length))
.range([0,w],0.05)
var yScale=d3.scaleLinear().domain([0,d3.max(dataset)])
.range([h-padding,padding])
//生成坐标轴
var xAxis=d3.axisBottom().scale(xScale).ticks(5)
var yAxis=d3.axisLeft().scale(yScale).ticks(5)
//生成svg
var svg=d3.select('body').append('svg').attr('width',w).attr('height',h)
//生成柱形图并绑定数据
svg.selectAll('rect').data(dataset).enter().append('rect')
.attr('x',function(d,i){return xScale.domain()[i]*10})
.attr('y',function(d) {return h-yScale(d)})
.attr('width',10)
.attr('height',function(d){return yScale(d)})
.attr('fill','black')
//生成标签
svg.selectAll('text').data(dataset).enter().append('text').text(function(d){return d})
.attr('x',function(d,i) {return xScale.domain()[i]*10+2})
.attr('y',function(d) {return h-yScale(d)+14})
.attr('font-size','8px')
.attr('font-family','san-serif')
.attr('fill','red')
// 设置监听
d3.select('p').on('click', function(){
// 生成随机数
var valueNum=100
var dataset=[]
for (var i=0;i<100;i++){
var num=Math.floor(Math.random()*100)
dataset.push(num)}
//更新比例尺
var xScale=d3.scaleOrdinal().domain(d3.range(dataset.length))
.range([0,w],0.05)
var yScale=d3.scaleLinear().domain([0,d3.max(dataset)])
.range([h-padding,padding])
// 更新数据
svg.selectAll('rect').data(dataset).transition().duration(1000)
.each(function(d,i){
d3.select(this)
.attr('x',xScale.domain()[i]*10)
.attr('y',h-yScale(d))
.attr('width',10)
.attr('height',yScale(d))
.attr('fill','black')
})
svg.selectAll('text').data(dataset).enter().append('text').text(function(d){return d})
.attr('x',function(d,i) {return xScale.domain()[i]*10+2})
.attr('y',function(d) {return h-yScale(d)+14})
.attr('font-size','8px')
.attr('font-family','san-serif')
.attr('fill','red')
})
增加数据
在这个过程中需要注意的是设置新增加的那个数据的位置,已经设置总体更新的过渡函数。注意选择器的使用,不要用错了主体,从而导致新增的数据无法显示
这个方法虽然能够更新数据,但是在删除的时候会出现数据与标签对不上的问题,因此在更新数据时,更应该尝试使用键值对(字典)的形式来绑定数据
//生成数据
var dataset=[]
var maxvalue=25
for (var i=0;i < maxvalue;i++){
var num=Math.floor(Math.random()*maxvalue)
dataset.push(num)
}
//宽高
var w = 1000;
var h = 300;
var padding = 20;
//生成比例尺
var xScale=d3.scaleOrdinal().domain(d3.range(dataset.length))
.range([0,w],0.05)
var yScale=d3.scaleLinear().domain([0,d3.max(dataset)])
.range([h-padding,padding])
//生成svg
var svg=d3.select('body').append('svg').attr('width',w).attr('height',h)
//生成柱形图并绑定数据
svg.selectAll('rect').data(dataset).enter().append('rect')
.attr('x',function(d,i){return xScale.domain()[i]*(w/dataset.length)})
.attr('y',function(d) {return h-yScale(d)})
.attr('width',w/dataset.length-2)
.attr('height',function(d){return yScale(d)})
.attr('fill','black')
//生成标签
svg.selectAll('text').data(dataset).enter().append('text').text(function(d){return d})
.attr('x',function(d,i) {return xScale.domain()[i]*(w/dataset.length)+(w/dataset.length)/2})
.attr('y',function(d) {return h-yScale(d)+20})
.attr('font-size','10px')
.attr('font-family','san-serif')
.attr('fill','red')
//增加数据
d3.select('p').on('click',function(){
var num=Math.floor(Math.random()*maxvalue)
dataset.push(num)
xScale.domain(d3.range(dataset.length))
yScale.domain([0,d3.max(dataset)])
var bars=svg.selectAll('rect').data(dataset)
bars.enter().append('rect').attr('x',w-(w/dataset.length)).attr('y',function(d){return h-yScale(d)}).attr('width',(w/dataset.length)-2).attr('height',function(d){return yScale(d)})
.attr('fill','black')
bars.transition().duration(1000).attr('x',function(d,i){return xScale.domain()[i]*(w/dataset.length)})
.attr('y',function(d) {return h-yScale(d)})
.attr('width',w/dataset.length-2)
.attr('height',function(d){return yScale(d)})
.attr('fill','black')
var text=svg.selectAll('text').data(dataset)
text.enter().append('text').text(function(d){return d})
.attr('x',w-(w/dataset.length))
.attr('y',function(d){return h-yScale(d)+20})
.attr('font-size','12px')
.attr('font-family','san-serif')
.attr('fill','red')
text.transition().duration(1000).attr('x',function(d,i) {return xScale.domain()[i]*(w/dataset.length)+(w/dataset.length)/2})
.attr('y',function(d) {return h-yScale(d)})
.attr('font-size','10px')
.attr('font-family','san-serif')
.attr('fill','red')
//删除数据
d3.select('#delete').on('click',function(){
dataset.shift()
xScale.domain(d3.range(dataset.length))
yScale.domain([0,d3.max(dataset)])
var bars=svg.selectAll('rect').data(dataset)
bars.enter().append('rect').attr('x',w-(w/dataset.length)).attr('y',function(d){return h-yScale(d)}).attr('width',(w/dataset.length)-2).attr('height',function(d){return yScale(d)})
.attr('fill','black')
bars.transition().duration(1000).attr('x',function(d,i){return xScale.domain()[i]*(w/dataset.length)})
.attr('y',function(d) {return h-yScale(d)})
.attr('width',w/dataset.length-2)
.attr('height',function(d){return yScale(d)})
.attr('fill','black')
bars.exit().transition().duration(1000).attr('x',w-(w/dataset.length)).remove()
var text=svg.selectAll('text').data(dataset)
text.enter().append('text').text(function(d){return d})
.attr('x',w-(w/dataset.length))
.attr('y',function(d){return h-yScale(d)+20})
.attr('font-size','12px')
.attr('font-family','san-serif')
.attr('fill','red')
text.transition().duration(1000).attr('x',function(d,i) {return xScale.domain()[i]*(w/dataset.length)+(w/dataset.length)/2})
.attr('y',function(d) {return h-yScale(d)})
.attr('font-size','10px')
.attr('font-family','san-serif')
.attr('fill','red')
text.exit().transition().duration(1000).attr('x',w-(w/dataset.length)/2).remove()
})
字典绑定
这里可能是版本的问题,代码运行还是会存在一些问题:
- 增加值标签不会出现问题,但是在删除值时,标签数据不会同步更新
- 增加再删除,会出现新增加的标签直接偏移到最左边
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3: Adding and removing values from a chart (dynamic labels included)</title>
<script src="d3/d3.min.js"></script>
<style type="text/css">
/* No style rules here yet */
</style>
</head>
<body>
<p id="add">Add a new data value</p>
<p id="remove">Remove a data value</p>
<script type="text/javascript">
//Width and height
var w = 600;
var h = 250;
var dataset = [ { key: 0, value: 5 }, //dataset is now an array of objects.
{ key: 1, value: 10 }, //Each object has a 'key' and a 'value'.
{ key: 2, value: 13 },
{ key: 3, value: 19 },
{ key: 4, value: 21 },
{ key: 5, value: 25 },
{ key: 6, value: 22 },
{ key: 7, value: 18 },
{ key: 8, value: 15 },
{ key: 9, value: 13 },
{ key: 10, value: 11 },
{ key: 11, value: 12 },
{ key: 12, value: 15 },
{ key: 13, value: 20 },
{ key: 14, value: 18 },
{ key: 15, value: 17 },
{ key: 16, value: 16 },
{ key: 17, value: 18 },
{ key: 18, value: 23 },
{ key: 19, value: 25 } ];
var xScale = d3.scaleOrdinal()
.domain(d3.range(dataset.length))
.range([0, w], 0.05);
var yScale = d3.scaleLinear()
.domain([0, d3.max(dataset, function(d) { return d.value; })])
.range([0, h]);
//Define key function, to be used when binding data
var key = function(d) {
return d.key;
};
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Create bars
svg.selectAll("rect")
.data(dataset, key)
.enter()
.append("rect")
.attr("x", function(d, i) {
return xScale.domain()[i]*(w/dataset.length);
})
.attr("y", function(d) {
return h - yScale(d.value);
})
.attr("width", (w/dataset.length)-2)
.attr("height", function(d) {
return yScale(d.value);
})
.attr("fill", function(d) {
return "rgb(0, 0, " + (d.value * 10) + ")";
});
//Create labels
svg.selectAll("text")
.data(dataset, key)
.enter()
.append("text")
.text(function(d) {
return d.value;
})
.attr("text-anchor", "middle")
.attr("x", function(d, i) {
return xScale.domain()[i]*(w/dataset.length)+(w/dataset.length)/2;
})
.attr("y", function(d) {
return h - yScale(d.value) + 14;
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "red");
//On click, update with new data
d3.selectAll("p")
.on("click", function() {
//See which p was clicked
var paragraphID = d3.select(this).attr("id");
//Decide what to do next
if (paragraphID == "add") {
//Add a data value
var maxValue = 25;
var newNumber = Math.floor(Math.random() * maxValue);
var lastKeyValue = dataset[dataset.length - 1].key;
console.log(lastKeyValue);
dataset.push({
key: lastKeyValue + 1,
value: newNumber
});
} else {
//Remove a value
dataset.shift(); //Remove one value from dataset
}
//Update scale domains
xScale.domain(d3.range(dataset.length));
yScale.domain([0, d3.max(dataset, function(d) { return d.value; })]);
//Select…
var bars = svg.selectAll("rect")
.data(dataset, key);
//Enter…
bars.enter()
.append("rect")
.attr("x", w)
.attr("y", function(d) {
return h - yScale(d.value);
})
.attr("width", (w/dataset.length)-2)
.attr("height", function(d) {
return yScale(d.value);
})
.attr("fill", function(d) {
return "rgb(0, 0, " + (d.value * 10) + ")";
});
//Update…
bars.transition()
.duration(500)
.attr("x", function(d, i) {
return xScale.domain()[i]*(w/dataset.length)+(w/dataset.length);
})
.attr("y", function(d) {
return h - yScale(d.value);
})
.attr("width", (w/dataset.length))
.attr("height", function(d) {
return yScale(d.value);
});
//Exit…
bars.exit()
.transition()
.duration(500)
.attr("x", -(w/dataset.length))
.remove();
//Update all labels
//Select…
var labels = svg.selectAll("text")
.data(dataset, key);
//Enter…
<!--labels.enter()-->
<!--.append("text")-->
<!--.text(function(d) {-->
<!--return d.value;-->
<!--})-->
<!--.attr("text-anchor", "middle")-->
<!--.attr("x", w)-->
<!--.attr("y", function(d) {-->
<!--return h - yScale(d.value) + 14;-->
<!--})-->
<!--.attr("font-family", "sans-serif")-->
<!--.attr("font-size", "11px")-->
<!--.attr("fill", "black");-->
<!--//Update…-->
<!--labels.transition()-->
<!--.duration(500)-->
<!--.attr("x", function(d, i) {-->
<!--return xScale.domain()[i]+ (w/dataset.length) / 2;-->
<!--});-->
labels.enter().append('text').text(function(d){return d.value})
.attr('x',w)
.attr('y',function(d){return h-yScale(d.value)+20})
.attr('font-size','12px')
.attr('font-family','san-serif')
.attr('fill','red')
labels.transition().duration(1000).attr('x',function(d,i) {return xScale.domain()[i+1]*(w/dataset.length)+(w/dataset.length)/2})
labels.exit().transition().duration(1000).attr('x',-(w/dataset.length)/2).remove()
<!--//Exit…-->
<!--labels.exit()-->
<!--.transition()-->
<!--.duration(500)-->
<!--.attr("x", -(w/dataset.length))-->
<!--.remove();-->
});
</script>
</body>
</html>
事件监听
- 使用CSS实现悬停高亮
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>时间监听</title>
<script src="d3/d3.min.js"></script>
<style type="text/css">
rect:hover {
fill: orange;
}
</style>
</head>
<body>
<script type="text/javascript">
var w = 1000;
var h = 300;
padding = 10
var dataset = [ { key: 0, value: 5 }, //dataset is now an array of objects.
{ key: 1, value: 10 }, //Each object has a 'key' and a 'value'.
{ key: 2, value: 13 },
{ key: 3, value: 19 },
{ key: 4, value: 21 },
{ key: 5, value: 25 },
{ key: 6, value: 22 },
{ key: 7, value: 18 },
{ key: 8, value: 15 },
{ key: 9, value: 13 },
{ key: 10, value: 11 },
{ key: 11, value: 12 },
{ key: 12, value: 15 },
{ key: 13, value: 20 },
{ key: 14, value: 18 },
{ key: 15, value: 17 },
{ key: 16, value: 16 },
{ key: 17, value: 18 },
{ key: 18, value: 23 },
{ key: 19, value: 25 } ];
var key=function(d){return d.key}
//定义比例尺
var xScale=d3.scaleOrdinal().domain(d3.range(dataset.length))
.range([0,w],0.05)
var yScale=d3.scaleLinear().domain([0,d3.max(dataset,function(d){return d.value})])
.range([0,h])
//生成svg
var svg=d3.select('body').append('svg').attr('width',w).attr('height',h)
//生成柱形图并绑定数据
svg.selectAll('rect').data(dataset,key).enter().append('rect')
.attr('x',function(d,i){return xScale.domain()[i]*(w/dataset.length)})
.attr('y',function(d) {return h-yScale(d.value)})
.attr('width',w/dataset.length-2)
.attr('height',function(d){return yScale(d.value)})
.attr('fill','black')
//生成标签
svg.selectAll('text').data(dataset,key).enter().append('text').text(function(d){return d.value})
.attr('x',function(d,i) {return xScale.domain()[i]*(w/dataset.length)+(w/dataset.length)/2})
.attr('y',function(d) {return h-yScale(d.value)+20})
.attr('font-size','10px')
.attr('font-family','san-serif')
.attr('fill','red')
</script>
</body>
</html>
- 使用d3实现悬停高亮
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>d3悬停</title>
<script src="d3/d3.min.js"></script>
</head>
<body>
<script type="text/javascript">
var w = 1000;
var h = 300;
padding = 10
var dataset = [ { key: 0, value: 5 }, //dataset is now an array of objects.
{ key: 1, value: 10 }, //Each object has a 'key' and a 'value'.
{ key: 2, value: 13 },
{ key: 3, value: 19 },
{ key: 4, value: 21 },
{ key: 5, value: 25 },
{ key: 6, value: 22 },
{ key: 7, value: 18 },
{ key: 8, value: 15 },
{ key: 9, value: 13 },
{ key: 10, value: 11 },
{ key: 11, value: 12 },
{ key: 12, value: 15 },
{ key: 13, value: 20 },
{ key: 14, value: 18 },
{ key: 15, value: 17 },
{ key: 16, value: 16 },
{ key: 17, value: 18 },
{ key: 18, value: 23 },
{ key: 19, value: 25 } ];
var key=function(d){return d.key}
//定义比例尺
var xScale=d3.scaleOrdinal().domain(d3.range(dataset.length))
.range([0,w],0.05)
var yScale=d3.scaleLinear().domain([0,d3.max(dataset,function(d){return d.value})])
.range([0,h])
//生成svg
var svg=d3.select('body').append('svg').attr('width',w).attr('height',h)
//生成柱形图并绑定数据
svg.selectAll('rect').data(dataset,key).enter().append('rect')
.attr('x',function(d,i){return xScale.domain()[i]*(w/dataset.length)})
.attr('y',function(d) {return h-yScale(d.value)})
.attr('width',w/dataset.length-2)
.attr('height',function(d){return yScale(d.value)})
.attr('fill','#81D4FA').on('mouseover',function(){return d3.select(this).attr('fill','#FF9100')})
.on('mouseout',function(d){return d3.select(this).transition().duration(1000).attr('fill','#81D4FA')})
//生成标签
svg.selectAll('text').data(dataset,key).enter().append('text').text(function(d){return d.value})
.attr('x',function(d,i) {return xScale.domain()[i]*(w/dataset.length)+(w/dataset.length)/2})
.attr('y',function(d) {return h-yScale(d.value)+20})
.attr('font-size','10px')
.attr('font-family','san-serif')
.attr('fill','white')
</script>
</body>
</html>
自动排序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>自动排序</title>
<script src="d3/d3.min.js"></script>
</head>
<body>
<script type="text/javascript">
//生成数据
var dataset=[]
var maxvalue=25
for (var i=0;i < maxvalue;i++){
var num=Math.floor(Math.random()*maxvalue)
dataset.push(num)
}
//宽高
var w = 1000;
var h = 300;
var padding = 20;
//生成比例尺
var xScale=d3.scaleOrdinal().domain(d3.range(dataset.length))
.range([0,w],0.05)
var yScale=d3.scaleLinear().domain([0,d3.max(dataset)])
.range([h-padding,padding])
//生成svg
var svg=d3.select('body').append('svg').attr('width',w).attr('height',h)
//生成柱形图并绑定数据
svg.selectAll('rect').data(dataset).enter().append('rect')
.attr('x',function(d,i){return xScale.domain()[i]*(w/dataset.length)})
.attr('y',function(d) {return yScale(d)})
.attr('width',w/dataset.length-2)
.attr('height',function(d){return h-yScale(d)})
.attr('fill','#81D4FA')
.on('mouseover',function(){return d3.select(this).attr('fill','#FF9100')})
.on('mouseout',function(d){return d3.select(this).transition().duration(1000).attr('fill','#81D4FA')})
.on('click',function(){return sortby(),sortbytext()})
//生成标签
svg.selectAll('text').data(dataset).enter().append('text').text(function(d){return d})
.attr('x',function(d,i) {return xScale.domain()[i]*(w/dataset.length)+(w/dataset.length)/2})
.attr('y',function(d) {return yScale(d)+20})
.attr('font-size','10px')
.attr('font-family','san-serif')
.attr('fill','red')
var sortby=function(){
svg.selectAll('rect').sort(function(a,b){return d3.ascending(a,b)}).transition().duration(1000).attr('x',function(d,i){return xScale.domain()[i]*(w/dataset.length)})}
var sortbytext=function(){
svg.selectAll('text').sort(function(a,b){return d3.ascending(a,b)}).transition().duration(1000).attr('x',function(d,i){return xScale.domain()[i]*(w/dataset.length)})}
</script>
</body>
</html>
提示条
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>div提示框</title>
<script src="d3/d3.min.js"></script>
<style type="text/css">
rect:hover {
fill: orange;
}
#tooltip {
position: absolute;
width: 200px;
height: auto;
padding: 10px;
background-color: white;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
-webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
-moz-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
pointer-events: none;
}
#tooltip.hidden {
display: none;
}
#tooltip p {
margin: 0;
font-family: sans-serif;
font-size: 16px;
line-height: 20px;
}
</style>
</head>
<body>
<div id="tooltip" class="hidden">
<p><strong>Important Label Heading</strong></p>
<p><span id="value">100</p>
</div>
<script type="text/javascript">
//生成数据
var dataset=[]
var maxvalue=25
for (var i=0;i < maxvalue;i++){
var num=Math.floor(Math.random()*maxvalue)
dataset.push(num)
}
//宽高
var w = 1000;
var h = 300;
var padding = 20;
//生成比例尺
var xScale=d3.scaleOrdinal().domain(d3.range(dataset.length))
.range([0,w],0.05)
var yScale=d3.scaleLinear().domain([0,d3.max(dataset)])
.range([h-padding,padding])
//生成svg
var svg=d3.select('body').append('svg').attr('width',w).attr('height',h)
//生成柱形图并绑定数据
svg.selectAll('rect').data(dataset).enter().append('rect')
.attr('x',function(d,i){return xScale.domain()[i]*(w/dataset.length)})
.attr('y',function(d) {return yScale(d)})
.attr('width',w/dataset.length-2)
.attr('height',function(d){return h-yScale(d)})
.attr('fill','#81D4FA')
.on('mouseover',function(d){
var xPosition = parseFloat(d3.select(this).attr("x")) + (w/dataset.length) / 2;
var yPosition = parseFloat(d3.select(this).attr("y")) / 2 + h / 2;
//Update the tooltip position and value
d3.select("#tooltip")
.style("left", xPosition + "px")
.style("top", yPosition + "px")
.select("#value")
.text(d);
//Show the tooltip
d3.select("#tooltip").classed("hidden", false);
return d3.select(this).attr('fill','#FF9100')})
.on('mouseout',function(d){
d3.select("#tooltip").classed("hidden", true);
return d3.select(this).transition().duration(1000).attr('fill','#81D4FA')})
.on('click',function(){return sortby(),sortbytext()}).append('title').text(function(d){return d})
//生成标签
svg.selectAll('text').data(dataset).enter().append('text').text(function(d){return d})
.attr('x',function(d,i) {return xScale.domain()[i]*(w/dataset.length)+(w/dataset.length)/2})
.attr('y',function(d) {return yScale(d)+20})
.attr('font-size','10px')
.attr('font-family','san-serif')
.attr('fill','red')
var sortby=function(){
svg.selectAll('rect').sort(function(a,b){return d3.ascending(a,b)}).transition().duration(1000).attr('x',function(d,i){return xScale.domain()[i]*(w/dataset.length)})}
var sortbytext=function(){
svg.selectAll('text').sort(function(a,b){return d3.ascending(a,b)}).transition().duration(1000).attr('x',function(d,i){return xScale.domain()[i]*(w/dataset.length)})}
</script>
</body>
</html>
布局
D3的全部布局方法如下:
- Bundle:把霍尔顿(Holten)的分层捆绑算法应用到连线(edge)上
- Chord: 根据矩阵关系生成弦形图(chord diagram)
- Cluster:聚集实体生成系统树图(dendrogram)
- Force :根据物理模拟链接定位的节点
- Hierarchy :派生自定义的系统(分层的)布局实现
- Histogram:基于量化的分组计算数据分布
- Pack:基于递归圆形填充(circle packing)产生分层布局
- Partition:递归细分节点树,呈射线或冰挂状
- Pie:计算饼图或圆环图中弧形的起止角度
- Stack:计算一系列堆叠的条形或者面积图的基线
- Tree : 整齐的定位树节点
- Treemap:基于递归空间细分来显示节点树
饼图
- 建立pie布局
- 创建svg并传入pie给g元组
- 设置内外圆半径
- 绘制路径
- 绘制文本标签
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3: Pie layout</title>
<script type="text/javascript" src="../d3/d3.v3.js"></script>
<style type="text/css">
text {
font-family: sans-serif;
font-size: 12px;
fill: white;
}
</style>
</head>
<body>
<script type="text/javascript">
//Width and height
var w = 300;
var h = 300;
var dataset = [ 5, 10, 20, 45, 6, 25 ];
var outerRadius = w / 2;
var innerRadius = 0;
var arc = d3.svg.arc()
.innerRadius(innerRadius)
.outerRadius(outerRadius);
var pie = d3.layout.pie();
//Easy colors accessible via a 10-step ordinal scale
var color = d3.scale.category10();
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Set up groups
var arcs = svg.selectAll("g.arc")
.data(pie(dataset))
.enter()
.append("g")
.attr("class", "arc")
.attr("transform", "translate(" + outerRadius + "," + outerRadius + ")");
//Draw arc paths
arcs.append("path")
.attr("fill", function(d, i) {
return color(i);
})
.attr("d", arc);
//Labels
arcs.append("text")
.attr("transform", function(d) {
return "translate(" + arc.centroid(d) + ")";
})
.attr("text-anchor", "middle")
.text(function(d) {
return d.value;
});
</script>
</body>
</html>
堆叠柱状图
- 创建stack布局
- 计算堆叠
- 设置高度与基准值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3: Stack layout stacked bar chart</title>
<script type="text/javascript" src="../d3/d3.v3.js"></script>
<style type="text/css">
/* No style rules here yet */
</style>
</head>
<body>
<script type="text/javascript">
//Width and height
var w = 500;
var h = 300;
//Original data
var dataset = [
[
{ x: 0, y: 5 },
{ x: 1, y: 4 },
{ x: 2, y: 2 },
{ x: 3, y: 7 },
{ x: 4, y: 23 }
],
[
{ x: 0, y: 10 },
{ x: 1, y: 12 },
{ x: 2, y: 19 },
{ x: 3, y: 23 },
{ x: 4, y: 17 }
],
[
{ x: 0, y: 22 },
{ x: 1, y: 28 },
{ x: 2, y: 32 },
{ x: 3, y: 35 },
{ x: 4, y: 43 }
]
];
//Set up stack method
var stack = d3.layout.stack();
//Data, stacked
stack(dataset);
//Set up scales
var xScale = d3.scale.ordinal()
.domain(d3.range(dataset[0].length))
.rangeRoundBands([0, w], 0.05);
var yScale = d3.scale.linear()
.domain([0,
d3.max(dataset, function(d) {
return d3.max(d, function(d) {
return d.y0 + d.y;
});
})
])
.range([0, h]);
//Easy colors accessible via a 10-step ordinal scale
var colors = d3.scale.category10();
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
// Add a group for each row of data
var groups = svg.selectAll("g")
.data(dataset)
.enter()
.append("g")
.style("fill", function(d, i) {
return colors(i);
});
// Add a rect for each data value
var rects = groups.selectAll("rect")
.data(function(d) { return d; })
.enter()
.append("rect")
.attr("x", function(d, i) {
return xScale(i);
})
.attr("y", function(d) {
return yScale(d.y0);
})
.attr("height", function(d) {
return yScale(d.y);
})
.attr("width", xScale.rangeBand());
</script>
</body>
</html>
力图
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3: Force layout</title>
<script type="text/javascript" src="../d3/d3.v3.js"></script>
<style type="text/css">
/* No style rules here yet */
</style>
</head>
<body>
<script type="text/javascript">
//Width and height
var w = 500;
var h = 300;
//Original data
var dataset = {
nodes: [
{ name: "Adam" },
{ name: "Bob" },
{ name: "Carrie" },
{ name: "Donovan" },
{ name: "Edward" },
{ name: "Felicity" },
{ name: "George" },
{ name: "Hannah" },
{ name: "Iris" },
{ name: "Jerry" }
],
edges: [
{ source: 0, target: 1 },
{ source: 0, target: 2 },
{ source: 0, target: 3 },
{ source: 0, target: 4 },
{ source: 1, target: 5 },
{ source: 2, target: 5 },
{ source: 2, target: 5 },
{ source: 3, target: 4 },
{ source: 5, target: 8 },
{ source: 5, target: 9 },
{ source: 6, target: 7 },
{ source: 7, target: 8 },
{ source: 8, target: 9 }
]
};
//Initialize a default force layout, using the nodes and edges in dataset
var force = d3.layout.force()
.nodes(dataset.nodes)
.links(dataset.edges)
.size([w, h])
.linkDistance([50])
.charge([-100])
.start();
var colors = d3.scale.category10();
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Create edges as lines
var edges = svg.selectAll("line")
.data(dataset.edges)
.enter()
.append("line")
.style("stroke", "#ccc")
.style("stroke-width", 1);
//Create nodes as circles
var nodes = svg.selectAll("circle")
.data(dataset.nodes)
.enter()
.append("circle")
.attr("r", 10)
.style("fill", function(d, i) {
return colors(i);
})
.call(force.drag);
//Every time the simulation "ticks", this will be called
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; });
nodes.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
});
</script>
</body>
</html>
地图
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3: Setting path fills dynamically to generate a choropleth</title>
<script type="text/javascript" src="../d3/d3.v3.js"></script>
<style type="text/css">
/* No style rules here yet */
</style>
</head>
<body>
<script type="text/javascript">
//Width and height
var w = 500;
var h = 300;
//Define map projection
var projection = d3.geo.albersUsa()
.translate([w/2, h/2])
.scale([500]);
//Define path generator
var path = d3.geo.path()
.projection(projection);
//Define quantize scale to sort data values into buckets of color
var color = d3.scale.quantize()
.range(["rgb(237,248,233)","rgb(186,228,179)","rgb(116,196,118)","rgb(49,163,84)","rgb(0,109,44)"]);
//Colors taken from colorbrewer.js, included in the D3 download
//Create SVG element
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//Load in agriculture data
d3.csv("us-ag-productivity-2004.csv", function(data) {
//Set input domain for color scale
color.domain([
d3.min(data, function(d) { return d.value; }),
d3.max(data, function(d) { return d.value; })
]);
//Load in GeoJSON data
d3.json("us-states.json", function(json) {
//Merge the ag. data and GeoJSON
//Loop through once for each ag. data value
for (var i = 0; i < data.length; i++) {
//Grab state name
var dataState = data[i].state;
//Grab data value, and convert from string to float
var dataValue = parseFloat(data[i].value);
//Find the corresponding state inside the GeoJSON
for (var j = 0; j < json.features.length; j++) {
var jsonState = json.features[j].properties.name;
if (dataState == jsonState) {
//Copy the data value into the JSON
json.features[j].properties.value = dataValue;
//Stop looking through the JSON
break;
}
}
}
//Bind data and create one path per GeoJSON feature
svg.selectAll("path")
.data(json.features)
.enter()
.append("path")
.attr("d", path)
.style("fill", function(d) {
//Get data value
var value = d.properties.value;
if (value) {
//If value exists…
return color(value);
} else {
//If value is undefined…
return "#ccc";
}
});
});
});
</script>
</body>
</html>
$
\frac{\partial C}{\partial \theta}
&=&
\frac{1}{m} \sum_{i=1}^m
\left[ \sigma\left(\theta^{\rm T} x^{(i)} \right) - y^{(i)} \right]
x^{(i)}\\
&=&
\frac{1}{m}
X^{\rm T}
\left[ \sigma\left(X \theta \right) - y \right]
$