任务十七:零基础JavaScript编码(五)

任务目的

  • 在上一任务基础上继续JavaScript的体验
  • 接触更加复杂的表单对象
  • 实现页面上的一个完整交互功能
  • 用DOM实现一个柱状图图表

任务描述

  • 参考以下示例代码,原始数据包含几个城市的空气质量指数数据
  • 用户可以选择查看不同的时间粒度,以选择要查看的空气质量指数是以天为粒度还是以周或月为粒度
    • 天:显示每天的空气质量指数
    • 周:以自然周(周一到周日)为粒度,统计一周7天的平均数为这一周的空气质量数值,如果数据中缺少一个自然周的几天,则按剩余天进行计算
    • 月:以自然月为粒度,统一一个月所有天的平均数为这一个月的空气质量数值
  • 用户可以通过select切换城市
  • 通过在"aqi-chart-wrap"里添加DOM,来模拟一个柱状图图表,横轴是时间,纵轴是空气质量指数,参考图(点击打开)。天、周、月的数据只根据用户的选择显示一种。
    • 天:每天的数据是一个很细的矩形
    • 周:每周的数据是一个矩形
    • 月:每周的数据是一个很粗的矩形
  • 鼠标移动到柱状图的某个柱子时,用title属性提示这个柱子的具体日期和数据

task.html

<!DOCTYPE>
<html>
  <head>
    <meta charset="utf-8">
    <title>IFE JavaScript Task 01</title>
    <script src="task.js"></script>
  </head>
<body>
  <fieldset id="form-gra-time">
    <legend>请选择日期粒度:</legend>
    <label>日<input name="gra-time" value="day" type="radio" checked="checked"></label>
    <label>周<input name="gra-time" value="week" type="radio"></label>
    <label>月<input name="gra-time" value="month" type="radio"></label>
  </fieldset>

  <fieldset>
    <legend>请选择查看的城市:</legend>
    <select id="city-select">
      <option>北京</option>
    </select>
  </fieldset>

  <div class="aqi-chart-wrap">
  </div>
</body>
</html>

task.js

/* 数据格式演示
var aqiSourceData = {
  "北京": {
    "2016-01-01": 10,
    "2016-01-02": 10,
    "2016-01-03": 10,
    "2016-01-04": 10
  }
};
*/

// 以下两个函数用于随机模拟生成测试数据
function getDateStr(dat) {
  var y = dat.getFullYear();
  var m = dat.getMonth() + 1;
  m = m < 10 ? ‘0‘ + m : m;
  var d = dat.getDate();
  d = d < 10 ? ‘0‘ + d : d;
  return y + ‘-‘ + m + ‘-‘ + d;
}
function randomBuildData(seed) {
  var returnData = {};
  var dat = new Date("2016-01-01");
  var datStr = ‘‘
  for (var i = 1; i < 92; i++) {
    datStr = getDateStr(dat);
    returnData[datStr] = Math.ceil(Math.random() * seed);
    dat.setDate(dat.getDate() + 1);
  }
  return returnData;
}

var aqiSourceData = {
  "北京": randomBuildData(500),
  "上海": randomBuildData(300),
  "广州": randomBuildData(200),
  "深圳": randomBuildData(100),
  "成都": randomBuildData(300),
  "西安": randomBuildData(500),
  "福州": randomBuildData(100),
  "厦门": randomBuildData(100),
  "沈阳": randomBuildData(500)
};

// 用于渲染图表的数据
var chartData = {};

// 记录当前页面的表单选项
var pageState = {
  nowSelectCity: -1,
  nowGraTime: "day"
}

/**
 * 渲染图表
 */
function renderChart() {

}

/**
 * 日、周、月的radio事件点击时的处理函数
 */
function graTimeChange() {
  // 确定是否选项发生了变化 

  // 设置对应数据

  // 调用图表渲染函数
}

/**
 * select发生变化时的处理函数
 */
function citySelectChange() {
  // 确定是否选项发生了变化 

  // 设置对应数据

  // 调用图表渲染函数
}

/**
 * 初始化日、周、月的radio事件,当点击时,调用函数graTimeChange
 */
function initGraTimeForm() {

}

/**
 * 初始化城市Select下拉选择框中的选项
 */
function initCitySelector() {
  // 读取aqiSourceData中的城市,然后设置id为city-select的下拉列表中的选项

  // 给select设置事件,当选项发生变化时调用函数citySelectChange

}

/**
 * 初始化图表需要的数据格式
 */
function initAqiChartData() {
  // 将原始的源数据处理成图表需要的数据格式
  // 处理好的数据存到 chartData 中
}

/**
 * 初始化函数
 */
function init() {
  initGraTimeForm()
  initCitySelector();
  initAqiChartData();
}

init();

