使用 D3.js 进行简单的数据可视化--折线图

本文介绍如何使用D3.js实现北京市不同地区PM2.5指数的可视化展示,通过绘制折线图来直观呈现各监测点的数据变化趋势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

写在前面:大数据课程的作业之一是利用 D3.js 实现数据的可视化,下面记录一下简单的的实现 。

先附上程序(直接引入JSON文件的版本):

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>显示北京PM2.5的数值</title>
<script src="../D3_JS/d3.min.js"></script>
<script src="../D3_JS/d3.js"></script>
<script type="text/javascript" src="BeiJingPM2_5.js" ></script>//引入json数据,看下面解释
</head>
<body>
<div id = "svg"></div>
<script>  
 var data_DingLing = new Array(23);  
 var data_DongSi = new Array(23);
 var data_TianTan = new Array(23);
 var data_NongZhanGuan = new Array(23);
 var data_GuCheng = new Array(23);
 const data_time = ["0:00","1:00","2:00","3:00","4:00","5:00","6:00","7:00"
  ,"8:00","9:00","10:00","11:00","12:00","13:00","14:00"
  ,"15:00","16:00","17:00","18:00","19:00","20:00","21:00"
  ,"22:00","23:00"]
 var dingLing = 0;
 var dongsi = 0;
 var tiantan = 0;
 var nongzhanguan = 0;
 var gucheng = 0;
 var locationName = ["定陵","东四","天坛","农展馆","古城"];
 var data = [data_DingLing,data_DongSi,data_TianTan,data_NongZhanGuan,data_GuCheng];
 
 var dataset = eval(beijing_PM2_5); //可以直接使用BeiJingPM2_5.js 中定义的json值了


   //把各地 PM2.5 数据分别取出来
for(var i=0; i<dataset.PM_data.length;i++){
        //把csvData中的数值型数据变为整数型
dataset.PM_data[i].PM2_5 = + dataset.PM_data[i].PM2_5;

if(dataset.PM_data[i].jczname == "定陵"){
data_DingLing[dingLing] = dataset.PM_data[i].PM2_5;
dingLing++;
}

if(dataset.PM_data[i].jczname == "东四"){
data_DongSi[dongsi] = dataset.PM_data[i].PM2_5;
dongsi++;
}

if(dataset.PM_data[i].jczname == "天坛"){
data_TianTan[tiantan] = dataset.PM_data[i].PM2_5;
tiantan++;
}

if(dataset.PM_data[i].jczname == "农展馆"){
data_NongZhanGuan[nongzhanguan] = dataset.PM_data[i].PM2_5;
nongzhanguan++;
}

if(dataset.PM_data[i].jczname == "古城"){
data_GuCheng[gucheng] = dataset.PM_data[i].PM2_5;
gucheng++;
}

}
//定义坐标轴
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("#svg").append("svg").attr("width",width+40).attr("height",height+40);
//设置坐标轴的比例尺
const xScale = d3.scaleBand().domain(data_DingLing.map((o,i)=>i)).range([0,xAxisWidth]);
const yScale = d3.scaleLinear().domain([0,
d3.max([ d3.max(data_DingLing),d3.max(data_DongSi),d3.max(data_TianTan),d3.max(data_NongZhanGuan),d3.max(data_GuCheng)] ) + 20])
.rangeRound([yAxisWidth,0]);
const xAxis = d3.axisBottom(xScale).tickFormat(function(d){return data_time[d];});//可显示自己定义的标注,本例也可使用 tickFormat(function(d){return d+":00";})
const yAxis = d3.axisLeft(yScale);

const gy = svg.append('g').attr("transform","translate(" + (padding.left)*3 + "," + (height - padding.bottom - yAxisWidth) + ")");
const gx = svg.append("g").attr("transform",`translate(${(padding.left)*3}, ${height - padding.bottom})`);
//画x轴并加上标注
gx.call(xAxis).append("text")
           //.attr("class", "yAxislabel") //加不加class皆可
           .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=>"时间 / h");
           //画y轴并加上标注
gy.call(yAxis).append("text")  
           //.attr("class", "yAxislabel") 
           .attr("text-anchor", "start")  
           .attr("stroke","red")
           .style("font-size","17px")
.style("font-style","宋体")
           .attr("x", (padding.left-5))  
           .attr("y", 40)  
           .text(d=>"PM2.5( ug/m³ )");
// 获得随机颜色
const color = d3.scaleOrdinal(d3.schemeCategory10); 
//定义折线
const pathLine = d3.line().curve(d3.curveBasis).x((d,i)=>xScale(i) + padding.left + xScale.bandwidth()/2)
         .y(d=>height - padding.bottom - (yScale(0) - yScale(d)));

const labels = svg.append("g");
//显示地名,颜色与折线是对应的
labels.selectAll("text").data(locationName).enter().append("text")
     .attr("stroke",(d,i)=>color(i))
     .attr("transform",(d,i)=>"translate(0,170)" + `translate(${width-padding.right*5},${i*55})`)
     .style("font-size","20px")
     .text(d=>d);
//画出各个地点对应的线,这里是用的比较笨的方法,因为没找到合适方法
for(var i=0; i < data.length; i++){
svg.append("path").attr("d",pathLine( data[i] )).attr("stroke",color(i))
     .attr("stroke-width","4px").attr("fill","none")
     .attr("transform",`translate(${(padding.left)*2},0)`);
}

//最下面加上一行标题
const header = ["北京市 2013/2/1日 0:00--23:00 各景区 PM2.5"];
const headers = svg.append("g");
headers.selectAll("text").data(header).enter().append("text")
     .attr("stroke","black")
     .attr("transform",`translate(${width/3-padding.left*2},${height+30})`)
     .style("font-size","25px")
     .text(d=>d);
    
</script>
</body>
</html>

程序已经加了注释,下面附上结果图:


在 D3.js 中,读取本地文件有时候会遇到 “跨域问题”,简单的说就是只能读取放在服务器上的文件,所以只能在编译器环境运行,下面先附上读取文件的方法:

 d3.csv("BeiJingPM2_5UTF.csv",function(csvData){
csvData.forEach(function(d){
        
d.PM2_5 = +d.PM2_5; //把csvData中的数值型数据变为整数型
d.jczname = d.jczname;
});

如果想解决跨域问题,可以百度一下,或者使用本例子中的方法:直接把JSON文件写入一个 js 页面(按JSON的格式来写),然后引入本页面即可。

https://www.bejson.com/json/col2json/ (在线Excel,CSV转JSON)

下面给出本例中包含JSON文件的js页面:

BeiJingPM2_5.js :

var beijing_PM2_5 = {
PM_data:[
{"jczname":"定陵","PM2_5":"69"},
.........
{"jczname":"古城","PM2_5":"15"},
]
}

这样就变相解决了跨域的问题大笑

写在前面:有错的话再来修改。


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值