站内搜索

使用Echarts实现动态曲线图表

最近做的一个在线气象观测网站要实现一个需求:使用图表展示最近五天温湿度等气象要素的曲线变化

具体效果参考:http://www.weatherobserve.com/showInfoIndex.jsp

图示如下(2016-5-25日的数据):

无标题

下面就详述一下实现过程吧(注:相较于原网页我隐去了很多内容,本实现过程就只专注于Echarts图表实现)

一:

HTML页面部分,代码如下:

DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html lang="zh-CN">    <head>            <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">        <meta http-equiv="X-UA-Compatible" content="IE=edge">           <meta name="viewport" content="width=device-width, initial-scale=1">            <meta name="Author" content="Dreamer-1.">                        <script type="text/javascript" src="js/jquery-1.12.3.min.js">script>        <script type="text/javascript" src="js/echarts.common.min.js">script>        <title>- 观测数据 -title>    head>    <body>                <div style="height:410px;min-height:100px;margin:0 auto;" id="main">div>                                                            <script type="text/javascript">                    // 基于准备好的dom,初始化echarts实例        var myChart = echarts.init(document.getElementById('main'));        // 指定图表的配置项和数据        var option = {            title: {    //图表标题                text: '过去五天数据图表'            },            tooltip: {                trigger: 'axis', //坐标轴触发提示框,多用于柱状、折线图中                /*                 控制提示框内容输出格式                formatter: '{b0}
{a0} : {c0} ℃ ' + '
{a1} : {c1} % ' + '
{a3} : {c3} mm ' + '
{a4} : {c4} m/s ' + '
{a2} : {c2} hPa '
*/ }, dataZoom: [ { type: 'slider', //支持鼠标滚轮缩放 start: 0, //默认数据初始缩放范围为10%到90% end: 100 }, { type: 'inside', //支持单独的滑动条缩放 start: 0, //默认数据初始缩放范围为10%到90% end: 100 } ], legend: { //图表上方的类别显示 show:true, data:['温度(℃)','湿度(%)','雨量(mm)','风速(m/s)','压强(hPa)'] }, color:[ '#FF3333', //温度曲线颜色 '#53FF53', //湿度曲线颜色 '#B15BFF', //压强图颜色 '#68CFE8', //雨量图颜色 '#FFDC35' //风速曲线颜色 ], toolbox: { //工具栏显示 show: true, feature: { saveAsImage: {} //显示“另存为图片”工具 } }, xAxis: { //X轴 type : 'category', data : [] //先设置数据值为空,后面用Ajax获取动态数据填入 }, yAxis : [ //Y轴(这里我设置了两个Y轴,左右各一个) { //第一个(左边)Y轴,yAxisIndex为0 type : 'value', name : '温度', /* max: 120, min: -40, */ axisLabel : { formatter: '{value} ℃' //控制输出格式 } }, { //第二个(右边)Y轴,yAxisIndex为1 type : 'value', name : '压强', scale: true, axisLabel : { formatter: '{value} hPa' } } ], series : [ //系列(内容)列表 { name:'温度(℃)', type:'line', //折线图表示(生成温度曲线) symbol:'emptycircle', //设置折线图中表示每个坐标点的符号;emptycircle:空心圆;emptyrect:空心矩形;circle:实心圆;emptydiamond:菱形 data:[] //数据值通过Ajax动态获取 }, { name:'湿度(%)', type:'line', symbol:'emptyrect', data:[] }, { name:'压强(hPa)', type:'line', symbol:'circle', //标识符号为实心圆 yAxisIndex: 1, //与第二y轴有关 data:[] }, { name:'雨量(mm)', type:'bar', //柱状图表示 //barMinHeight: 10, //柱条最小高度,可用于防止某数据项的值过小而影响交互 /* label: { //显示值 normal: { show: true, position: 'top' } }, */ data:[] }, { name:'风速(m/s)', type:'line', symbol:'emptydiamond', data:[] } ] }; myChart.showLoading(); //数据加载完之前先显示一段简单的loading动画 var tems=[]; //温度数组(存放服务器返回的所有温度值) var hums=[]; //湿度数组 var pas=[]; //压强数组 var rains=[]; //雨量数组 var win_sps=[]; //风速数组 var dates=[]; //时间数组 $.ajax({ //使用JQuery内置的Ajax方法 type : "post", //post请求方式 async : true, //异步请求(同步请求将会锁住浏览器,用户其他操作必须等待请求完成才可以执行) url : "ShowInfoIndexServlet", //请求发送到ShowInfoIndexServlet处 data : {name:"A0001"}, //请求内包含一个key为name,value为A0001的参数;服务器接收到客户端请求时通过request.getParameter方法获取该参数值 dataType : "json", //返回数据形式为json success : function(result) { //请求成功时执行该函数内容,result即为服务器返回的json对象 if (result != null && result.length > 0) { for(var i=0;i<result.length;i++){ tems.push(result[i].tem); //挨个取出温度、湿度、压强等值并填入前面声明的温度、湿度、压强等数组 hums.push(result[i].hum); pas.push(result[i].pa); rains.push(result[i].rain); win_sps.push(result[i].win_sp); dates.push(result[i].dateStr); } myChart.hideLoading(); //隐藏加载动画 myChart.setOption({ //载入数据 xAxis: { data: dates //填入X轴数据 }, series: [ //填入系列(内容)数据 { // 根据名字对应到相应的系列 name: '温度', data: tems }, { name: '湿度', data: hums }, { name: '压强', data: pas }, { name: '雨量', data: rains }, { name: '风速', data: win_sps } ] }); } else { //返回的数据为空时显示提示信息 alert("图表请求数据为空,可能服务器暂未录入近五天的观测数据,您可以稍后再试!"); myChart.hideLoading(); } }, error : function(errorMsg) { //请求失败时执行该函数 alert("图表请求数据失败,可能是服务器开小差了"); myChart.hideLoading(); } }) myChart.setOption(option); //载入图表 script> body>html>

二:

Servlet部分,客户端请求提交到 ShowInfoIndex 处,先在 web.xml 里配置一下Servlet映射:

xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" version="3.1">  <display-name>BlogExampledisplay-name>    <servlet>        <servlet-name>ShowInfoIndexServletservlet-name>        <servlet-class>EchartsExample.ShowInfoIndexServletservlet-class>    servlet>    <servlet-mapping>        <servlet-name>ShowInfoIndexServletservlet-name>        <url-pattern>/ShowInfoIndexServleturl-pattern>    servlet-mapping>  web-app>

关于ShowInfoIndexServlet,简单说一下请求-响应中间的过程:

客户端发送图表请求给Servlet,Servlet接收到请求后先获取客户端请求查看的气象站名称,然后从数据库(SqlServer2005 Express版)中获取最近五天内该气象站所有的采集数据(装在List中),再用Gson工具将该List转换成Json对象返回给客户端,客户端接收到返回的Json对象后对其进行解析并将相应数据填入Echarts中,然后作显示;

其中Record.java是只对外提供get/set方法的用于封装数据的普通实体类,DBUtil.java是JDBC方式下专门提供Connection、Statement、ResultSet等的数据库工具类。

(原本的连接数据库并获取数据过程需经过业务逻辑层与数据访问层,较为复杂,这里隐去这两层,直接在Servlet内连接数据库并拿取数据)

Ps:墙裂建议使用PreparedStatement进行参数化查询,这样可以有效避免SQL注入!

ShowInfoIndexServlet代码如下:

package EchartsExample;import java.io.IOException;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.ResultSet;import java.sql.SQLException;import java.text.SimpleDateFormat;import java.util.*;import javax.servlet.ServletException;import javax.servlet.http.HttpServlet;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import com.google.gson.Gson;/** * 响应观测记录展示页的Echarts图表数据请求(使用json格式返回客户端需要的数据) * @author zhong * */public class ShowInfoIndexServlet extends HttpServlet {    /**     *      */    private static final long serialVersionUID = 1L;    @Override    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {        doPost(req,resp);    }    @Override    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {        request.setCharacterEncoding("UTF-8");    //设定客户端提交给servlet的内容按UTF-8编码        response.setCharacterEncoding("UTF-8");    //设定servlet传回给客户端的内容按UTF-8编码        response.setContentType("text/html;charset=UTF-8");    //告知浏览器用UTF-8格式解析内容                        String name = request.getParameter("name");    //获取台站名参数                //获取当天在内的五天以前的0点格式字符串(用于数据库查询)        Calendar  cal = Calendar.getInstance();        cal.add(Calendar.DATE, -4);        //获取当天在内的五天以前的日期时间        SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy-MM-dd 00:00:00");    //设定日期格式        String fiveDaysAgoStr = sdf1.format(cal.getTime());    //将五天前的日期时间按指定格式转换成字符串                        //获取当前时间并将其转换成指定格式的字符串(用于数据库查询)        Date now = new Date();          SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");          String nowStr = sdf2.format(now);  //System.out.println(nowStr);                              //======================================连接数据库操作============================================================================================                /*         * 连接数据库并获取五天内该名称的气象站的所有采集数据         */        List records = new ArrayList();    //用一个ArrayList来盛装封装了各气象数据的对象                Connection conn = null;        PreparedStatement pstmt = null;        ResultSet rs = null;                try {            conn = DBUtil.getConnection();    //获取与数据库的连接            String sql = "select * from alldata where data_taizhan_num = ? and data_date >= ? and data_date <= ? order by data_date asc";    //初始化SQL查询语句            pstmt = conn.prepareStatement(sql);    //创建preparedStatement语句对象                pstmt.setString(1, name);    //设定查询参数            pstmt.setString(2, fiveDaysAgoStr);            pstmt.setString(3, nowStr);            rs = pstmt.executeQuery();    //获取查询到的结果集            while (rs.next()) {                //封装Record对象                Record r = new Record();                r.setTaizhan_num(rs.getString(1));                r.setDate(rs.getTimestamp(2));                r.setTem(rs.getString(3));                r.setHum(rs.getString(4));                r.setPa(rs.getString(5));                r.setRain(rs.getString(6));                r.setWin_dir(rs.getString(7));                r.setWin_sp(rs.getString(8));                                //将时间转换成给定格式便于echarts的X轴日期坐标显示                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");                             String str = sdf.format(rs.getTimestamp(2));                r.setDateStr(str);//System.out.println(r.getTem()+" | "+r.getHum()+" | "+r.getPa()+" | "+r.getRain()+" | "+r.getWin_dir()+" | "+r.getWin_sp());                                                            records.add(r);        //将封装好的Record对象放入列表容器中            }                    } catch (SQLException e) {            System.out.println("查询出错,操作未完成!");            e.printStackTrace();        } finally {            //查询结束后释放资源            DBUtil.close(rs);            DBUtil.close(pstmt);            DBUtil.close(conn);        }    //======================================连接数据库操作(完)============================================================================================                                       //将list中的对象转换为Json格式的数组        Gson gson = new Gson();                            String json = gson.toJson(records);            //System.out.println(json);                //将json数据返回给客户端        response.setContentType("text/html; charset=utf-8");        response.getWriter().write(json);    }}

alldata表部分数据截图:

数据库截图

Record类代码如下:

package EchartsExample;import java.sql.*;/** * 封装气象数据信息 * @author zhong * */public class Record {        private String taizhan_num;    //台站名    private String tem;            //温度    private String hum;            //湿度    private String pa;            //压强    private String rain;        //雨量    private String win_dir;        //风向    private String win_sp;        //风速    private String dateStr;        //观测日期(用于Echarts显示格式)    private Timestamp date;        //观测日期(原始格式)        /**     * 获取观测日期(用于echarts图表展示);     * @return 观测日期值     */    public String getDateStr() {        return dateStr;    }    /**     * 设置观测日期(用于echarts图表展示);     * @param dateStr 待设置观测日期值     */    public void setDateStr(String dateStr) {        this.dateStr = dateStr;    }        /**     * 获取产生该观测记录的台站名称;     * @return 台站名称     */    public String getTaizhan_num() {        return taizhan_num;    }    /**     * 设置产生该观测记录的台站名称;     * @param taizhan_num 待设置台站名称     */    public void setTaizhan_num(String taizhan_num) {        this.taizhan_num = taizhan_num;    }    /**     * 获取温度;     * @return 温度值     */    public String getTem() {        return tem;    }    /**     * 设置温度;     * @param tem 待设置温度值     */    public void setTem(String tem) {        this.tem = tem;    }    /**     * 获取湿度;     * @return 湿度值      */    public String getHum() {        return hum;    }    /**     * 设置湿度;     * @param hum 待设置湿度值     */    public void setHum(String hum) {        this.hum = hum;    }    /**     * 获取压强;     * @return 压强值     */    public String getPa() {        return pa;    }    /**     * 设置压强;     * @param pa 待设置压强值     */    public void setPa(String pa) {        this.pa = pa;    }    /**     * 获取雨量;     * @return 雨量值     */    public String getRain() {        return rain;    }    
  • 上一篇:学会九种web网站建设语言及工具视频教程
  • 下一篇:纯css3制作写轮眼开眼及进化过程