D3.js
<script src="https://d3js.org/d3.v6.min.js"></script>
import * as d3 from "d3";//将内容导入到命名空间
const d3 = require("d3");//在节点中
1.svg
一种文本格式
给svg元素指定width和height值
<svg width="500" height="50"></svg>
rect用于绘制矩形
circle用于绘制圆形
ellipse每个轴要分别指定半径
line用于绘制直线
text用于绘制文本(x用于指定文本左上角的位置,y用于指定字体的基线位置)
svg属性
fill颜色 stroke颜色值 stroke-width带单位的数值 opacity设置透明度
文本font-family font-size
分层与绘制顺序–代码中元素出现的顺序决定了它们的深度次序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Page Template</title>
<script type="text/javascript" src="d3/d3.v3.js"></script>
</head>
<body>
<script type="text/javascript">
// 创建新的元素
// d3.select("body").append("p").text("New paragraph!");
//绑定数据selection.data()
//1.加载csv数据
// d3.csv("1.csv",function(data){
// console.log(data);
// });
// var dataset; // 全局变量
// d3.csv("1.csv", function(data) {
// dataset = data; // 加载完毕,就将其复制到 dataset.
// generateVis(); // 再调用其他依赖数据
// hideLoadingMsg(); // 显示图形的函数
// });
// d3.json("1.json",function(json){
// console.log(json);
// });
var dataset=[5,10,15,20,25];
d3.select("body").selectAll("p")
.data(dataset)//解析并数出数据值,因为数组中有5个值,因而此后的所有方法都将执行五遍,每次针对一个值
.enter()//创建新的绑定元素
.append("p")
// .text("New paragraph!");
//使用绑定到了DOM中新创建的元素
.text(function(d){return d;})
//D3绑定的数据没有出现在DOM中,而是作为元素的__data__属性保存在内存中
//添加样式
// .style("color","red");
.style("color",function(d){
if(d>15){
return "red";
}else{
return "black";
}
});
</script>
</body>
</html>
2.设定样式style(),设定属性attr()
<style>
div.bar{
display:inline-block;
width:20px;
height:75px;
background-color: teal;
margin-right: 2px;
}
</style>
</head>
<body>
<div></div>
<script type="text/javascript">
var dataset=[];
for(var i=0;i<25;i++){
var newNumber=Math.random()*30;
dataset.push(newNumber);//把新数值添加到数组中
}
d3.select("body").selectAll("div")
.data(dataset)
.enter()
.append("div")
//attr()设定属性,class,id,src,width,alt
.attr("class","bar")
.style("height",function(d){
var barHeight=d*5;
return barHeight+"px";
});
</script>
</body>
3.绘制svg元素
<body>
<script type="text/javascript">
var svg=d3.select("body")
.append("svg")
.attr("width",500)
.attr("height",50);
var dataset=[5,10,15,20,25];
var circles=svg.selectAll("circle")
.data(dataset)//把数据绑定到即将创建的元素
.enter()//返回对这个新元素的占位引用
.append("circle");
circles.attr("cx",function(d,i){//i当前元素的索引值
return (i*50)+25;
})
.attr("cy",h/2)
.attr("r",function(d){
return d;
})
.attr("fill","yellow")
.attr("stroke","orange")
.attr("stroke-width",function(d){
return d/2;
});
</script>
</body>
4.绘制条形图
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Page Template</title>
<script type="text/javascript" src="d3/d3.v3.js"></script>
<style>
</style>
</head>
<body>
<p>Click on this text to update the chart with new data values (once).</p>
</body>
</html>
<script type="text/javascript">
var dataset=[ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13,11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ];
var w=600;
var h=300;
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//设置序数比例尺
var xScale = d3.scale.ordinal()
.domain(d3.range(dataset.length))//设置了输入值的值域
//.rangeBands()根据输入值域的长度自动将其切成相等的块或档,第二个参数设置档间距
//.rangeRoundBands()输出的值会舍入为最接近的整数
.rangeRoundBands([0, w], 0.05);
var yScale = d3.scale.ordinal()
.domain(d3.range(30))//设置了输入值的值域
//.rangeBands()根据输入值域的长度自动将其切成相等的块或档,第二个参数设置档间距
//.rangeRoundBands()输出的值会舍入为最接近的整数
.rangeRoundBands([0, h],0.05);
//添加矩形,条形图
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x",function(d,i){return xScale(i);})
.attr("y", function(d){return h-yScale(d);})//让条形从下向上
.attr("width",xScale.rangeBand())
.attr("height", function(d){return yScale(d);})
.attr("fill",function(d){return "rgb(0,0,"+(d*10)+")";});
//加标签
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function(d){return d;})
.attr("x",function(d,i){return xScale(i) + xScale.rangeBand() / 2;})
.attr("y",function(d){ return h-yScale(d)+14;})
.attr("font-family","sans-serif")
.attr("font-size","11px")
.attr("fill","white")
.attr("text-anchor","middle")//text-anchor水平居中文本
d3.select("p")
.on("click",function(){
//从数据集中删除第一个元素
// dataset.shift();
//新数据集
var numValues = dataset.length; // 取得原数据集的长度
dataset = []; // 初始化空数组
for (var i = 0; i < numValues; i++) {
var newNumber = Math.floor(Math.random() * 25); // 生成新随机数(0~24)
dataset.push(newNumber); // 把新数值添加到数组
}
yScale.domain(d3.range(30));//更新比例尺的值域
//更新所有矩形
var bars=svg.selectAll("rect")
.data(dataset)
.transition()//动态动画
.duration(1000)//参数的单位是持续1毫秒
.attr("y", function(d) {return h - yScale(d);})
.attr("height", function(d) {return yScale(d);});
svg.selectAll("text")
.data(dataset)
.transition()
//设置静态延迟时间
// .delay(1000)//延迟时间
//设置动态延迟时间
.delay(function(d,i){
return i/dataset.length*1000;//确保数据在很多时总的过渡时间是可以接收的
})
.duration(500)
//默认缓动效果是cublic-in-out逐渐加速然后逐渐减速
// .ease("linear")//线性缓动,没有逐渐加速和减速的变化
// .ease("circle")//逐渐加速进入并加速,然后突然停止
// .ease("elastic")//有弹性
.ease("bounce")//像皮球落地一样反复弹跳,慢慢停下来
.text(function(d) {
return d;
})
.attr("x", function(d, i) {
return xScale(i) + xScale.rangeBand() / 2;
})
.attr("y", function(d) {
return h - yScale(d) + 14;
});
//退出
// bars.exit()
// .transition(1000)
// .attr("x",w)
// .remove();
// svg.selectAll("text")
// .data(dataset,key)
// .exit()
// .transition()
// .duration(500)
// .attr("x",w)
});
</script>
5.绘制散点图
<script type="text/javascript">
var dataset = [[5, 20], [480, 90], [250, 50], [100, 33], [330, 95],[410, 12], [475, 44], [25, 67], [85, 21], [220, 88]];
//创建svg元素
var w=1000;
var h=1000;
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
var circles=svg.selectAll("circle") // <-- 不是 "rect" 了
.data(dataset)
.enter()
.append("circle") // <-- 不是 "rect" 了
circles.attr("cx",function(d){
return d[0];
})
.attr("cy",function(d){
return d[1];
})
.attr("r",function(d){
return Math.sqrt(d[1]);//下方的圆形大
// return Math.sqrt(h-d[1]);//上方的圆形大
});
var texts=svg.selectAll("text") // <-- 注意是 "text",而非 "circle" 或 "rect"
.data(dataset)
.enter()
.append("text")
//text()方法设定了每个元素的内容
.text(function(d) {
return d[0] + "," + d[1];
})
//为文本设置样式
.attr("x", function(d) {
return d[0];
})
.attr("y", function(d) {
return d[1];
})
.attr("font-family", "sans-serif")
.attr("font-size", "11px")
.attr("fill", "red");
</script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Page Template</title>
<script type="text/javascript" src="d3/d3.v3.js"></script>
<style>
/* 数轴本身由path,line和text组成 */
/* css给svg元素应用样式时,只能使用svg的属性名,不能使用常规的CSS属性 */
.axis path,
.axis line{
fill:none;
stroke:black;
shape-rendering:crispEdges;
/* shape-rendering保证数轴和刻度线精确到像素级 */
}
.axis text{
font-family: sans-serif;
font-size: 11px;
}
</style>
</head>
<body>
<P>点击我试试更换数据吧</P>
<!-- 剪切路径,本身不可见,但可以包含可见的元素 -->
<!-- 在clipPath中放一个可见的元素 -->
<clipPath id="chart-area">
<rect x="30" y="30" width="410" height="240"></rect>
</clipPath>
</body>
</html>
<script type="text/javascript">
var h=500;
var w=500;
var dataset = [];
var numDataPoints = 50;
var xRange = Math.random() * 1000;
var yRange = Math.random() * 1000;
for (var i = 0; i < numDataPoints; i++) {
var newNumber1 = Math.floor(Math.random() * xRange);
var newNumber2 = Math.floor(Math.random() * yRange);
dataset.push([newNumber1, newNumber2]);
}
var padding=30;//边距向量
var svg=d3.select("body")
.append("svg")
.attr("width",h)
.attr("height",w);
//创建比例尺
var xScale=d3.scale.linear()
.domain([0,d3.max(dataset,function(d){return d[0];})])//设置比例尺的值域
.range([padding,w-padding*2]);//设置输出范围
//边距可以把圆形向里推,使它们远离svg的四边,从而避免被切掉
var yScale=d3.scale.linear()
.domain([0,d3.max(dataset,function(d){return d[1];})])//设置比例尺的值域
// .range([0,h]);//设置输出范围,较小的y值在图表上方
.range([h-padding,padding]);
var rScale=d3.scale.linear()
.domain([0,d3.max(dataset,function(d){return d[1];})])
.range([2,5]);
//d3.max()会循环数组中的每一个x值,返回其中最大的那个
//设定数轴
var xAxis=d3.svg.axis()
.scale(xScale)
.orient("bottom")//设定标签相对于数轴显示在什么地方
.ticks(5);//粗略设置刻度线的数量
// 定义 y 轴
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.ticks(5);
//定义剪切路径,添加蒙版
svg.append("clipPath")//创建新的clipPath元素
.attr("id","chart-area")//指定ID
.append("rect")//在clipPath中创建并添加新的rect
.attr("x",padding)//设置rect的位置和大小
.attr("y",padding)
.attr("width",w-padding*3)
.attr("height",h-padding*2)
var circles=svg.append("g") // 创建新的 g 元素
.attr("id", "circles") // 指定它的 ID 为 circles
.attr("clip-path", "url(#chart-area)") // 添加对 clipPath 的引用
.selectAll("circle") // 剩下的代码跟以前一样……
.data(dataset)
.enter()
.append("circle")
//所有的圆形都被组织到一个g元素中,这个g元素的clip-path属性指向了新创建的剪切路径
circles.attr("cx",function(d){
return xScale(d[0]);
})
.attr("cy",function(d){
return yScale(d[1]);
})
// .attr("r",function(d){
// return Math.sqrt(d[1]);//下方的圆形大
// // return Math.sqrt(h-d[1]);//上方的圆形大
// });
.attr("r",function(d){
return rScale(d[1]);
});
var texts=svg.selectAll("text") // <-- 注意是 "text",而非 "circle" 或 "rect"
.data(dataset)
.enter()
.append("text")
//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");
//添加x轴数轴
//调用数轴函数
svg.append("g")//g是一个分组元素,是不可见的,1.可以用来包含其他元素 2.可以对整个分组应用变换
.attr("class","x axis")
.attr("transform","translate(0,"+(h-padding)+")")//将整个数轴分组平移到图表下方;translate(x,y)平移函数
.call(xAxis);//call()函数会取得传递过来的元素;把g交给了xAxis函数,在g里面生成数轴
//将剪切路径应用到圆形
//添加y轴数轴
svg.append("g")
.attr("class", "y axis")
.attr("transform", "translate(" + padding + ",0)")
.call(yAxis);
d3.select("p")
.on("click",function(){
//更新x上的比例尺
var xScale=d3.scale.linear()
.domain([0,d3.max(dataset,function(d) {return d[0]; })])
.range([padding,w-padding*2]);
//更新y上的比例尺
var yScale=d3.scale.linear()
.domain([0,d3.max(dataset,function(d) {return d[1]; })])
.range([h-padding,padding])
//更新r的比例尺
var rScale=d3.scale.linear()
.domain([0,d3.max(dataset,function(d){ return d[1]; })])
.range([2,5]);
//定义x轴数轴 一定要重新定义一次在更新,否则数轴更新无效
var xaxis=d3.svg.axis()
.scale(xScale)
.orient("bottom")//设定标签相对于数轴显示在什么地方
.ticks(5);//粗略设置刻度线的数量
var yaxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.ticks(5);
//更换x轴数据
svg.select(".x.axis")
.transition()
.duration(1000)
.call(xaxis);
// 更新 y 轴
svg.select(".y.axis")
.transition()
.duration(1000)
.call(yaxis);
//方法一
// svg.selectAll("circle")
// .data(dataset)
// .transition()
// .duration(1000)
// .each("start", function() { // <-- 在过渡开始时执行
// d3.select(this)
// .attr("fill", "magenta")
// .attr("r", 3);
// })
// //each(start)里面执行立即变换,而不能再添加任何过渡效果
// .attr("cx", function(d) {
// return xScale(d[0]);
// })
// .attr("cy", function(d) {
// return yScale(d[1]);
// })
// .each("end", function() { // <-- 在过渡结束时执行
// d3.select(this)
// .transition()
// .duration(1000)
// .attr("fill", "black")
// .attr("r", 2);
// })
// //each(end)支持过渡
// });
//方法二
svg.selectAll("circle")
.data(dataset)
.transition() // <-- #1 过渡
.duration(1000)
.each("start", function() {
d3.select(this)
.attr("fill", "magenta")
.attr("r", 7);
})
.attr("cx", function(d) {
return xScale(d[0]);
})
.attr("cy", function(d) {
return yScale(d[1]);
})
.transition() // <-- #2 过渡
.duration(1000)
.attr("fill", "black")
.attr("r", 2);
})
</script>
6.比例尺d3.scale.linear()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Page Template</title>
<script type="text/javascript" src="d3/d3.v3.js"></script>
<style>
/* 数轴本身由path,line和text组成 */
/* css给svg元素应用样式时,只能使用svg的属性名,不能使用常规的CSS属性 */
.axis path,
.axis line{
fill:none;
stroke:black;
shape-rendering:crispEdges;
/* shape-rendering保证数轴和刻度线精确到像素级 */
}
.axis text{
font-family: sans-serif;
font-size: 11px;
}
</style>
</head>
<body>
</body>
</html>
<script type="text/javascript">
var h=500;
var w=500;
var dataset = [];
var numDataPoints = 50;
var xRange = Math.random() * 1000;
var yRange = Math.random() * 1000;
for (var i = 0; i < numDataPoints; i++) {
var newNumber1 = Math.floor(Math.random() * xRange);
var newNumber2 = Math.floor(Math.random() * yRange);
dataset.push([newNumber1, newNumber2]);
}
var padding=30;//边距向量
var svg=d3.select("body")
.append("svg")
.attr("width",w)
.attr("height",h);
//创建比例尺
var xScale=d3.scale.linear()
.domain([0,d3.max(dataset,function(d){return d[0];})])//设置比例尺的值域
.range([padding,w-padding*2]);//设置输出范围
//边距可以把圆形向里推,使它们远离svg的四边,从而避免被切掉
var yScale=d3.scale.linear()
.domain([0,d3.max(dataset,function(d){return d[1];})])//设置比例尺的值域
// .range([0,h]);//设置输出范围,较小的y值在图表上方
.range([h-padding,padding]);
var rScale=d3.scale.linear()
.domain([0,d3.max(dataset,function(d){return d[1];})])
.range([2,5]);
//d3.max()会循环数组中的每一个x值,返回其中最大的那个
//设定数轴
var xAxis=d3.svg.axis()
.scale(xScale)
.orient("bottom")//设定标签相对于数轴显示在什么地方
.ticks(5);//粗略设置刻度线的数量
// 定义 y 轴
var yAxis = d3.svg.axis()
.scale(yScale)
.orient("left")
.ticks(5);
svg.append("g")
.attr("class", "axis")
.attr("transform", "translate(" + padding + ",0)")
.call(yAxis);
//调用数轴函数
svg.append("g")//g是一个分组元素,是不可见的,1.可以用来包含其他元素 2.可以对整个分组应用变换
.attr("class","axis")
.attr("transform","translate(0,"+(h-padding)+")")//将整个数轴分组平移到图表下方;translate(x,y)平移函数
.call(xAxis);//call()函数会取得传递过来的元素;把g交给了xAxis函数,在g里面生成数轴
var circles=svg.selectAll("circle") // <-- 不是 "rect" 了
.data(dataset)
.enter()
.append("circle") // <-- 不是 "rect" 了
circles.attr("cx",function(d){
return xScale(d[0]);
})
.attr("cy",function(d){
return yScale(d[1]);
})
// .attr("r",function(d){
// return Math.sqrt(d[1]);//下方的圆形大
// // return Math.sqrt(h-d[1]);//上方的圆形大
// });
.attr("r",function(d){
return rScale(d[1]);
});
var texts=svg.selectAll("text") // <-- 注意是 "text",而非 "circle" 或 "rect"
.data(dataset)
.enter()
.append("text")
//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");
</script>
nice()告诉比例尺取得为range()设置的任何值域
rangeRound()则比例尺输出的所有值都会舍入到最接近的整数值。
clamp()线性比例尺可以返回指定范围之外的值
7.添加值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Page Template</title>
<script type="text/javascript" src="d3/d3.v3.js"></script>
<style>
</style>
</head>
<body>
<p>Click on this text to update the chart with new data values (once).</p>
</body>
</html>
<script type="text/javascript">
var dataset=[ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13,11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ];
var w=600;
var h=300;
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//设置序数比例尺
var xScale = d3.scale.ordinal()
.domain(d3.range(dataset.length))//设置了输入值的值域
//.rangeBands()根据输入值域的长度自动将其切成相等的块或档,第二个参数设置档间距
//.rangeRoundBands()输出的值会舍入为最接近的整数
.rangeRoundBands([0, w], 0.05);
var yScale = d3.scale.ordinal()
.domain(d3.range(30))//设置了输入值的值域
//.rangeBands()根据输入值域的长度自动将其切成相等的块或档,第二个参数设置档间距
//.rangeRoundBands()输出的值会舍入为最接近的整数
.rangeRoundBands([0, h],0.05);
//添加矩形,条形图
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x",function(d,i){return xScale(i);})
.attr("y", function(d){return h-yScale(d);})//让条形从下向上
.attr("width",xScale.rangeBand())
.attr("height", function(d){return yScale(d);})
.attr("fill",function(d){return "rgb(0,0,"+(d*10)+")";});
//加标签
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function(d){return d;})
.attr("x",function(d,i){return xScale(i) + xScale.rangeBand() / 2;})
.attr("y",function(d){ return h-yScale(d)+14;})
.attr("font-family","sans-serif")
.attr("font-size","11px")
.attr("fill","white")
.attr("text-anchor","middle")//text-anchor水平居中文本
d3.select("p")
.on("click",function(){
//向数据集中添加一个新值
var maxValue=25;
var newNumber = Math.floor(Math.random()*maxValue); // 生成新随机数(0~24)
dataset.push(newNumber); // 把新数值添加到数组
xScale.domain(d3.range(dataset.length));//更新比例尺的值域
//1.选择,bars就保存了新的数据集
var bars=svg.selectAll("rect")
.data(dataset)
//2.加入
bars.enter()
.append("rect")
.attr("x", w)
.attr("y", function(d) {
return h - yScale(d);
})
.attr("width", xScale.rangeBand())
.attr("height", function(d) {
return yScale(d);
})
.attr("fill", function(d) {
return "rgb(0, 0, " + (d * 10) + ")";
});
//3.更新
bars.transition()
.duration(500)
.attr("x", function(d, i) {
return xScale(i);
})
.attr("y", function(d) {
return h - yScale(d);
})
.attr("width", xScale.rangeBand())
.attr("height", function(d) {
return yScale(d);
});
texts=svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function(d){return d;})
texts.transition()
//设置静态延迟时间
// .delay(1000)//延迟时间
//设置动态延迟时间
.delay(function(d,i){
return i/dataset.length*1000;//确保数据在很多时总的过渡时间是可以接收的
})
.duration(500)
.ease("bounce")//像皮球落地一样反复弹跳,慢慢停下来
.text(function(d) {
return d;
})
.attr("x", function(d, i) {
return xScale(i) + xScale.rangeBand() / 2;
})
.attr("y", function(d) {
return h - yScale(d) + 14;
})
.attr("font-family","sans-serif")
.attr("font-size","11px")
.attr("fill","white")
.attr("text-anchor","middle");//text-anchor水平居中文本
//退出
// bars.exit()
// .transition(1000)
// .attr("x",w)
// .remove();
// svg.selectAll("text")
// .data(dataset,key)
// .exit()
// .transition()
// .duration(500)
// .attr("x",w)
});
</script>
8.删除值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Page Template</title>
<script type="text/javascript" src="d3/d3.v3.js"></script>
<style>
</style>
</head>
<body>
<p>Click on this text</p>
</body>
</html>
<script type="text/javascript">
var dataset = [ { key: 0, value: 5 },
{ key: 1, value: 10 },
{ 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 w=600;
var h=300;
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//设置序数比例尺
var xScale = d3.scale.ordinal()
.domain(d3.range(dataset.length))//设置了输入值的值域
//.rangeBands()根据输入值域的长度自动将其切成相等的块或档,第二个参数设置档间距
//.rangeRoundBands()输出的值会舍入为最接近的整数
.rangeRoundBands([0, w], 0.05);
var yScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) { return d.value; })])
.range([0, h]);
//定义键函数,以备把数据绑定到元素时使用
var key=function(d){
return d.key
}
//添加矩形,条形图
svg.selectAll("rect")
.data(dataset,key)
.enter()
.append("rect")
.attr("x",function(d,i){return xScale(i);})
.attr("y", function(d){return h-yScale(d.value);})//让条形从下向上
.attr("width",xScale.rangeBand())
.attr("height", function(d){return yScale(d.value);})
.attr("fill",function(d){return "rgb(0,0,"+(d.value*10)+")";});
//加标签
svg.selectAll("text")
.data(dataset,key)
.enter()
.append("text")
.text(function(d){return d.value;})
.attr("x",function(d,i){return xScale(i) + xScale.rangeBand() / 2;})
.attr("y",function(d){ return h-yScale(d.value)+14;})
.attr("font-family","sans-serif")
.attr("font-size","11px")
.attr("fill","white")
.attr("text-anchor","middle")//text-anchor水平居中文本
d3.select("p")
.on("click",function(){
//从数据集中删除第一个元素
dataset.shift();
//更新所有矩形
var bars=svg.selectAll("rect")
.data(dataset,key)
//退出
bars.exit()
.transition(1000)
.attr("x",w)
.remove();
svg.selectAll("text")
.data(dataset,key)
.exit()
.transition()
.duration(500)
.attr("x",w)
});
</script>
9.添加和删除
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Page Template</title>
<script type="text/javascript" src="d3/d3.v3.js"></script>
<style>
</style>
</head>
<body>
<p id="add">Add a new data a value</p>
<p id="remove">Remove a data value</p>
</body>
</html>
<script type="text/javascript">
var dataset=[ { key: 0, value: 5 },
{ key: 1, value: 10 },
{ 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 w=600;
var h=300;
var key=function(d){return d.key};
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//设置序数比例尺
var xScale = d3.scale.ordinal()
.domain(d3.range(dataset.length))//设置了输入值的值域
//.rangeBands()根据输入值域的长度自动将其切成相等的块或档,第二个参数设置档间距
//.rangeRoundBands()输出的值会舍入为最接近的整数
.rangeRoundBands([0, w], 0.05);
var yScale = d3.scale.ordinal()
.domain(d3.range(30))//设置了输入值的值域
//.rangeBands()根据输入值域的长度自动将其切成相等的块或档,第二个参数设置档间距
//.rangeRoundBands()输出的值会舍入为最接近的整数
.rangeRoundBands([0, h],0.05);
//添加矩形,条形图
svg.selectAll("rect")
.data(dataset,key)
.enter()
.append("rect")
.attr("x",function(d,i){return xScale(i);})
.attr("y", function(d){return h-yScale(d.value);})//让条形从下向上
.attr("width",xScale.rangeBand())
.attr("height", function(d){return yScale(d.value);})
.attr("fill",function(d){return "rgb(0,0,"+(d.value*10)+")";});
d3.selectAll("p")
.on("click",function(){
// 看看单击了哪个段落
var paragraphID = d3.select(this).attr("id");
// 确定接下来该干什么
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 {
// 删除一个值
dataset.shift();
}
xScale.domain(d3.range(dataset.length));//更新比例尺的值域
//1.选择,bars就保存了新的数据集
var bars=svg.selectAll("rect")
.data(dataset,key)
//2.加入
bars.enter()
.append("rect")
.attr("x", w)
.attr("y", function(d) {
return h - yScale(d.value);
})
.attr("width", xScale.rangeBand())
.attr("height", function(d) {
return yScale(d.value);
})
.attr("fill", function(d) {
return "rgb(0, 0, " + (d.value * 10) + ")";
});
//3.更新
bars.transition()
.duration(500)
.attr("x", function(d, i) {
return xScale(i);
})
.attr("y", function(d) {
return h - yScale(d.value);
})
.attr("width", xScale.rangeBand())
.attr("height", function(d) {
return yScale(d.value);
});
//退出
bars.exit()
.transition(1000)
.attr("x",w)
.remove();
});
</script>
10.悬停高亮
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Page Template</title>
<script type="text/javascript" src="d3/d3.v3.js"></script>
<style>
</style>
</head>
<body>
<p id="add">Add a new data a value</p>
<p id="remove">Remove a data value</p>
</body>
</html>
<script type="text/javascript">
var dataset=[ { key: 0, value: 5 },
{ key: 1, value: 10 },
{ 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 w=600;
var h=300;
var key=function(d){return d.key};
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//设置序数比例尺
var xScale = d3.scale.ordinal()
.domain(d3.range(dataset.length))//设置了输入值的值域
//.rangeBands()根据输入值域的长度自动将其切成相等的块或档,第二个参数设置档间距
//.rangeRoundBands()输出的值会舍入为最接近的整数
.rangeRoundBands([0, w], 0.05);
var yScale = d3.scale.ordinal()
.domain(d3.range(30))//设置了输入值的值域
//.rangeBands()根据输入值域的长度自动将其切成相等的块或档,第二个参数设置档间距
//.rangeRoundBands()输出的值会舍入为最接近的整数
.rangeRoundBands([0, h],0.05);
//添加矩形,条形图
svg.selectAll("rect")
.data(dataset,key)
.enter()
.append("rect")
.attr("x",function(d,i){return xScale(i);})
.attr("y", function(d){return h-yScale(d.value);})//让条形从下向上
.attr("width",xScale.rangeBand())
.attr("height", function(d){return yScale(d.value);})
.attr("fill",function(d){return "rgb(0,0,"+(d.value*10)+")";})
.on("mouseover",function(){
d3.select(this)
.attr("fill","orange");
})
.on("mouseout",function(d){
d3.select(this)
.transition()
.duration(250)
.attr("fill","rgb(0,0,"+(d.value*10)+")");
});
//指针事件和重叠元素,在svg中,后加入DOM元素在视觉层次上会被渲染在先加入元素的前面
//希望在某些元素上忽略鼠标事件,在css中给要忽略的元素添加一行代码即可
//pointer-events:none;
</script>
11.分组SVG 元素
g元素自身不会触发任何鼠标事件(g没有像素),被它封装的元素,比如rect,circle和text元素才有像素
可以把事件监听器绑定给g元素,因为要是被包含的元素中有哪个被单击了或被鼠标悬停了,那么绑定到g元素的事件监听器也会被触发
12.点击排序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Page Template</title>
<script type="text/javascript" src="d3/d3.v3.js"></script>
<style>
</style>
</head>
<body>
<p>Click on this text to update the chart with new data values (once).</p>
</body>
</html>
<script type="text/javascript">
var dataset=[ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13,11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ];
var w=600;
var h=300;
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//设置序数比例尺
var xScale = d3.scale.ordinal()
.domain(d3.range(dataset.length))//设置了输入值的值域
//.rangeBands()根据输入值域的长度自动将其切成相等的块或档,第二个参数设置档间距
//.rangeRoundBands()输出的值会舍入为最接近的整数
.rangeRoundBands([0, w], 0.05);
var yScale = d3.scale.ordinal()
.domain(d3.range(30))//设置了输入值的值域
//.rangeBands()根据输入值域的长度自动将其切成相等的块或档,第二个参数设置档间距
//.rangeRoundBands()输出的值会舍入为最接近的整数
.rangeRoundBands([0, h],0.05);
//添加矩形,条形图
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x",function(d,i){return xScale(i);})
.attr("y", function(d){return h-yScale(d);})//让条形从下向上
.attr("width",xScale.rangeBand())
.attr("height", function(d){return yScale(d);})
.attr("fill",function(d){return "rgb(0,0,"+(d*10)+")";})
.on("click", function() {
sortBars();
});
//加标签
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function(d){return d;})
.attr("x",function(d,i){return xScale(i) + xScale.rangeBand() / 2;})
.attr("y",function(d){ return h-yScale(d)+14;})
.attr("font-family","sans-serif")
.attr("font-size","11px")
.attr("fill","white")
.attr("text-anchor","middle")//text-anchor水平居中文本
//点击排序函数
var sortOrder=false;
var sortBars = function() {
// 反转 sortOrder 的值
sortOrder = !sortOrder;
svg.selectAll("rect")
.sort(function(a, b) {
if (sortOrder) {
return d3.ascending(a, b);
} else {
return d3.descending(a, b);
}
})
.transition()
.delay(function(d, i) {
return i * 50;
})
.duration(1000)
.attr("x", function(d, i) {
return xScale(i);
});
};
</script>
13.SVG元素提示条
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Page Template</title>
<script type="text/javascript" src="d3/d3.v3.js"></script>
<style>
</style>
</head>
<body>
<p>Click on this text to update the chart with new data values (once).</p>
</body>
</html>
<script type="text/javascript">
var dataset=[ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13,11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ];
var w=600;
var h=300;
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//设置序数比例尺
var xScale = d3.scale.ordinal()
.domain(d3.range(dataset.length))//设置了输入值的值域
//.rangeBands()根据输入值域的长度自动将其切成相等的块或档,第二个参数设置档间距
//.rangeRoundBands()输出的值会舍入为最接近的整数
.rangeRoundBands([0, w], 0.05);
var yScale = d3.scale.ordinal()
.domain(d3.range(30))//设置了输入值的值域
//.rangeBands()根据输入值域的长度自动将其切成相等的块或档,第二个参数设置档间距
//.rangeRoundBands()输出的值会舍入为最接近的整数
.rangeRoundBands([0, h],0.05);
//添加矩形,条形图
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x",function(d,i){return xScale(i);})
.attr("y", function(d){return h-yScale(d);})//让条形从下向上
.attr("width",xScale.rangeBand())
.attr("height", function(d){return yScale(d);})
.attr("fill",function(d){return "rgb(0,0,"+(d*10)+")";})
// .append("title")
// .text(function(d){
// return d;
// });
.on("mouseover",function(d){
//取得条形的x/y值。增大后作为提示条的坐标
var xPosition=parseFloat(d3.select(this).attr("x"))+xScale.rangeBand()/2;
var yPosition=parseFloat(d3.select(this).attr("y"))+14;
//创建提示条
svg.append("text")
.attr("id","tooltip")
.attr("x",xPosition)
.attr("y",yPosition)
.attr("text-anchor","middle")
.attr("font-family","sans-serif")
.attr("font-size","11px")
.attr("font-weight","bold")
.attr("fill","black")
.text(d);
})
.on("mouseout",function(){
//删除提示条
d3.select("#tooltip").remove();HTML
})
</script>
14.HTML的div提示条
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Page Template</title>
<script type="text/javascript" src="d3/d3.v3.js"></script>
<style>
#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</span>%</p>
</div>
</body>
</html>
<script type="text/javascript">
var dataset=[ 5, 10, 13, 19, 21, 25, 22, 18, 15, 13,11, 12, 15, 20, 18, 17, 16, 18, 23, 25 ];
var w=600;
var h=300;
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
//设置序数比例尺
var xScale = d3.scale.ordinal()
.domain(d3.range(dataset.length))//设置了输入值的值域
//.rangeBands()根据输入值域的长度自动将其切成相等的块或档,第二个参数设置档间距
//.rangeRoundBands()输出的值会舍入为最接近的整数
.rangeRoundBands([0, w], 0.05);
var yScale = d3.scale.ordinal()
.domain(d3.range(30))//设置了输入值的值域
//.rangeBands()根据输入值域的长度自动将其切成相等的块或档,第二个参数设置档间距
//.rangeRoundBands()输出的值会舍入为最接近的整数
.rangeRoundBands([0, h],0.05);
//添加矩形,条形图
svg.selectAll("rect")
.data(dataset)
.enter()
.append("rect")
.attr("x",function(d,i){return xScale(i);})
.attr("y", function(d){return h-yScale(d);})//让条形从下向上
.attr("width",xScale.rangeBand())
.attr("height", function(d){return yScale(d);})
.attr("fill",function(d){return "rgb(0,0,"+(d*10)+")";})
.on("mouseover", function(d) {
// 取得条形的 x/y 值,增大后作为提示条的坐标
var xPosition = parseFloat(d3.select(this).attr("x")) + xScale.rangeBand() / 2;
var yPosition = parseFloat(d3.select(this).attr("y")) / 2 + h / 2;
// 更新提示条的位置和值
d3.select("#tooltip")
.style("left", xPosition + "px")
.style("top", yPosition + "px")
.select("#value")
.text(d);
// 显示提示条
d3.select("#tooltip").classed("hidden", false);
})
.on("mouseout",function(){
//隐藏提示条
d3.select("#tooltip").classed("hidden",true);
})
</script>
15.力导向图
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>D3 Page Template</title>
<script type="text/javascript" src="d3/d3.v3.js"></script>
<style>
</style>
</head>
<body>
</body>
</html>
<script type="text/javascript">
var w=600;
var h=300;
var svg = d3.select("body")
.append("svg")
.attr("width", w)
.attr("height", h);
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 }
]
};
//初始化力导向图
var force=d3.layout.force()
.nodes(dataset.nodes)
.links(dataset.edges)
.size([w,h])
.linkDistance(150)//连接节点的连线长度
.charge([-400])//节点之间的负电荷
.start();
//创建连线的SVG直线
var edges=svg.selectAll("line")
.data(dataset.edges)
.enter()
.append("line")
.style("stroke","red")//定义颜色
.style("stroke-width",2);//粗细
var color=d3.scale.category20();
//为每个节点创建SVG圆形
var nodes=svg.selectAll("circle")
.data(dataset.nodes)
.enter()
.append("circle")
.attr("r",10)
.style("fill",function(d,i){
return color(i);
})
.call(force.drag);//启用拖动交互作用
//添加描述节点的文字
var texts = svg.selectAll("text")
.data(dataset.nodes)
.enter()
.append("text")
.style("fill", "black")
.attr("dx", 20)
.attr("dy", 8)
.text(function(d){
return d.name;
});
//每打一次点,力导向布局就会根据初始化布局时指定的数据,调整每个结点和连线的位置值(更新与之关联的元素--直线和圆形)
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.source.x;})
.attr("y2",function(d){return d.source.y;})
nodes.attr("cx",function(d){return d.x;})
.attr("cy",function(d){return d.y;});
texts.attr("x",function(d){return d.x;})
.attr("y",function(d){return d.y;});
});
</script>