任务注意事项

  • 实现简单功能的同时,请仔细学习JavaScript基本语法、事件、DOM相关的知识
  • 请注意代码风格的整齐、优雅
  • 代码中含有必要的注释
  • 示例图仅为参考,不需要完全一致
  • 点击select或者radio选项时,如果没有发生变化,则图表不需要重新渲染
  • 建议不使用任何第三方库、框架
  • 示例代码仅为示例,可以直接使用,也可以完全自己重写

任务完成与总结:

我看不懂的JS代码:

// 以下两个函数用于随机模拟生成测试数据
function getDateStr(dat) {
    var y = dat.getFullYear();
    var m = dat.getMonth() + 1;
    m = m < 10 ? ‘0‘ + m : m;
    var d = dat.getDate();
    d = d < 10 ? ‘0‘ + d : d;
    return y + ‘-‘ + m + ‘-‘ + d;
}

function randomBuildData(seed) {
    var returnData = {};
    var dat = new Date("2016-01-01");
    var datStr = ‘‘;
    for (var i = 1; i < 92; i++) {
        datStr = getDateStr(dat);
        returnData[datStr] = Math.ceil(Math.random() * seed);
        dat.setDate(dat.getDate() + 1);
    }
    return returnData;
}

var aqiSourceData = {
    "北京": randomBuildData(500),
    "上海": randomBuildData(300),
    "广州": randomBuildData(200),
    "深圳": randomBuildData(100),
    "成都": randomBuildData(300),
    "西安": randomBuildData(500),
    "福州": randomBuildData(100),
    "厦门": randomBuildData(100),
    "沈阳": randomBuildData(500)
};

