D3.js是一个非常强大的可视化工具,这几天我正在学习相关的知识,主要是我项目里有在使用,觉得D3.js比Echarts强大,和大家一起分享一下,先附上D3.js的官方地址:
https://iowiki.com/d3js/d3js_introduction.html
1.先看一个简单的例子:一个黄色的圆的实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<!-- 先去官网把d3.js文件下载下来,然后引入 -->
<!-- 或者直接这么引入也可以 ,不用下载了-->
<script src="https://d3js.org/d3.v6.min.js"></script>
</head>
<body>
<svg width='960' height='500' id='mainsvg' class='svgs'></svg>
<script>
let mainSvg = d3.select('.svgs') //选择了svg这个标签
let maingroup = mainSvg
.append('g') //在我选择标签时,我会在它里面添加一个组 <g></g>
.attr('transform', `translate(${100},${100})`) //把这个组向下和向右各平移100个像素
let circle = maingroup
.append('circle') //attr是设置元素的一个属性,这里代表在组里面添加了一个circle,然后添加了3个属性
.attr('stroke', 'black') //描边 内圈边 设置为黑色
.attr('r', '66') //半径是66px
.attr('fill', 'yellow') //填充颜色是yellow
</script>
</body>
</html>
可以看到一个黄色的圆:
2. 使用D3设置SVG的属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BarChart!</title>
<script src="https://d3js.org/d3.v6.min.js"></script>
</head>
<body>
<svg width='1600' height='800' id='mainsvg' class='svgs'></svg>
<script>
const data=[{name:'junxi',value:'3'},
{name:'wangyang',value:'5'},{name:'lihe',value:'16'},{name:'makui',value:'6'},
{name:'liwu',value:'6'},{name:'wenliu',value:'8'},{name:'yexuan',value:'3'},
{name:'guangzhi',value:'9'},{name:'lidan',value:'12'},{name:'chizi',value:'8'},
{name:'luixiang',value:'7'},{name:'zhangwei',value:'4'},
{name:'yunpeng',value:'3'},{name:'sunyue',value:'6'}, ]
const svg = d3.select('#mainsvg') //选择了svg这个标签的id
const width=+svg.attr('width')//获取到了SVG标签的宽和高
const height=+svg.attr('height')
const margin={top:60,right:30,bottom:60,left:100}//预先给一个magrin,要不然坐标轴可能显示不出来
const innerWidth=width-margin.left-margin.right//内容宽度
const innerHeight=height-margin.top-margin.bottom//内容高度
const xScale=d3.scaleLinear()//X轴
.domain([0,d3.max(data,d=>d.value)])
.range([0,innerWidth])//最小值是0,宽度就是我们设置的减去magrin后的值
const yScale=d3.scaleBand()//y轴
.domain(data.map(d=>d.name))
.range([0,innerHeight])//最小值是0,高度就是我们设置的减去magrin后的值
.padding(0.1)//每个矩形间距留出1%的位置
const g=svg.append('g').attr('id','maingroup')
.attr('transform',`translate(${margin.left},${margin.right})`)
const yAxis=d3.axisLeft(yScale)//定义y坐标轴
.tickSize(-innerWidth)//对轴线的控制
g.append('g').call(yAxis)//把容器填满
const xAxis=d3.axisBottom(xScale)
g.append('g').call(xAxis)//默认坐标轴在上方显示
.attr('transform',`translate(0,${innerHeight})`)//把X轴放在下边显示
data.forEach(d=>{
g.append('rect')//设置每个人名的柱形图 矩形
.attr('width',xScale(d.value))
.attr('height',yScale.bandwidth())//y轴属性稍显特殊
.attr('fill','green')
.attr('opacity',0.8)//设置透明度
.attr('y',yScale(d.name))
})
d3.selectAll('.tick text').attr('font-size','2em')//设置刻度的字体,单位是em
g.append('text').text('Members of CSCG')//添加一个标题
.attr('font-size','2em')
.attr('transform',`translate(${innerWidth/2},0)`)//设置居中显示
.attr('text-anchor','middle')
</script>
</body>
</html>
看一下运行的效果:
3.data的join属性:使用给定的数据集映射现有文档的元素
(1)先看一个简单的例子
<body>
<ul id="list">
<li></li>
<li></li>
</ul>
<script>
d3.select("#list").selectAll("li").data([10, 20, 30, 25, 15])
.text(function (d) {
return "此时映射的数据是" + d; //返回前两个数据 10 20 对应文档中定义的两个li元素
})
.enter() //表示对对剩余数据的访问
.append("li") //用于从相应数据创建新元素
.text(function (d) {
return "后三个数据是" + d; //返回 30 25 15
})
</script>
</body>
(2)exit()和remove()方法
<body>
<ul id="list">
<li></li>
<li></li>
</ul>
<input type="button" name="remove" value="移除第四项" onclick="remove()" />
<script>
d3.select("#list").selectAll("li")
.data([10, 20, 30, 25, 15])
.text(function (d) {
return "此时映射的数据是 " + d;
})
.enter()
.append("li")
.text(function (d) {
return "剩余三个数据是 " + d;
});
function remove() {
d3.selectAll("li")
.data([10, 20, 30, 15])
.exit() //从数据集中动态删除的数据项
.remove() //把25这一项值删除了
}
</script>
</body>
(3)datum()方法
<body>
<p></p>
<div></div>
<script>
d3.select("p")
.datum(50)//datum()方法用于为HTML文档中的单个元素设置值,这里为p标签设置了50
.text(function(d) {
return "p的值是 " + d ;
});
d3.select("div")
.datum(100)//这里为div设置了100
.append("p")
.text(function(d) {
return "div的值是 " + d ;
});
</script>
</body>
4.Paths :路径用于绘制矩形,圆形,椭圆形,折线,多边形,直线和曲线。
(1)绘制一条简单的线
<!DOCTYPE html>
<meta charset = "UTF-8">
<head>
<title>SVG path line Generator</title>
</head>
<style>
path {
fill: green;
stroke: #aaa;
}
</style>
<body>
<svg width = "600" height = "100">
<path transform = "translate(200, 0)" />
</svg>
<script src = "https://d3js.org/d3.v4.min.js"></script>
<script>
var data = [[0, 20], [50, 30], [100, 50], [200, 60], [300, 90]];
var lineGenerator = d3.line();//用于创建从当前点到定义的x,y值的线
var pathString = lineGenerator(data);
d3.select('path').attr('d', pathString);
</script>
</body>
</html>
看下运行效果:
5.Selections
(1)append()方法
<!DOCTYPE html>
<html>
<head>
<script type = "text/javascript" src = "https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<div class = "myclass">
Hello World!
</div>
<script>
d3.select("div.myclass").append("span");//append()方法将新元素作为当前选择中元素的最后一个子元素附加
</script>
</body>
</html>
效果展示:
(2) html()方法:用于设置所选元素的html内容
<!DOCTYPE html>
<html>
<head>
<script type = "text/javascript" src = "https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<div class = "myclass">
Hello World!
</div>
<script>
//html()方法用于设置所选/附加元素的html内容。
d3.select(".myclass").html("Hello World! <span>from D3.js</span>");
</script>
</body>
</html>
看下效果:
(3)attr()方法:用于添加或更新所选元素的属性
<!DOCTYPE html>
<html>
<head>
<script type = "text/javascript" src = "https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<div class = "myclass">
Hello World!
</div>
<script>
//attr()方法用于添加或更新所选元素的属性
// d3.select(".myclass").attr("style", "color: red");
d3.select(".myclass").style("color", "red");//等价于上面的代码
</script>
</body>
</html>
看下效果:
(4) classed()方法:用于设置HTML元素的“class”属性。
<!DOCTYPE html>
<html>
<head>
<script type = "text/javascript" src = "https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<div class = "myclass">
Hello World!
</div>
<script>
d3.select(".myclass").classed("myanotherclass", true);//Add class - 要添加类,必须将分类方法的第二个参数设置为true
d3.select(".myclass").classed("myanotherclass", false);//要删除类,必须将分类方法的第二个参数设置为false
</script>
</body>
</html>
(5)selectAll():用于选择HTML文档中的多个元素
<!DOCTYPE html>
<html>
<head>
<script type = "text/javascript" src = "https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<h2 class = "myclass">Message</h2>
<div class = "myclass">
Hello World!
</div>
<script>
d3.selectAll(".myclass").attr("style", "color: red");
</script>
</body>
</html>
看下效果:
6.Drawing Charts
(1)条形图
<html>
<head>
<script type="text/javascript" src="https://d3js.org/d3.v4.min.js"></script>
<style>
svg rect {
fill: gray;
/* 设置矩形颜色 */
}
svg text {
fill: yellow;
/* 文本颜色 */
font: 12px sans-serif;
text-anchor: end;
}
</style>
</head>
<body>
<script>
var data = [10, 5, 12, 15];
var width = 300 //SVG的宽度
scaleFactor = 20, //缩放到屏幕上可见的像素值
barHeight = 30; //水平条的静态高度
var graph = d3.select("body")
.append("svg") //添加SVG元素
.attr("width", width)
.attr("height", barHeight * data.length);//高度计算为条形高度*数据值的数量
var bar = graph.selectAll("g")//附加组元素
.data(data)
.enter()
.append("g")
.attr("transform", function (d, i) {
return "translate(0," + i * barHeight + ")";
});
bar.append("rect").attr("width", function (d) {//将rect元素添加到栏中
return d * scaleFactor;
})
.attr("height", barHeight - 1);
bar.append("text")
.attr("x", function (d) {
return (d * scaleFactor);
})
.attr("y", barHeight / 2)//宽度定义为(数据值*比例因子)
.attr("dy", ".35em")//文本元素不支持填充或边距,设置一个“dy”偏移量
.text(function (d) {
return d;
});
</script>
</body>
</html>
看下效果:
(2) 圆图
<html>
<head>
<script type="text/javascript" src="https://d3js.org/d3.v4.min.js"></script>
</head>
<body>
<script>
var width = 400; //SVG的宽度
var height = 400; //SVG的高度
var data = [10, 20, 30]; //数据元素数组
var colors = ['green', 'purple', 'yellow']; //将颜色应用于圆形元素
var svg = d3
.select("body") //添加SVG元素
.append("svg")
.attr("width", width)
.attr("height", height);
var g = svg.selectAll("g") //创建用于保持圆圈的组元素
.data(data) //将我们的数据数组绑定到组元素
.enter() // 为我们的组元素创建占位符
.append("g") //将组元素添加到我们的页面
.attr("transform", function (d, i) {
return "translate(0,0)"; //相对于原点定位元素
})
g.append("circle") //将圆形元素附加到组中
.attr("cx", function (d, i) { //将属性添加到组中
return i * 75 + 50;
})
.attr("cy", function (d, i) {
return 75;
})
.attr("r", function (d) { //设置每个圆的半径
return d * 1.5; //半径乘以数据值以及常数“1.5”以增加圆的大小
})
.attr("fill", function (d, i) {
return colors[i]; //填充每个圆圈的颜色
})
g.append("text").attr("x", function (d, i) { //显示每个圆圈上的数据
return i * 75 + 25;
})
.attr("y", 80)
.attr("stroke", "teal")
.attr("font-size", "10px")
.attr("font-family", "sans-serif").text(function (d) {
return d;
});
</script>
</body>
</html>
看下效果:
就先写这么多,具体的各位还是看官方教程,挺详细的。