前言
D3.js是一个很优秀的可视化工具,也是一般的入门工具,可以和多种js和框架一同使用,可以有各种各样的操作。
这篇的代码借鉴了另一位大佬的代码。
学D3一个学期了,发现用的还是不是很6,打算写博客记录一下。
目录
如下所示,a.json是用的数据,index.css是主要的css文件,index.html是界面
数据
数据经过部分处理,这里就给一条吧。
只显示数据格式,非所用数据。
{
"BFS": [630, 624, 753, 600, 532, 1038, 772],
...
}
HTML
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>RainFall</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="css/index.css">
</head>
<body>
<!-- 引入D3.js(V4) -->
<script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
<!-- 在container里绘制 -->
<div id = "container"></div>
<!-- 引入画折线图的js -->
<script src="js/zhe.js" async defer></script>
</body>
</html>
CSS
CSS还是很简单的,因为只画了一张图表,选中container。
body
{
background-color: aqua;
}
#container
{
background-color: #ffffff;
width: 1250px;
height: 650px;
}
JS
线生成器
画折线图最主要的部分
// 创建线生成器
const pathLine = d3.line()
.curve(d3.curveBasis) // 如果没有这一行则是折线,有则为曲线
.x((d, i) => xScale(i + 1970) + padding.left + xScale.bandwidth() / 2)
.y(d => height - padding.bottom - (yScale(0) - yScale(d)));
自动生成颜色
找多种颜色一直很麻烦,看了网上一个大佬的方式,很好,但缺点是差异度可能不是很大,如果要观察清晰还要自己配色。
// 可以自动生成颜色
var color = [];
for (i = 0; i < 80; i++) {
var letters = '0123456789ABCDEF'.split('');
var rand_color = '#';
for (var j = 0; j < 6; j++) {
rand_color += letters[Math.round(Math.random() * 15)];
}
color[i] = rand_color;
}
绘制曲线
可以绘制多条曲线。
// 绘制曲线
for (var i = 0; i < data_sum.length; ++i) {
svg.append("path")
.attr("d", pathLine(data_sum[i]))
.attr("stroke", color[i])
.attr("stroke-width", "1px")
.attr("fill", "none")
.attr("transform", `translate(${(padding.left)*2},0)`);
}
剩下的大同小异。
完整JS代码
// 绘制折线图
const padding = {
top: 20,
left: 20,
right: 20,
bottom: 20
};
const height = 600;
const width = 1200;
const xAxisWidth = width - padding.left - padding.right;
const yAxisWidth = height - padding.top - padding.bottom;
// 创建svg画布
const svg = d3.select("#container")
.append("svg")
.attr("width", width + 40)
.attr("height", height + 40)
// 打开要用相对路径,否则很容易发生跨域错误,然后凉凉
d3.json("./data/a.json", function (dataset) {
console.log(dataset);
data_key = []
year = []
data_sum = []
for (var i in dataset) {
data_change = []
data_key.push(i);
for (var num in dataset[i]) {
data_change.push(parseInt(dataset[i][num]))
}
data_sum.push(data_change)
}
console.log(data_sum)
const xScale = d3.scaleBand()
.domain(dataset[data_key[0]].map((o, i) => i + 1970))
.range([0, xAxisWidth]);
const yScale = d3.scaleLinear()
.domain([400, 3000])
.rangeRound([yAxisWidth, 0])
const xAxis = d3.axisBottom(xScale)
const yAxis = d3.axisLeft(yScale);
const gx = svg.append("g")
.attr("transform", `translate(${(padding.left)*3}, ${height - padding.bottom})`);
const gy = svg.append('g')
.attr("transform", "translate(" + ((padding.left) * 3 + 12) + "," + (height - padding.bottom - yAxisWidth) + ")");
// 绘制x轴
gx.call(xAxis)
.append("text")
.attr("text-anchor", "start")
.attr("stroke", "red")
.style("font-size", "17px")
.style("font-style", "宋体")
.attr("x", width - padding.right * 5)
.attr("y", padding.bottom * 2)
.text(d => "年 / year");
// 绘制y轴
gy.call(yAxis).append("text")
.attr("text-anchor", "start")
.attr("stroke", "red")
.style("font-size", "17px")
.style("font-style", "宋体")
.attr("x", (padding.left - 10))
.attr("y", 40)
.text(d => "降水量 / mm");
// 可以自动生成颜色
var color = [];
for (i = 0; i < 80; i++) {
var letters = '0123456789ABCDEF'.split('');
var rand_color = '#';
for (var j = 0; j < 6; j++) {
rand_color += letters[Math.round(Math.random() * 15)];
}
color[i] = rand_color;
}
// 创建线生成器
const pathLine = d3.line()
.curve(d3.curveBasis) // 如果没有这一行则是折线,有则为曲线
.x((d, i) => xScale(i + 1970) + padding.left + xScale.bandwidth() / 2)
.y(d => height - padding.bottom - (yScale(0) - yScale(d)));
// 绘制曲线
for (var i = 0; i < data_sum.length; ++i) {
svg.append("path")
.attr("d", pathLine(data_sum[i]))
.attr("stroke", color[i])
.attr("stroke-width", "1px")
.attr("fill", "none")
.attr("transform", `translate(${(padding.left)*2},0)`);
}
// 添加表头
const header = ["1970 - 2013 各站点降水量统计图"];
const headers = svg.append("g");
headers.selectAll("text")
.data(header)
.enter()
.append("text")
.attr("stroke","black")
.attr("transform",`translate(${width/3 + padding.left * 4},${30})`)
.style("font-size","25px")
.text(d=>d);
})
效果图
写在后面
感谢zhangzhe_0305 大佬的代码,我稍微根据自己的数据形式改了一些,大家有兴趣可以看看。
前端的路还是难度不小,成长之路也是一步一步,加油吧!!!