使用Echarts實現動態曲線圖表

最近作的一個在線氣象觀測網站要實現一個需求:使用圖表展現最近五天溫溼度等氣象要素的曲線變化javascript

具體效果參考:http://www.weatherobserve.com/showInfoIndex.jsphtml

圖示以下(2016-5-25日的數據):java

無標題

下面就詳述一下實現過程吧(注:相較於原網頁我隱去了不少內容,本實現過程就只專一於Echarts圖表實現)jquery

 

一:web

HTML頁面部分,代碼以下:ajax

複製代碼
<!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">   <!-- 在IE運行最新的渲染模式 -->
        <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>

        <!-- 顯示Echarts圖表 -->
        <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}<br/><font color=#FF3333>&nbsp;●&nbsp;</font>{a0} : {c0} ℃ ' + 
                               '<br/><font color=#53FF53>●&nbsp;</font>{a1} : {c1} % ' +          
                               '<br/><font color=#68CFE8>&nbsp;●&nbsp;</font>{a3} : {c3} mm ' +
                               '<br/><font color=#FFDC35>&nbsp;●&nbsp;</font>{a4} : {c4} m/s ' +
                               '<br/><font color=#B15BFF>&nbsp;&nbsp;&nbsp;&nbsp;●&nbsp;</font>{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>
複製代碼

 

二:sql

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>BlogExample</display-name>

    <servlet>
        <servlet-name>ShowInfoIndexServlet</servlet-name>
        <servlet-class>EchartsExample.ShowInfoIndexServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>ShowInfoIndexServlet</servlet-name>
        <url-pattern>/ShowInfoIndexServlet</url-pattern>
    </servlet-mapping>
  
</web-app>
複製代碼

關於ShowInfoIndexServlet,簡單說一下請求-響應中間的過程:apache

客戶端發送圖表請求給Servlet,Servlet接收到請求後先獲取客戶端請求查看的氣象站名稱,而後從數據庫(SqlServer2005 Express版)中獲取最近五天內該氣象站全部的採集數據(裝在List中),再用Gson工具將該List轉換成Json對象返回給客戶端,客戶端接收到返回的Json對象後對其進行解析並將相應數據填入Echarts中,而後做顯示;json

其中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<Record> records = new ArrayList<Record>();    //用一個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;
    }

    /**
     * 設置雨量;
     * @param rain 待設置雨量值
     */
    public void setRain(String rain) {
        this.rain = rain;
    }

    /**
     * 獲取風向;
     * @return 風向值
     */
    public String getWin_dir() {
        return win_dir;
    }

    /**
     * 設置風向;
     * @param win_dir 待設置風向值
     */
    public void setWin_dir(String win_dir) {
        this.win_dir = win_dir;
    }

    /**
     * 獲取風速;
     * @return 風速值
     */
    public String getWin_sp() {
        return win_sp;
    }

    /**
     * 設置風向;
     * @param win_sp 待設置風向值
     */
    public void setWin_sp(String win_sp) {
        this.win_sp = win_sp;
    }

    /**
     * 獲取觀測日期;
     * @return 觀測日期
     */
    public Timestamp getDate() {
        return date;
    }

    /**
     * 設置觀測日期; 
     * @param date 觀測日期值
     */
    public void setDate(Timestamp date) {
        this.date = date;
    }

    
}
複製代碼

 

DBUitl類(數據庫工具類)代碼以下:

複製代碼
package EchartsExample;


import java.sql.*;

import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolProperties;

/**
 * 數據庫工具類(採用了tomcat jdbc pool)
 * @author zhong
 *
 */
public class DBUtil {
    
    private static DataSource ds;
    
    static {
        //配置tomcat jdbc pool (鏈接池)
        PoolProperties p = new PoolProperties();
        p.setUrl("jdbc:sqlserver://localhost:1433; DatabaseName=weather");    //設置鏈接的url
        p.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");    //載入數據庫驅動
        p.setUsername("sa");    //用於遠程鏈接的用戶名
        p.setPassword("2003NianDeDiYiChangXue");    //密碼
        p.setJmxEnabled(true);
        p.setTestWhileIdle(false);
        p.setTestOnBorrow(true);
        p.setValidationQuery("SELECT 1");
        p.setTestOnReturn(false);
        p.setValidationInterval(30000);
        p.setTimeBetweenEvictionRunsMillis(30000);
        p.setMaxActive(100);
        p.setInitialSize(10);
        p.setMaxWait(10000);
        p.setRemoveAbandonedTimeout(60);
        p.setMinEvictableIdleTimeMillis(30000);
        p.setMinIdle(10);
        p.setLogAbandoned(true);
        p.setRemoveAbandoned(true);
        p.setJdbcInterceptors(
          "org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"+
          "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");
        ds = new DataSource();
        ds.setPoolProperties(p);
    }
    
    private DBUtil() {}
    
    /**
     * 獲取一個數據庫鏈接(Connection);
     * @return Database Connection
     */
    public static Connection getConnection() {
        Connection conn = null;
        
        try {            
            conn = ds.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        
        return conn;
    }
    
    /**
     * 關閉傳入的Connection;
     * @param conn 待關閉的Connection
     */
    public static void close(Connection conn) {
        try {
            if (conn != null) {
                conn.close();
                conn = null;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 關閉傳入的Statement;
     * @param stmt    待關閉的Statement
     */
    public static void close(Statement stmt) {
        try {
            if (stmt != null) {
                stmt.close();
                stmt = null;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    
    /**
     * 關閉傳入的ResultSet;
     * @param rs    待關閉的ResultSet
     */
    public static void close(ResultSet rs) {
        try {
            if (rs != null) {
                rs.close();
                rs = null;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    
}
複製代碼

 

——————————————————————————我是小小分割線————————————————————————————————————

關於遠程鏈接(包括使用Eclipse鏈接)SqlServer2005我再多嘴兩句:

當確認鏈接的URL,驅動加載,用戶名,密碼都配置正確時,仍然拋出 java.lang.NullPointerException 的話,請打開開始菜單Microsoft SQL Server 2005軟件目錄下的SQL Server配置管理器:

①:啓用SQL Server 2005網絡配置 下的 SQLEXPRESS協議 內的 TCP/IP 協議,並右鍵TCP/IP協議選擇屬性,確保IP地址一欄最末的TCP端口爲1433,具體見下圖

無標題

 

②:啓用 SQL Native Client配置 下的 客戶端協議 內的 TCP/IP 協議,並右鍵查看TCP/IP 屬性,確保端口爲1433,具體見下圖

無標題2

 

③:從新啓動 SQL Server 2005服務 下的 SQL Server服務,詳情見下圖

無標題3

至此,應該就解決了java.lang.NullPointerException這個錯誤了。

————————————————————————我是小小分割線————————————————————————————————————

讓咱們再回到原來的Echarts圖表顯示過程上,你能夠試着在後臺打印看看轉換出的Json字符串,關於Json的使用這裏我再也不多言解釋,具體可參考簡單易懂的官方教程:http://www.w3school.com.cn/json/

 

最後再貼一下實現效果吧:

無標題44

相關文章
相關標籤/搜索