本例項針對的具體應用行情是我需要定時從資料庫中讀取某商品價格,然後以圖形顯示在網頁上,類似於股票中的交易品種價格走勢圖.
我使用的是asp.net,結合jQuery中的Highcharts外掛實現,該外掛可以支援很多型別的圖形,但都是靜態的,提供的例項都需要改造,有興趣的朋友可以去Highcharts官網看看(http://www.highcharts.com/),裡面提供了很多的Demo,說實在的要實現我的需求,更應該使用Highstock,但是看了Highcharts的dynamic-update例項,也可以實現我的需求介面更加簡潔些,所以本文采用的是Highcharts中dynamic-update模型,圖形型別是spline最終實現的效果貼圖如下(品旗金這個品種的價格是10秒種更新一次的,每10秒對線狀圖形加一個點):
實現步聚:
用vs新建一web網站,新建asp.net頁面DynamicUpdate.aspx,頁面程式碼如下:
- <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="DynamicUpdate.aspx.cs"
- Inherits="WebImg.DynamicUpdate" %>
- <!DOCTYPE HTML>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
- <title>動態顯示價格圖例</title>
- <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
- <script type="text/javascript">
- $(function () {
- $(document).ready(function () {
- Highcharts.setOptions({
- global: {
- useUTC: false
- }
- });
- var chart;
- chart = new Highcharts.Chart({
- chart: {
- renderTo: 'container',
- type: 'spline',
- marginRight: 10,
- events: {
- load: function () {
- // set up the updating of the chart each second
- var series = this.series[0];
- setInterval(function () {
- var randomCode = parseInt(Math.random() * 10000);
- var oldrandomCode = parseInt(Math.random() * 10000);
- $.ajax({
- url: "ajaxhandler/dataupdate.ashx?" + randomCode + "=" + oldrandomCode + "&flag=1",
- type: "get",
- dataType: "json",
- success: function (data, textStatus, XMLHttpRequest) {
- var ctime = new Date();
- ctime.setTime(parseInt(data.rows[0].times));
- var x = ctime.getTime(), // current time
- y = data.rows[0].price * 200;
- series.addPoint([x, y], true, true);
- },
- error: function () { }
- });
- }, 10000);
- }
- }
- },
- title: {
- text: '品旗撮合交易市場品種行情'
- },
- xAxis: {
- title: {
- text: '時間'
- },
- type: 'datetime',
- tickPixelInterval: 150,
- labels:{formatter:function(){
- var vDate = new Date(this.value);
- return vDate.getHours()+":"+vDate.getMinutes()+":"+vDate.getSeconds();
- }}
- },
- yAxis: {
- title: {
- text: '價格'
- },
- plotLines: [{
- value: 0,
- width: 1,
- color: '#808080'
- }]
- },
- tooltip: {
- formatter: function () {
- return '<b>' + this.series.name + '</b><br/>' +
- Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) + '<br/>' +
- Highcharts.numberFormat(this.y, 2);
- }
- },
- legend: {
- enabled: false
- },
- exporting: {
- enabled: false
- },
- credits:{
- text:'品旗金屬交易市場',
- url:'http://www.inv6.com'
- },
- series: [{
- name: '品旗金(GOLD)',
- data: (function () {
- var data = [],
- i;
- var jsonData = <%= jsonstr %>;
- for (i = -19; i <= 0; i++) {
- var ctime = new Date();
- ctime.setTime(parseInt(jsonData.rows[i+19].time1));
- data.push({
- x: ctime.getTime(),
- y: jsonData.rows[i + 19].price * 200
- });
- }
- return data;
- })()
- }]
- });
- });
- });
- </script>
- </head>
- <body>
- <script src="http://code.highcharts.com/highcharts.js"></script>
- <script src="http://code.highcharts.com/modules/exporting.js"></script>
- <div id="container" style="min-width: 400px; height: 400px; margin: 0 auto">
- </div>
- </body>
- </html>
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="DynamicUpdate.aspx.cs" Inherits="WebImg.DynamicUpdate" %> <!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>動態顯示價格圖例</title> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> <script type="text/javascript"> $(function () { $(document).ready(function () { Highcharts.setOptions({ global: { useUTC: false } }); var chart; chart = new Highcharts.Chart({ chart: { renderTo: 'container', type: 'spline', marginRight: 10, events: { load: function () { // set up the updating of the chart each second var series = this.series[0]; setInterval(function () { var randomCode = parseInt(Math.random() * 10000); var oldrandomCode = parseInt(Math.random() * 10000); $.ajax({ url: "ajaxhandler/dataupdate.ashx?" + randomCode + "=" + oldrandomCode + "&flag=1", type: "get", dataType: "json", success: function (data, textStatus, XMLHttpRequest) { var ctime = new Date(); ctime.setTime(parseInt(data.rows[0].times)); var x = ctime.getTime(), // current time y = data.rows[0].price * 200; series.addPoint([x, y], true, true); }, error: function () { } }); }, 10000); } } }, title: { text: '品旗撮合交易市場品種行情' }, xAxis: { title: { text: '時間' }, type: 'datetime', tickPixelInterval: 150, labels:{formatter:function(){ var vDate = new Date(this.value); return vDate.getHours()+":"+vDate.getMinutes()+":"+vDate.getSeconds(); }} }, yAxis: { title: { text: '價格' }, plotLines: [{ value: 0, width: 1, color: '#808080' }] }, tooltip: { formatter: function () { return '<b>' + this.series.name + '</b><br/>' + Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) + '<br/>' + Highcharts.numberFormat(this.y, 2); } }, legend: { enabled: false }, exporting: { enabled: false }, credits:{ text:'品旗金屬交易市場', url:'http://www.inv6.com' }, series: [{ name: '品旗金(GOLD)', data: (function () { var data = [], i; var jsonData = <%= jsonstr %>; for (i = -19; i <= 0; i++) { var ctime = new Date(); ctime.setTime(parseInt(jsonData.rows[i+19].time1)); data.push({ x: ctime.getTime(), y: jsonData.rows[i + 19].price * 200 }); } return data; })() }] }); }); }); </script> </head> <body> <script src="http://code.highcharts.com/highcharts.js"></script> <script src="http://code.highcharts.com/modules/exporting.js"></script> <div id="container" style="min-width: 400px; height: 400px; margin: 0 auto"> </div> </body> </html>
Highcharts的屬性中renderTo表示顯示容器,
events表示容器需要註冊的事件,其中的load表示在載入完成之後發生,這裡在load中設定了一個js計時器,10秒鐘發生一次,裡面的程式碼就是通過jQuery 中的ajax向跟DynamicUpdate.aspx頁面在同一根目錄下的ajaxhandler資料夾的dataupdate.ashx檔案請求最新一條的品旗金(GOLD)品種的價格資料,這裡在ajax的url中為何要加randomCode + "=" + oldrandomCode是因為加一個隨機數可以避免快取,而flag=1則是因為我的dataupdate.ashx檔案要接受多個不同的ajax的請求,所以用flag區分一下
xAxis表示針對容器的x軸進行定義的的屬性合集,type表示顯示的文字型別,可選,這裡我填寫的是時間型別,這裡注意例項預設採用的是GMT時間,也可以使用UTC時間,但我們一般都採用的是北京時間,(GMT or UTC)+8小時 = 北京時間,因此當我們用ajax獲取的時間是北京時間時,應在小時上減去8小時(這裡我還要分享一條經驗,如何將伺服器時間轉換為.getTime()方法可以使用的js時間,那就是將伺服器時間減去1970-1-1,將剩下的天數轉換為毫秒數,然後在js中通過setTime方法給新初始化的時間賦值,我發現js中直接用new Date(年,月,日,時,分,秒,毫秒)的形式初始化一個js時間用getTime()獲取到的結果是不正確的,至於為什麼要減去1970-1-1,這是因為getTime()方法的定義就是獲取從當前時間從1970-1-1後的毫秒數),當x軸顯示的不是時間時或需要自己定義時,也可以通過categories屬性來定義,tickPixelInterval表示x軸的密度,labels則用來格式化x軸的顯示格式
yAxis表示針對容器的y軸進行定義的屬性合集,大致與x軸的屬性是一樣的,但是在Highcharts中是無法通過categories定義y軸的固定值的,Highcharts的y軸是根據給出的座標點資料自動生成的,這取決於series屬性的data子屬性,比如當你給data所賦值的最大值是300,最小值是100,那麼y軸的顯示將從100到300之間,或者你也可以設定yAxis的max或min屬性
series表示顯示在容器中所有曲線的合集,這裡我只顯示一條曲線,name表示曲線的名稱,data表示該條曲線一系列座標點的集合,x在前,y在後,它是一個js陣列,本例中由於x軸顯示的是時間,因此須將陣列物件的x屬性設定為時間,但是Highcharts中並不是直接將時間賦給x軸,而是將從1970-1-1到某個時間之間的毫秒數來賦給x軸表示這個時間,所以必須用getTime()方法,y軸座標點的形式必須是 y = 較小數字 * 整數的形式,也沒有摸透Highcharts為何必須這樣,由於本例項中品種的價格資料一般是一般多左右,所以只好在獲取資料時除以200,然後再給y軸賦值時再乘以200。
頁面程式碼中的<%= jsonstr %>是我需要從伺服器獲取的初始資料,以初始化圖形,頁面的cs程式碼如下(DynamicUpdate.aspx.cs):
- public string jsonstr = "";
- protected void Page_Load(object sender, EventArgs e)
- {
- getData();
- }
- private void getData()
- {
- DataTable dtPrice = SQLDBHelper.ExecuteTable("select top 20 TMPCode,TMPTime,TMPPrice from TabMerPrice with(nolock) order by TMPTime desc");
- string json = "{\"rows\":[";
- for (int i = (dtPrice.Rows.Count-1); i >= 0; i--)
- {
- json += "{\"time1\":\"" + (Convert.ToDateTime(dtPrice.Rows[i]["TMPTime"]).AddHours(-8) - new DateTime(1970, 1, 1)).TotalMilliseconds + "\",\"price\":\"" + (Convert.ToDecimal(dtPrice.Rows[i]["TMPPrice"])/200) + "\"},";
- }
- json = json.TrimEnd(',');
- json += "]}";
- jsonstr = json;
- }
public string jsonstr = ""; protected void Page_Load(object sender, EventArgs e) { getData(); } private void getData() { DataTable dtPrice = SQLDBHelper.ExecuteTable("select top 20 TMPCode,TMPTime,TMPPrice from TabMerPrice with(nolock) order by TMPTime desc"); string json = "{\"rows\":["; for (int i = (dtPrice.Rows.Count-1); i >= 0; i--) { json += "{\"time1\":\"" + (Convert.ToDateTime(dtPrice.Rows[i]["TMPTime"]).AddHours(-8) - new DateTime(1970, 1, 1)).TotalMilliseconds + "\",\"price\":\"" + (Convert.ToDecimal(dtPrice.Rows[i]["TMPPrice"])/200) + "\"},"; } json = json.TrimEnd(','); json += "]}"; jsonstr = json; }
其中TabMerPrice表是品種價格資訊表,TMPTime時間,TMPPrice價格,TMPTime的時間間隔是十秒,我用資料庫作業生成該表的記錄,十秒鐘發生一次
AddHours(-8)是為了將時間轉換為北京時間,生成的資料格式是json格式
dataupdate.ashx程式碼如下:
- public void ProcessRequest(HttpContext context)
- {
- string flag = context.Request.QueryString["flag"].ToString();
- switch (flag)
- {
- case "1"://獲取品種當前價格
- GetMerPrice(context);
- break;
- }
- }
- private void GetMerPrice(HttpContext context)
- {
- context.Response.Clear();
- context.Response.Buffer = true;
- context.Response.ContentType = "application/json";
- context.Response.ContentEncoding.GetBytes("utf-8");
- DataTable dtPrice = SQLDBHelper.ExecuteTable("select top 1 TMPCode,TMPTime,TMPPrice from TabMerPrice with(nolock) order by TMPTime desc");
- string json = "{\"rows\":[";
- json += "{\"times\":\"" + (Convert.ToDateTime(dtPrice.Rows[0]["TMPTime"]).AddHours(-8) - new DateTime(1970, 1, 1)).TotalMilliseconds + "\",\"price\":\"" + (Convert.ToDecimal(dtPrice.Rows[0]["TMPPrice"]) / 200) + "\"}";
- json = json.TrimEnd(',');
- json += "]}";
- context.Response.Write(json);
- context.Response.Flush();
- context.Response.End();
- }