20任务十七——页面交互功能实现柱状图
Posted cjlalala
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20任务十七——页面交互功能实现柱状图相关的知识,希望对你有一定的参考价值。
0、题目
- 参考以下示例代码,原始数据包含几个城市的空气质量指数数据
- 用户可以选择查看不同的时间粒度,以选择要查看的空气质量指数是以天为粒度还是以周或月为粒度
- 天:显示每天的空气质量指数
- 周:以自然周(周一到周日)为粒度,统计一周7天的平均数为这一周的空气质量数值,如果数据中缺少一个自然周的几天,则按剩余天进行计算
- 月:以自然月为粒度,统一一个月所有天的平均数为这一个月的空气质量数值
- 用户可以通过select切换城市
- 通过在"aqi-chart-wrap"里添加DOM,来模拟一个柱状图图表,横轴是时间,纵轴是空气质量指数,参考图(点击打开)。天、周、月的数据只根据用户的选择显示一种。
- 天:每天的数据是一个很细的矩形
- 周:每周的数据是一个矩形
- 月:每周的数据是一个很粗的矩形
- 鼠标移动到柱状图的某个柱子时,用title属性提示这个柱子的具体日期和数
1、解答过程
task17.html
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>IFE javascript Task 17</title> 6 <style> 7 #aqi-chart-wrap{ 8 width:90%; 9 height:500px; 10 display: flex; 11 justify-content: center; 12 align-content: center; 13 align-items: flex-end; 14 margin:10px auto; 15 } 16 .div{ 17 display:inline-block; 18 width:20px; 19 margin-left:3px; 20 } 21 </style> 22 </head> 23 <body> 24 <fieldset id="form-gra-time"> 25 <legend>请选择日期粒度:</legend> 26 <label>日<input name="gra-time" value="day" type="radio" checked="checked"></label> 27 <label>周<input name="gra-time" value="week" type="radio"></label> 28 <label>月<input name="gra-time" value="month" type="radio"></label> 29 </fieldset> 30 <fieldset> 31 <legend>请选择查看的城市:</legend> 32 <select id="city-select"> 33 </select> 34 </fieldset> 35 <div id="aqi-chart-wrap"> // 柱状图显示区 36 37 </div> 38 <script src="task17.js"> </script> 39 </body> 40 </html>
task17.js
1 /* 数据格式演示 2 var aqiSourceData = { 3 "北京": { 4 "2016-01-01": 10, 5 "2016-01-02": 10, 6 "2016-01-03": 10, 7 "2016-01-04": 10 8 } 9 }; 10 */ 11 // 以下两个函数用于随机模拟生成测试数据 12 function getDateStr(dat) { 13 var y = dat.getFullYear(); //返回表示当前年份的四位数字 14 var m = dat.getMonth() + 1; //getMonth()返回0-11的数来表示当前月份 15 m = m < 10 ? \'0\' + m : m; 16 var d = dat.getDate(); //返回月份中的某一天,1-31之间的数 17 d = d < 10 ? \'0\' + d : d; 18 return y + \'-\' + m + \'-\' + d; 19 } 20 function randomBuildData(seed) { 21 var returnData = {}; 22 var dat = new Date("2016-01-01"); 23 var datStr = \'\'; 24 for (var i = 1; i < 92; i++) { 25 datStr = getDateStr(dat); 26 returnData[datStr] = Math.ceil(Math.random() * seed); //得到与每天相对应的随机空气质量指数数据 27 dat.setDate(dat.getDate() + 1); 28 } 29 return returnData; 30 } 31 32 var aqiSourceData = { 33 "北京": randomBuildData(500), 34 "上海": randomBuildData(300), 35 "广州": randomBuildData(200), 36 "深圳": randomBuildData(100), 37 "成都": randomBuildData(300), 38 "西安": randomBuildData(500), 39 "福州": randomBuildData(100), 40 "厦门": randomBuildData(100), 41 "沈阳": randomBuildData(500) 42 }; 43 // 用于渲染图表的数据 44 var chartData = {}; 45 // 记录当前页面的表单选项 46 var pageState= { 47 nowSelectCity: "北京", 48 nowGraTime: "day", 49 width:20 50 } 51 var aqiChartWrap=document.getElementById("aqi-chart-wrap"), 52 formGraTime=document.getElementById("form-gra-time"), 53 citySelect=document.getElementById("city-select"); 54 /* 55 渲染图表 56 */ 57 function renderChart() { 58 var content=" "; 59 for(var item in chartData){ 60 var bg="#" + Math.random().toString(16).substring(2, 8); //得到背景的随机颜色 61 content+=\'<div class="div"style="height:\'+chartData[item]+\'px;width:\'+pageState.width+\'px;background-color:\'+bg+\';"\'+\'title="\'+item+\' 空气质量指数:\'+chartData[item]+\'">\'+ 62 \'</div>\'; 63 } 64 aqiChartWrap.innerHTML=content; 65 } 66 /** 67 * 初始化日、周、月的radio事件,当点击时,调用函数graTimeChange 68 */ 69 function initGraTimeForm() { 70 formGraTime.addEventListener("click",graTimeChange); 71 } 72 /** 73 * 日、周、月的radio事件点击时的处理函数 74 */ 75 function graTimeChange() { 76 // 确定是否选项发生了变化 77 var input=document.getElementsByTagName("input"); 78 for(var i=0;i<input.length;i++){ 79 if(input[i].checked){ //确定选中的粒度 80 pageState.nowGraTime=input[i].value; // 设置对应数据 81 } 82 } 83 initAqiChartData(); // 调用图表渲染函数 84 } 85 /** 86 * 初始化城市Select下拉选择框中的选项 87 */ 88 function initCitySelector() { 89 // 读取aqiSourceData中的城市,然后设置id为city-select的下拉列表中的选项 90 var content=" "; 91 for(var city in aqiSourceData ){ 92 content+=\'<option value="\'+city+\'" >\'+city+\'</option>\'; 93 } 94 citySelect.innerHTML=content; 95 // 给select设置事件,当选项发生变化时调用函数citySelectChange 96 citySelect.addEventListener("change",citySelectChange); 97 } 98 /** 99 * select发生变化时的处理函数 100 */ 101 function citySelectChange() { 102 var options=document.getElementsByTagName("option"); 103 for(var i=0;i<options.length;i++){ 104 if(options[i].selected){ // 确定被选中的城市 105 pageState.nowSelectCity=options[i].value; // 设置对应数据 106 } 107 } 108 initAqiChartData(); // 调用原始数据处理函数 109 } 110 /** 111 * 初始化图表需要的数据格式 112 */ 113 function initAqiChartData() { 114 //将选中城市的数据先放在chart中 115 var chart=aqiSourceData[pageState.nowSelectCity]; 116 switch(pageState.nowGraTime){ //根据选择的粒度计算数据并保存至chartData 117 case "day":{ 118 chartData={}; 119 chartData=chart; 120 pageState.width=10; //设置每个显示出来的柱子的宽度 121 break; 122 } 123 case "week":{ 124 chartData={}; 125 var sum=0,i=0,week=0; 126 for(var item in chart){ 127 sum+=chart[item]; 128 i++; 129 if(new Date(item).getDay()==6) { 130 week++; 131 chartData[\'2016年第\'+week+\'周\']=Math.round(sum/i); 132 sum=0;i=0; 133 } 134 } 135 if(sum!=0){ 136 week++; 137 chartData[\'2016年第\'+week+\'周\']=Math.round(sum/i); 138 } 139 pageState.width=100; 140 break; 141 } 142 case "month":{ 143 chartData={}; 144 var sum=0,i=0,month=0; 145 for(var item in chart){ 146 if((new Date(item)).getMonth()==month) { 147 sum+=chart[item]; 148 i++; 149 } 150 else{ 151 month++; 152 chartData[\'2016年\'+month+\'月\']=Math.round(sum/i); 153 sum=0;i=0; 154 sum+=chart[item]; 155 i++; 156 } 157 } 158 if(sum!=0){ 159 month++; 160 chartData[\'2016年\'+month+\'月\']=Math.round(sum/i); 161 } 162 pageState.width=300; 163 break; 164 } 165 } 166 renderChart(); //调用图表渲染函数 167 } 168 // 初始化函数 169 function init() { 170 initGraTimeForm() 171 initCitySelector(); 172 initAqiChartData(); 173 renderChart(); 174 } 175 init();
2、遇到的问题
(1)title属性:
title 属性规定关于元素的额外信息。
这些信息通常会在鼠标移到元素上时显示一段工具提示文本(tooltip text)。
(2)onchange事件在数据变化时才会发生
为了得到用户选择查看的城市并处理对应数据,给select设置事件,当选项发生变化时调用函数citySelectChange,修改pageState.nowSelectCity(记录当前页面表单的城市选项)的值,由于题目中给的pageState.nowSelectCity:-1;与后续的数据处理函数没有绑定,所以页面被打开时并不会渲染柱状图,又因为这里用到onchange事件监听选项变化,而onchange事件必须在数据有变化的时候才会发生,所以一开始默认选择的是北京,接着再点北京是不会触发事件的,必须先点其他城市,再点回北京才会出现柱状图,这里有两种方法避免这种情况:
A、将pageState.nowSelectCity 最初默认值设置为“北京”,这样页面打开时就会呈现北京市的柱状图,之后选择其他的城市,onchange事件就会发生。
B、在北京前面加一个option,选项名可以为“城市名”,之后用户无论选择什么城市,都会触发事件渲染图表;
支持onchange事件的 HTML 标签:
<input type="text">, <select>, <textarea>
支持onchange事件的 JavaScript 对象:
select, text, textarea,fileUpload(FileUpload 控件显示一个文本框控件和一个浏览按钮,使用户可以选择客户端上的文件并将它上载到 Web 服务器。)
(3)自然周/月
题目中要求用户选择 “周” 时要以自然周(周一到周日)为粒度,开始做的方法是从第一个数据开始,每7个数据求一个平均数,后来发现第一个数据也就是2016-01-01并不一定是一周的第一天,所以这种方法行不通。具体可行的方法如下:
将所有的日期放在一个新的Date对象中,之后利用getDay()方法,该方法返回值是 0(周日) 到 6(周六) 之间的一个整数,所以当new Date.getDay()=6时就意味着一个自然周结束了,所以将每次new Date.getDay()=6之前的<=7个数据求平均即可,同时只要最后的求和!=0就说明最后一组不到7个数据,也应该求平均值。
“月”要以自然月为粒度做法和上面类似,利用getMonth()方法,该方法返回值是 0(一月) 到 11(十二月) 之间的一个整数。
以上是关于20任务十七——页面交互功能实现柱状图的主要内容,如果未能解决你的问题,请参考以下文章
Qt+ECharts开发笔记:ECharts的动态排序柱状图介绍基础使用和Qt封装Demo