如何用JavaScript实现渐变色调的波形图绘制?
最编程
2024-02-10 16:39:03
...
1. 前言
色阶图适合二维的数据,而且横轴跟纵轴的标签都比较多。本期的数据:
Example data shows concurrent user sessions over time, taken from a development environment.
翻译过来大意就是:展示的是随着时间的推移用户会话并发的个数
数据结构:
星期数 |
时间点 |
会话数 |
day |
hour |
value |
1 |
1 |
16 |
图形:
2. 色阶图
1)本地链接
2)知识点:
2. 读取csv格式数据画图,并且解决中文乱码问题
3. 图形的转变效果: d3.transition().duration()
4. x轴文字竖放以及标签突出重点
3)图形效果:
自己应用的场景:某品牌商想重点关注自己的产品型号在重点电商店铺的销量情况,这里涉及的型号和店铺都很多,导致excel数据表非常的庞大而稀疏,所以用色阶图会比较直观的展示出top-N的店铺里哪种型号卖的好,某些特定的型号会在哪些店铺买的好。颜色的深浅就代表销量的多少,越深越多,越浅越少。
4)完整的网页代码(内含详细解释):
1 <!DOCTYPE html>
2 <meta charset="utf-8">
3 <html>
4 <head>
5 <style> //css样式区
6 rect.bordered {stroke: #E6E6E6;stroke-width:2px;}
7 text.mono {font-size: 9pt;font-family: Consolas, courier;fill: #aaa;}
8 text.axis-workweek {fill: #000;}
9 text.axis-worktime {fill: #000;}
10 </style>
11 <script src="http://d3js.org/d3.v3.js"></script>
12 </head>
13 <body>
14 <div id="chart"></div>
15 <div id="dataset-picker">
16 </div>
17 <script type="text/javascript">
18 //1. 先定义一些全局变量
19 var margin = { top: 80, right: 0, bottom: 100, left: 150 },
20 width = 1000 - margin.left - margin.right,
21 height = 800 - margin.top - margin.bottom,
22 gridSize = Math.floor(width / 73),//格子的大小
23 legendElementWidth = gridSize*5, //图例的宽度
24 buckets = 9,
25 colors = ["#ffffd9","#edf8b1","#c7e9b4","#7fcdbb","#41b6c4","#1d91c0","#225ea8","#253494","#081d58"], // alternatively colorbrewer.YlGnBu[9]
26 times=[['E408','0'],['E488','0'],['E518','0'],['E568','0'],['G1800','1'],['G2800','1'],['G3800','1'],['IP110','0'],['IP1188','0'],['IP2780','1'],['IP2880S','1'],['IP7280','1'],['IP8780','0'],['IX6580','0'],['IX6780','0'],['IX6880','0'],['LBP151dw','0'],['LBP2900+','0'],['LBP5960(A3)','0'],['LBP6018L','1'],['LBP6018W','0'],['LBP6230dn','1'],['LBP6230dw','0'],['LBP6300dn','0'],['LBP7010C','1'],['LBP7100Cn','0'],['LBP7200Cd','0'],['LBP8100n(A3)','0'],['LBP9100Cdn(A3)','0'],['MF211','0'],['MF212w','1'],['MF215','0'],['MF216n','0'],['MF226dn','0'],['MF229dw','0'],['MF3010','0'],['MF4712','1'],['MF4752','1'],['MF6140dn','0'],['MF621Cn','0'],['MF623Cn','0'],['MF628Cw','0'],['MF725Cdn','0'],['MF727Cdw','0'],['MF810Cdn','0'],['MG2400','0'],['MG2580S','1'],['MG2980','0'],['MG3680','1'],['MG5780','0'],['MG6880','0'],['MG7780','1'],['MP236','0'],['MP288','1'],['MX498','0'],['MX538','0'],['MX728','0'],['MX928','0'],['PRO-1','0'],['PRO-10','0'],['PRO-100','0'],['PRO-500','0']]
27 days = ['店铺1','店铺2','店铺3','店铺4','店铺5','店铺6','店铺7','店铺8','店铺9','店铺10','店铺11','店铺12','店铺13','店铺14','店铺15','店铺16','店铺17','店铺18','店铺19','店铺20','店铺21','店铺22','店铺23','店铺24','店铺25','店铺26','店铺27','店铺28','店铺29','店铺30','店铺31','店铺32','店铺33','店铺34','店铺35','店铺36','店铺37','店铺38','店铺39','店铺40','店铺41','店铺42','店铺43','店铺44','店铺45','店铺46','店铺47','店铺48','店铺49','店铺50','店铺51','店铺52','店铺53','店铺54','店铺55','店铺56','店铺57','店铺58','店铺59','店铺60','店铺61','店铺62','店铺63','店铺64','店铺65','店铺66','店铺67','店铺68','店铺69','店铺70','店铺71','店铺72','店铺73','店铺74','店铺75','店铺76','店铺77','店铺78','店铺79','店铺80','店铺81','店铺82','店铺83','店铺84','店铺85','店铺86','店铺87','店铺88','店铺89','店铺90','店铺91','店铺92','店铺93','店铺94','店铺95','店铺96','店铺97','店铺98','店铺99','店铺100','店铺101','店铺102','店铺103','店铺104','店铺105','店铺106','店铺107','店铺108','店铺109','店铺110','店铺111','店铺112','店铺113','店铺114','店铺115','店铺116','店铺117','店铺118','店铺119','店铺120']
28 datasets = ["data.csv", "data2.csv"]; //数据文件变量
29 //2. 画布
30 var svg = d3.select("#chart").append("svg")
31 .attr("width", width + margin.left + margin.right)
32 .attr("height", height + margin.top + margin.bottom)
33 .append("g")
34 .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
35 //3. 轴Y
36 var dayLabels = svg.selectAll(".dayLabel")
37 .data(days)
38 .enter().append("text")
39 .text(function (d) { return d; })
40 .attr("x", 0)
41 .attr("y", function (d, i) { return i * gridSize; })
42 .style("text-anchor", "end")
43 .attr("transform", "translate(-6," + gridSize / 1.5 + ")")
44 .attr("class", function (d, i) { return ((i >= 0 && i <= 29) ? "dayLabel mono axis axis-workweek" : "dayLabel mono axis"); }) ;//轴标签是否明显显示
45 //4. 轴X
46 var timeLabels = svg.selectAll(".timeLabel")
47 .data(times)
48 .enter().append("text")
49 .text(function(d) { return d[0]; })
50 .attr("x",gridSize)
51 .attr("y", 0)
52 .style("text-anchor", "start")
53 .attr("transform",function(d,i) { return "translate(" + gridSize*(i+1) + ", 8)rotate(" + (- 90) + ")"}) //x轴文字竖放
54 .attr("class", function(d, i) {console.log(d);return ((d[1]==1) ? "timeLabel mono axis axis-worktime" : "timeLabel mono axis"); })//轴标签是否明显显示
55
56 //5. 定义heatmapChart函数,输入文件路径即可画图
57 var heatmapChart = function(tsvFile) {
58 var csv = d3.dsv(",", "text/csv;charset=gb2312"); //解决中文转码
59 csv(tsvFile,function(d) { return {day: +d.day,hour: +d.hour,value: +d.value};},
60
61 function(error, data) {
62 var colorScale = d3.scale.quantile() //比例尺:与quantize类似,但输入值域是独立的值,适合已经对数据分类的情形。
63 .domain([0, buckets - 1, d3.max(data, function (d) { return d.value; })])
64 .range(colors);
65
66 var cards = svg.selectAll(".hour")
67 .data(data, function(d) {return d.day+':'+d.hour;});
68
69 cards.append("title");
70
71 cards.enter().append("rect")
72 .attr("x", function(d) { return (d.hour - 1) * gridSize; })
73 .attr("y", function(d) { return (d.day - 1) * gridSize; })
74 .attr("rx", 4)
75 .attr("ry", 4)
76 .attr("class", "hour bordered")
77 .attr("width", gridSize)
78 .attr("height", gridSize)
79 .style("fill", colors[0]);
80
81 //颜色渐变效果
82 cards.transition().duration(1000)
83 .style("fill", function(d) { return colorScale(d.value); });
84
85 cards.select("title").text(function(d) { return d.value; });
86
87 cards.exit().remove();
88
89 //添加图例
90 var legend = svg.selectAll(".legend")
91 .data([0].concat(colorScale.quantiles()), function(d) { return d; });
92
93 legend.enter().append("g")
94 .attr("class", "legend");
95
96 legend.append("rect")
97 .attr("x", width-150)
98 .attr("y",function(d, i) { return legendElementWidth * i; })
99 .attr("width", legendElementWidth)
100 .attr("height", gridSize / 2)
101 .style("fill", function(d, i) { return colors[i]; });
102
103 legend.append("text")
104 .attr("class", "mono")
105 .text(function(d) { return "≥ " + Math.round(d); })
106 .attr("x", width-150+gridSize*2)
107 .attr("y",function(d, i) { return legendElementWidth * i-gridSize; })
108 .style("fill", "black");
109 legend.exit().remove();
110
111 });
112 };
113
114 //6. 调用前面的heatmapChart函数,输入数据文件名称
115 heatmapChart(datasets[0]);
116
117 //7. 按钮
118 var datasetpicker = d3.select("#dataset-picker").selectAll(".dataset-button")
119 .data(datasets);
120
121 datasetpicker.enter()
122 .append("input")
123 .attr("value", function(d){ return "Dataset " + d })
124 .attr("type", "button")
125 .attr("class", "dataset-button")
126 .on("click", function(d) {
127 heatmapChart(d);
128 });
129 </script>
130 </body>
131 </html>
View Code