利用D3.js(V4)绘制折线图(曲线图)

前言

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 大佬的代码,我稍微根据自己的数据形式改了一些,大家有兴趣可以看看。
前端的路还是难度不小,成长之路也是一步一步,加油吧!!!

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值