var colors = [‘#16324a‘, ‘#24385e‘, ‘#393f65‘, ‘#4e4a67‘, ‘#5a4563‘, ‘#b38e95‘,
              ‘#edae9e‘, ‘#c1b9c2‘, ‘#bec3cb‘, ‘#9ea7bb‘, ‘#99b4ce‘, ‘#d7f0f8‘];

// 用于渲染图表的数据
var chartData = {};

// 记录当前页面的表单选项
var pageState = {
    nowSelectCity: -1,
    nowGraTime: "day"
}

function getWidth(width, len) {
    var posObj = {};
    posObj.width = Math.floor(width / (len*2));
    posObj.left = Math.floor(width / len);
    posObj.offsetLeft = (width - posObj.left * (len - 1) - posObj.width) / 2;
    return posObj;
}

function getHintLfeft(posObj, i){
    if (posObj.left * i + posObj.offsetLeft + posObj.width / 2 - 60 <= 0) {
        return 5;
    } else if (posObj.left * i + posObj.offsetLeft + posObj.width / 2 + 60 >= 1200) {
        return (posObj.left * i + posObj.offsetLeft + posObj.width / 2 - 110);
    } else  {
        return (posObj.left * i + posObj.offsetLeft + posObj.width / 2 - 60);
    }
}

function getTitle() {
    switch (pageState.nowGraTime) {
        case "day":
            return "每日";
        case "week":
            return "周平均";
        case "month":
            return "月平均";
    }
}

/**
 * addEventHandler方法
 * 跨浏览器实现事件绑定
 */
function addEventHandler(ele, event, hanlder) {
    if (ele.addEventListener) {
        ele.addEventListener(event, hanlder, false);
    } else if (ele.attachEvent) {
        ele.attachEvent("on"+event, hanlder);
    } else  {
        ele["on" + event] = hanlder;
    }
}

/**
 * 渲染图表
 */
function renderChart() {
    var innerHTML = "", i = 0;
    var wrapper = document.getElementById("aqi-chart-wrap");
    var width = wrapper.clientWidth;
    var selectedData = chartData[pageState.nowGraTime][pageState.nowSelectCity];
    var len = Object.keys(selectedData).length;
    var posObj = getWidth(width, len);
    innerHTML += "<div class=‘title‘>" + pageState.nowSelectCity + "市01-03月"+ getTitle() +"空气质量报告</div>"
    for (var key in selectedData) {
        innerHTML += "<div class=‘aqi-bar " + pageState.nowGraTime + "‘ style=‘height:" + selectedData[key] + "px; width: " + posObj.width +"px; left:" + (posObj.left * i + posObj.offsetLeft) + "px; background-color:" + colors[Math.floor(Math.random() * 11)] + "‘></div>"
        innerHTML += "<div class=‘aqi-hint‘ style=‘bottom: " + (selectedData[key] + 10) + "px; left:" + getHintLfeft(posObj, i++) + "px‘>" + key + "<br/> [AQI]: " + selectedData[key] + "</div>"
    }
    wrapper.innerHTML = innerHTML;
}

/**
 * 日、周、月的radio事件点击时的处理函数
 */
function graTimeChange(radio) {
    // 确定是否选项发生了变化
    var value = radio.value;
    var item = radio.previousElementSibling;
    var items = document.getElementsByTagName(‘span‘);
    for (var i = 0; i < items.length; i++) {
        items[i].className = "";
    }
    item.className = "selected";
    if (value !== pageState.nowGraTime) {
        // 设置对应数据
        pageState.nowGraTime = value;
        // 调用图表渲染函数
        renderChart();
    }
}

/**
 * select发生变化时的处理函数
 */
function citySelectChange() {
    // 确定是否选项发生了变化
    var city = this.value;
    if (city !== pageState.nowSelectCity) {
        // 设置对应数据
        pageState.nowSelectCity = city;
        // 调用图表渲染函数
        renderChart();
    }
}

/**
 * 初始化日、周、月的radio事件,当点击时,调用函数graTimeChange
 */
function initGraTimeForm() {
    var radio = document.getElementsByName(‘gra-time‘);
    for (var i = 0; i < radio.length; i++) {
        (function (m) {
            addEventHandler(radio[m], ‘click‘, function () {
                graTimeChange(radio[m])
            })
        })(i);
    }
    addEventHandler(document, ‘mouseover‘, function(event){
        var ele = event.target;
        ele.className += " show";
    });
    addEventHandler(document, ‘mouseout‘, function(event){
        var ele = event.target;
        ele.className = ele.className.replace(/show/, "");
    });
}

/**
 * 初始化城市Select下拉选择框中的选项
 */
function initCitySelector() {
    // 读取aqiSourceData中的城市,然后设置id为city-select的下拉列表中的选项
    var select = document.getElementById("city-select");
    var cityArr = Object.getOwnPropertyNames(aqiSourceData);
    var htmlArr = cityArr.map(function(item) {
        return "<option>" + item + "</option>";
    });
    pageState.nowSelectCity = cityArr[0];
    select.innerHTML = htmlArr.join("");
    // 给select设置事件,当选项发生变化时调用函数citySelectChange
    addEventHandler(select, ‘change‘, citySelectChange);

}

/**
 * 初始化图表需要的数据格式
 */
function initAqiChartData() {
    // 将原始的源数据处理成图表需要的数据格式
    var week = {}, count = 0, singleWeek = {},
        month = {}, mcount = 0, singleMonth = {};

    for (var key in aqiSourceData) {
        var tempCity = aqiSourceData[key]
        var keyArr = Object.getOwnPropertyNames(tempCity);
        var tempMonth = keyArr[0].slice(5, 7);
        var weekInit = 4, weekCount = 0;
        for (var i = 0; i < keyArr.length; i++, weekInit++) {
            count += tempCity[keyArr[i]];
            mcount += tempCity[keyArr[i]];
            weekCount++;
            if ((weekInit+1) % 7 == 0 || i == keyArr.length - 1 || keyArr[i+1].slice(5, 7) !== tempMonth) {
                var tempKey = keyArr[i].slice(0, 7) + "月第" + (Math.floor(weekInit / 7) + 1) + "周";
                singleWeek[tempKey] = Math.floor(count / weekCount);

                if (i != keyArr.length - 1 && keyArr[i+1].slice(5, 7) !== tempMonth) {
                    weekInit = weekCount % 7;
                }
                count = 0;
                weekCount = 0;

                if (i == keyArr.length - 1 || keyArr[i+1].slice(5, 7) !== tempMonth) {
                    tempMonth = (i == keyArr.length - 1) ? keyArr[i].slice(5, 7) : keyArr[i+1].slice(5, 7);
                    var tempMKey = keyArr[i].slice(0, 7);
                    var tempDays = keyArr[i].slice(-2);
                    singleMonth[tempMKey] = Math.floor(mcount / tempDays);
                    mcount = 0;
                }
            }
        }
        week[key] = singleWeek;
        month[key] = singleMonth;
        singleWeek = {};
        singleMonth = {};
    }
    // 处理好的数据存到 chartData 中
    chartData.day = aqiSourceData;
    chartData.week = week;
    chartData.month = month;
    renderChart();
}

/**
 * 初始化函数
 */
function init() {
    initGraTimeForm();
    initCitySelector();
    initAqiChartData();
}

init()

效果展示

到了这步,有点小绝望,心里有些打击。看来得继续加油,好好加油!

时间: 2024-10-14 07:03:20

任务十七:零基础JavaScript编码(五)的相关文章

零基础JavaScript编码(二)

任务目的 在上一任务基础上继续JavaScript的体验 学习JavaScript中的if判断语法,for循环语法 学习JavaScript中的数组对象 学习如何读取.处理数据,并动态创建.修改DOM中的内容 任务描述 参考以下示例代码,页面加载后,将提供的空气质量数据数组,按照某种逻辑(比如空气质量大于60)进行过滤筛选,最后将符合条件的数据按照一定的格式要求显示在网页上 <!DOCTYPE html> <html> <head> <meta charset=&

零基础JavaScript编码(一)

任务目的 JavaScript初体验 初步明白JavaScript的简单基本语法,如变量.函数 初步了解JavaScript的事件是什么 初步了解JavaScript中的DOM是什么 任务描述 参考以下示例代码,补充其中的JavaScript功能,完成一个JavaScript代码的编写 本任务完成的功能为:用户可以在输入框中输入任何内容,点击"确认填写"按钮后,用户输入的内容会显示在"您输入的值是"文字的右边 <!DOCTYPE html> <ht

任务十六:零基础JavaScript编码(四)

面向人群: 零基础或初学者 难度: 中等 重要说明 百度前端技术学院的课程任务是由百度前端工程师专为对前端不同掌握程度的同学设计.我们尽力保证课程内容的质量以及学习难度的合理性,但即使如此,真正决定课程效果的,还是你的每一次思考和实践. 课程多数题目的解决方案都不是唯一的,这和我们在实际工作中的情况也是一致的.因此,我们的要求不仅仅是实现设计稿的效果,更是要多去思考不同的解决方案,评估不同方案的优劣,然后使用在该场景下最优雅的方式去实现.那些最终没有被我们采纳的方案,同样也可以帮助我们学到很多知

任务十三:零基础JavaScript编码(一)

任务目的 JavaScript初体验 初步明白JavaScript的简单基本语法,如变量.函数 初步了解JavaScript的事件是什么 初步了解JavaScript中的DOM是什么 任务描述 参考以下示例代码,补充其中的JavaScript功能,完成一个JavaScript代码的编写 本任务完成的功能为:用户可以在输入框中输入任何内容,点击"确认填写"按钮后,用户输入的内容会显示在"您输入的值是"文字的右边 <!DOCTYPE html> <ht

salesforce 零基础学习(五十二)Trigger使用篇(二)

第十七篇的Trigger用法为通过Handler方式实现Trigger的封装,此种好处是一个Handler对应一个sObject,使本该在Trigger中写的代码分到Handler中,代码更加清晰. 十七篇链接:salesforce 零基础学习(十七)Trigger用法 有的时候对于sObject的trigger处理复杂的情况下,比如一个sObject的before update要实现功能1,2.....n功能情况下,Handler中需要在before update写实现功能1--n的代码.然而

salesforce 零基础学习(五十三)多个文件生成一个zip文件(使用git上封装的代码)

此篇参考git代码:https://github.com/pdalcol/Zippex 学习salesforce可以访问一个朋友的网站:https://www.xgeek.net 首先感谢git上提供代码的大神,学到了新的知识.salesforce不像java提供生成Zip文件的类库,通过git上copy的代码可以实现此功能,具体的使用方法以及API可以查看上方git链接. 概述:实例模拟三个上传组件,加上一个下载Zip包按钮,本地选择需要上传的文件,点击按钮后便会下载成一个压缩文件,压缩文件中

任务一:零基础HTML编码练习

任务目的 了解HTML的定义.概念.发展简史 掌握常用HTML标签的含义.用法 能够基于设计稿来合理规划HTML文档结构 理解语义化,合理地使用HTML标签来构建页面 任务描述:完成一个HTML页面代码编写(不写CSS,不需要关注样式,只关注文档结构),详情看下图(可右键复制图片到本地自行练习): 任务注意事项 只需要完成HTML代码编写,不需要写CSS 示例图仅为参考,不需要完全实现一致,其中的图片.文案均可自行设定 尽可能多地尝试更多的HTML标签 任务完成及总结: 问题1:标题元素无法正确

零基础HTML编码学习笔记

任务目的 了解HTML的定义.概念.发展简史 掌握常用HTML标签的含义.用法 能够基于设计稿来合理规划HTML文档结构 理解语义化,合理地使用HTML标签来构建页面 任务描述:完成一个HTML页面代码编写(不写CSS,不需要关注样式,只关注文档结构) 任务注意事项 只需要完成HTML代码编写,不需要写CSS 示例图仅为参考,不需要完全实现一致,其中的图片.文案均可自行设定 尽可能多地尝试更多的HTML标签 总结 一.涉及HTML标签 1.<header>标签(Header Element):

salesforce 零基础学习(五十五)java通过SOAP方式定时访问某个文件然后插入到sObject中

项目源码:https://github.com/zhangyueqidlmu/SOAP-Access-SFDC.git 项目背景:salesforce端相关数据需要其他系统提供,其他系统可以提供相关数据的CSV文件.使用SOAP方式java代码定时将文件读取解析并插入到salesforce相关数据表中. 项目实现功能:固定时间访问指定目录下的csv文件,解析csv文件到List中并将records插入到Goods(自定义的sObject)表中,并将此定时任务放到计算机的服务中,防止误操作关闭了命