highstock实现股票分时
highchart学习网站
www.highcharts.com
http://www.hcharts.cn/docs/index.php
http://www.hcharts.cn/api/highstock.php
实现效果:
![](http://images0.cnblogs.com/blog2015/227236/201505/051938525481683.png)
传入数据:股票交易的时间早上9:30-11:30 下午13:00-15:00 对应的最新价、成交量、平均价
请求地址如下:
http://open.hundsun.com:8081/quote/v1/trend?prod_code=600570.SS&fields=last_px,business_amount,avg_px
数据格式如下:
{"data":{"trend":{"fields":["min_time","last_px","business_amount","avg_px"],"600570.SS":[[201505050930,115.800000,48400,115.990000],...}
技术难点:
1.刻度分隔问题:由于highstock的x轴是按照时间升序的,但是中间11:30到13:00无数据,故x与y轴刻度分隔问题,同时中间位11:30/13:00可见x轴坐标需要定制化?
在x与y坐标提供labels:{formatter:function(){return this.value;//这里改变}}和tickPositioner:function(){return array[]}来定制输出的标签和那些数据显示。
2.y轴左右两边问题,一般坐标轴只有1份或在左边或在右边,如何使y轴左右两边都有并且数据对应?
图表的右边的y轴,存的数据与图表左边y轴的一样,但是显示的时候labels:{}这里处理输出的值
3.基线问题:在0.00%处需要定制化一条基线如上图蓝色的基线
利用var chart = $(DIVID).highcharts();
chart.removePlotLine();
chart.addPlotLine({});
4.标注问题:如上图 112 13:02 -5.08%的显示
采用标志带:
chart.removePlotBand();
chart.addPlotBand({});
5.手指触摸问题:本应用可实现上下整体拖动,左右十字线移动。
touchmove、touchstart事件的绑定
document.getElementById("line_map").removeEventListener("touchstart",createKlineChart.kline_touchstart,false);
document.getElementById("line_map").addEventListener("touchstart", createTrendChart.trend_touchstart);
document.getElementById("line_map").removeEventListener("touchmove",createKlineChart.kline_touchmove,false);
6:手指左右移动十字线跟随移动问题
首先判断手指斜向上角度大于45度就判断为上下移动,否则则判断手指左右移动。
当手指左右移动的时候捕获事件获取pagex,pageY针对父控件手指的x、y坐标,然后做映射
i=x/chart.width*data.length;
data.length与 chart.plotwidth宽度 对应i为平均分布在宽度chart.plotwidth上的数据,找到i之后就可以从data中取值data[i][0]x轴事件 data[i][1]y轴的值
代码:
需要引入highstock.js jquery.js
html
1 <div id="report" class="klineMap-report"></div> 2 <div class="kline_map" id="line_map" style="height: 200px;width: 100%" >
trend.js
1 var Trend_Url=js_lib.getTrendUrl(); 2 //http://open.hundsun.com:8081/quote/v1/trend?prod_code=600570.SS&fields=last_px,business_amount,avg_px 3 var Real_Url=js_lib.getCommonRealUrl(); 4 //http://open.hundsun.com:8081/quote/v1/real?en_prod_code=600570.SS&fields=open_px,preclose_px 5 var DIVID='#line_map'; 6 //接收个股代码 7 var STOCK_CODE = js_lib.getQueryStringByName("stock_code"); 8 /* 9 * 分时 10 */ 11 if(STOCK_CODE==""){ 12 STOCK_CODE="600570.SS"; 13 } 14 function clickTrend(obj){ 15 var price_param="en_prod_code="+STOCK_CODE+"&fields=open_px,preclose_px"; 16 js_lib.ajax(Real_Url,callbackReal, 'get',price_param,failCallback); 17 $(obj).parent().parent().children().each(function(){ 18 $(this).removeClass("hover"); 19 }); 20 $(obj).parent().addClass("hover"); 21 } 22 function clickTrend_Show(val){ 23 var jsonText = JSON.parse(val); 24 if(typeof(jsonText.error_info)!='undefined'){ 25 failCallback(); 26 return ; 27 } 28 var data=jsonText.data.trend; 29 data=data[STOCK_CODE]; 30 //画图 31 trendChart(DIVID,data); 32 } 33 //图表上的成交量第一条的数据红绿的判断 是根据昨日的收盘价preclose_px 和今日的最新价last_px进行对比 34 //同时获取的昨日收盘价 用于涨幅的计算 35 var isFirstLineColorflag=true; 36 //保存昨收数据 37 var yesterdayClose; 38 //可以获取今开 与昨收 39 function callbackReal(val){ 40 var jsonText = JSON.parse(val); 41 var price_data=jsonText.data.snapshot; 42 if(typeof(price_data[STOCK_CODE])=='undefined'){ 43 failCallback(); 44 return ; 45 } 46 //今开 47 var open_px=price_data[STOCK_CODE][2]; 48 //昨收 49 var preclose_px=price_data[STOCK_CODE][3]; 50 yesterdayClose=preclose_px; 51 isFirstLineColorflag=open_px>preclose_px?true:false; 52 //获取分时数据 53 var kline_params = "prod_code="+STOCK_CODE+"&fields=last_px,business_amount,avg_px"; 54 js_lib.ajax(Trend_Url, clickTrend_Show, 'get',kline_params,failCallback); 55 } 56 /* 57 * 5日 58 */ 59 function clickFiveDayTrend(obj){ 60 $(obj).parent().parent().children().each(function(){ 61 $(this).removeClass("hover"); 62 }); 63 $(obj).parent().addClass("hover"); 64 } 65 var avg_pxyAxisMin; 66 var avg_pxyAxisMax; 67 var percentageyAxisMin; 68 var percentageyAxisMax; 69 var volume_yAxisMin; 70 var volume_yAxisMax; 71 var red="#ff0000"; 72 var blue="#00a800"; 73 function trendChart(DIVID,data) 74 { 75 var ohlc = [], 76 volume = [],//昨日开盘价 77 i = 0; 78 //容错判断 79 if(data!=undefined&&data!=null&&data.length==0){ 80 failCallback(); 81 return; 82 } 83 // split the data set into ohlc and volume 84 //数据处理 85 for (i; i < data.length; i += 1) { 86 var dateUTC=getDateUTCOrNot(data[i][0],true); 87 var business_amount=data[i][2]; 88 var columnColor = red; 89 if(i==0){//第一笔的 红绿柱 判断依据是根据 今天开盘价与昨日收盘价比较 90 if(isFirstLineColorflag==false){ 91 columnColor = blue; 92 } 93 avg_pxyAxisMin=data[i][3]; 94 avg_pxyAxisMax=data[i][3]; 95 percentageyAxisMin=Number(100*(data[i][1]/yesterdayClose-1)); 96 percentageyAxisMax=Number(100*(data[i][1]/yesterdayClose-1)); 97 volume_yAxisMin=data[i][2]; 98 volume_yAxisMax=data[i][2]; 99 } 100 else { 101 //除了第一笔,其它都是 返回的 last_px 与前一个对比 102 if(data[i-1][1]-data[i][1]>0){ 103 columnColor = blue; 104 } 105 business_amount=data[i][2]-data[i-1][2]; 106 } 107 avg_pxyAxisMin=avg_pxyAxisMin>data[i][1]?data[i][1]:avg_pxyAxisMin; 108 avg_pxyAxisMax=avg_pxyAxisMax>data[i][1]?avg_pxyAxisMax:data[i][1]; 109 percentageyAxisMin=percentageyAxisMin>Number(100*(data[i][1]/yesterdayClose-1))?Number(100*(data[i][1]/yesterdayClose-1)):percentageyAxisMin; 110 percentageyAxisMax=percentageyAxisMax>Number(100*(data[i][1]/yesterdayClose-1))?percentageyAxisMax:Number(100*(data[i][1]/yesterdayClose-1)); 111 volume_yAxisMin=volume_yAxisMin>business_amount?business_amount:volume_yAxisMin; 112 volume_yAxisMax=volume_yAxisMax>business_amount?volume_yAxisMax:business_amount; 113 //将数据放入 ohlc volume 数组中 114 ohlc.push({x:dateUTC,y:Number(data[i][1])}); 115 volume.push({x:dateUTC,y:Number(business_amount),color:columnColor}); 116 } 117 //将剩下的时间信息补全 118 appendTimeMessage(ohlc,volume,data); 119 createTrendChart(data,ohlc,volume); 120 }; 121 function createTrendChart(data,ohlc,volume){ 122 var date; 123 if(data.length>0){ 124 date=data[data.length-1][0]+""; 125 var dArr = new Array(); 126 for(var hh=0;hh<5;hh++){ 127 var numb ; 128 if(hh==0){ 129 numb = Number(date.slice(0,4)); 130 } 131 else { 132 numb= Number(date.slice((hh-1)*2+4,hh*2+4)); 133 }; 134 dArr.push(numb); 135 } 136 } 137 var last_dataTime=new Date(dArr[0],dArr[1]-1,dArr[2],dArr[3],dArr[4]); 138 var $reporting = $("#report"); 139 $reporting.html(""); 140 // Create the chart 141 var am_startTime=new Date(last_dataTime); 142 am_startTime.setHours(9, 30, 0, 0); 143 var am_startTimeUTC=Number(Date.UTC(am_startTime.getFullYear(),am_startTime.getMonth(),am_startTime.getDate(),am_startTime.getHours(),am_startTime.getMinutes())); 144 145 var am_midTime=new Date(last_dataTime); 146 am_midTime.setHours(10, 30, 0, 0); 147 var am_midTimeUTC=Number(Date.UTC(am_midTime.getFullYear(),am_midTime.getMonth(),am_midTime.getDate(),am_midTime.getHours(),am_midTime.getMinutes())); 148 149 //股票交易早上最后的时间 150 var am_lastTime=new Date(last_dataTime); 151 am_lastTime.setHours(11, 30, 0, 0); 152 var am_lastTimeUTC=Number(Date.UTC(am_lastTime.getFullYear(),am_lastTime.getMonth(),am_lastTime.getDate(),am_lastTime.getHours(),am_lastTime.getMinutes())); 153 //股票交易下午最后的时间 154 var pm_startTime=new Date(last_dataTime); 155 pm_startTime.setHours(13, 1, 0, 0); 156 var pm_startTimeUTC=Number(Date.UTC(pm_startTime.getFullYear(),pm_startTime.getMonth(),pm_startTime.getDate(),pm_startTime.getHours(),pm_startTime.getMinutes())); 157 158 var pm_midTime=new Date(last_dataTime); 159 pm_midTime.setHours(14, 0, 0, 0); 160 var pm_midTimeUTC=Number(Date.UTC(pm_midTime.getFullYear(),pm_midTime.getMonth(),pm_midTime.getDate(),pm_midTime.getHours(),pm_midTime.getMinutes())); 161 162 var pm_lastTime=new Date(last_dataTime); 163 pm_lastTime.setHours(15, 0, 0, 0); 164 var pm_lastTimeUTC=Number(Date.UTC(pm_lastTime.getFullYear(),pm_lastTime.getMonth(),pm_lastTime.getDate(),pm_lastTime.getHours(),pm_lastTime.getMinutes())); 165 //常量本地化 166 Highcharts.setOptions({ 167 global : { 168 useUTC : true 169 } 170 }); 171 172 var startX,startY,swipeX,swipeY; 173 createTrendChart.trend_touchstart=function(event){ 174 var touch = event.touches[0]; 175 startX=touch.pageX; 176 startY=touch.pageY; 177 swipeX=swipeY=false; 178 document.getElementById("line_map").addEventListener("touchmove", createTrendChart.trend_touchmove); 179 } 180 createTrendChart.trend_touchmove=function (event){ 181 var touch = event.touches[0]; 182 var currenX=touch.pageX; 183 var currentY=touch.pageY; 184 if(true==swipeX){//先左右就一直左右 上下也不影响 185 swipeY=false; 186 } 187 else if(true==swipeY){//向上下移动的标志 188 swipeX=false; 189 }else{ 190 if(Math.abs(currentY-startY)>Math.abs(currenX-startX)){//上下移动 191 swipeY=true; 192 } 193 else{ 194 swipeX=true; 195 } 196 } 197 if(true==swipeY){//上下移动 先重画线 人后删除事件 198 document.getElementById("line_map").removeEventListener("touchmove", createTrendChart.trend_touchmove,false); 199 }else if(true==swipeX){ 200 event.stopPropagation(); 201 event.preventDefault(); 202 } 203 //不管 上下 还是 左右 都需要先画标示线 204 var chart = $(DIVID).highcharts(); 205 var left=chart.yAxis[0].left+(chart.yAxis[0].axisLine.strokeWidth==undefined?0:chart.yAxis[0].axisLine.strokeWidth); 206 var y ; 207 var x = touch.pageX-left-7; 208 //x点 =x/chart宽度 * 总体点的个数 209 x=(x/chart.plotWidth)*ohlc.length; 210 var i=0; 211 i=Number(Math.ceil(x)); 212 if(i>=data.length||i<0){ 213 return;} 214 //计算图表x轴 215 x=ohlc[i].x;//utc格式时间数据 216 y=data[i][1]; 217 var last_px=data[i][1].toFixed(2); 218 var business_amount=data[i][2]; 219 var avg_price=data[i][3].toFixed(2); 220 var zfz=(100*(ohlc[i].y/yesterdayClose-1)).toFixed(2); 221 var time=Highcharts.dateFormat('%H:%M ', x); 222 //除了第一笔,其它都是 返回的 last_px 与前一个对比 223 if(i!=0){ 224 business_amount=data[i][2]-data[i-1][2]; 225 } 226 $reporting.html( 227 '<div class="detail">'+ 228 '<ul>'+ 229 '<li class="value-2">'+ '价格: <span>'+last_px+'</span></li>'+ 230 '<li class="value-2">'+ '成交量: <span>'+business_amount+'</span></li>'+ 231 '<li class="value-2">'+ '均价: <span>'+avg_price+'</span></li>'+ 232 '<li class="value-2">'+ '涨幅值: <span>'+zfz+'%</span></li>'+ 233 '</ul>'+ 234 '</div>' 235 ); 236 var chart = $(DIVID).highcharts(); // Highcharts构造函数 237 chart.xAxis[0].removePlotBand("plotBand-x"); 238 chart.xAxis[0].addPlotBand({ 239 borderColor:'red', 240 borderWidth:0.1, 241 color: 'red', 242 from: x-0.000001,//,Date.UTC(2015, 3, 27,10,50), 243 to: x+0.000001,//Date.UTC(2015, 3, 27,10,51), 244 label: { 245 useHTML:true, 246 text: '<span class="value" style="font-size:10px;background-color:rgba(0,0,0,.6); color:#fff; height:15px; line-height:15px; padding:0 5px;">'+time+'</span>', 247 textAlign: 'bottom', 248 y:5, 249 x:-30 250 }, 251 id:'plotBand-x', 252 zIndex:1001 253 }); 254 chart.yAxis[0].removePlotBand("plotBand-y0"); 255 chart.yAxis[0].addPlotBand({ 256 borderColor:'red', 257 borderWidth:0.1, 258 color: 'red', 259 from: y-0.000001,//,Date.UTC(2015, 3, 27,10,50), 260 to: y+0.000001,//Date.UTC(2015, 3, 27,10,51), 261 label: { 262 useHTML:true, 263 style: { //字体样式 264 font: 'normal 5px Verdana, sans-serif' 265 }, 266 text: '<span class="value" style="font-size:10px;background-color:rgba(0,0,0,.6); color:#fff; height:15px; line-height:15px; padding:0 5px;">'+y+'</span>', 267 verticalAlign:'top', 268 textAlign: 'left', 269 x:-25, 270 y:-2 271 }, 272 id:'plotBand-y0', 273 zIndex:1001 274 275 }); 276 chart.yAxis[0].removePlotBand("plotBand-y1"); 277 chart.yAxis[0].addPlotBand({ 278 color: '#BEBEBE', 279 borderColor:'#BEBEBE', 280 borderWidth:0.1, 281 from: y-0.000001,//,Date.UTC(2015, 3, 27,10,50), 282 to: y+0.000001,//Date.UTC(2015, 3, 27,10,51), 283 label: { 284 useHTML:true, 285 style: { //字体样式 286 font: 'normal 5px Verdana, sans-serif' 287 }, 288 text: '<span class="value" style="font-size:10px;background-color:rgba(0,0,0,.6); color:#fff; height:15px; line-height:15px; padding:0 5px;">'+zfz+"%"+'</span>', 289 textAlign: 'right', 290 verticalAlign:'bottom', 291 x:280, 292 y:-2 293 }, 294 id:'plotBand-y1', 295 zIndex:1001 296 }); 297 } 298 document.getElementById("line_map").removeEventListener("touchstart",createKlineChart.kline_touchstart,false); 299 document.getElementById("line_map").addEventListener("touchstart", createTrendChart.trend_touchstart); 300 document.getElementById("line_map").removeEventListener("touchmove",createKlineChart.kline_touchmove,false); 301 //开始画图 302 $(DIVID).highcharts('StockChart', { 303 chart:{ 304 //关闭平移 305 panning:false, 306 zoomType: 'none', 307 pinchType:'none', 308 renderTo : "line_map", 309 margin: [25, 25,25, 25], 310 spacing: [0,0,0,0], 311 plotBorderColor: '#3C94C4', 312 plotBorderWidth: 0, 313 events:{ 314 load:function(){ 315 x=ohlc[data.length-1].x; 316 y=ohlc[data.length-1].y; 317 var chart = $(DIVID).highcharts(); // Highcharts构造函数 318 //基准线 319 chart.yAxis[0].addPlotLine({ //在x轴上增加 320 value:yesterdayClose, //在值为2的地方 321 width:0.1, //标示线的宽度为2px 322 color: '#FFA500', //标示线的颜色 323 zIndex:1001 324 }); 325 chart.xAxis[0].removePlotBand("plotBand-x"); 326 chart.xAxis[0].addPlotBand({ 327 borderColor:'#BEBEBE', 328 borderWidth:0.1, 329 color: '#BEBEBE', 330 from: ohlc[data.length-1].x-0.000001,//,Date.UTC(2015, 3, 27,10,50), 331 to: ohlc[data.length-1].x+0.000001,//Date.UTC(2015, 3, 27,10,51), 332 label: { 333 useHTML:true, 334 text: '<span class="value" style="font-size:10px;background-color:rgba(0,0,0,.6); color:#fff; height:15px; line-height:15px; padding:0 5px;">'+Highcharts.dateFormat('%H:%M ', ohlc[data.length-1].x)+'</span>', 335 textAlign: 'top', 336 y:5, 337 x:-30 338 }, 339 id:'plotBand-x', 340 zIndex:1001 341 }); 342 chart.yAxis[0].removePlotBand("plotBand-y0"); 343 chart.yAxis[0].addPlotBand({ 344 borderColor:'#BEBEBE', 345 borderWidth:0.1, 346 color: '#BEBEBE', 347 from: ohlc[data.length-1].y-0.0001,//,Date.UTC(2015, 3, 27,10,50), 348 to: ohlc[data.length-1].y+0.0001,//Date.UTC(2015, 3, 27,10,51), 349 label: { 350 useHTML:true, 351 style: { //字体样式 352 font: 'normal 5px Verdana, sans-serif' 353 }, 354 text: '<span class="value" style="font-size:10px;background-color:rgba(0,0,0,.6); color:#fff; height:15px; line-height:15px; padding:0 5px;">'+ohlc[data.length-1].y.toFixed(2)+'</span>', 355 verticalAlign:'top', 356 textAlign: 'left', 357 x:-25, 358 y:-2 359 }, 360 id:'plotBand-y0', 361 zIndex:1001 362 }); 363 chart.yAxis[0].removePlotBand("plotBand-y1"); 364 chart.yAxis[0].addPlotBand({ 365 color: '#BEBEBE', 366 borderWidth:0.1, 367 borderColor:'#BEBEBE', 368 from: ohlc[data.length-1].y-0.0001,//,Date.UTC(2015, 3, 27,10,50), 369 to: ohlc[data.length-1].y+0.0001,//Date.UTC(2015, 3, 27,10,51), 370 label: { 371 useHTML:true, 372 style: { //字体样式 373 font: 'normal 5px Verdana, sans-serif' 374 }, 375 text: '<span class="value" style="font-size:10px;background-color:rgba(0,0,0,.6); color:#fff; height:15px; line-height:15px; padding:0 5px;">'+(100*(ohlc[data.length-1].y/yesterdayClose-1)).toFixed(2)+"%"+'</span>', 376 textAlign: 'right', 377 verticalAlign:'bottom', 378 x:280, 379 y:-2 380 }, 381 id:'plotBand-y1', 382 zIndex:1001 383 }); 384 $reporting.html( 385 '<div class="detail">'+ 386 '<ul>'+ 387 '<li class="value-2">'+ '价格: <span>'+data[data.length-1][1].toFixed(2)+'</span></li>'+ 388 '<li class="value-2">'+ '成交量: <span>'+data[data.length-1][2]+'</span></li>'+ 389 '<li class="value-2">'+ '均价: <span>'+data[data.length-1][3].toFixed(2)+'</span></li>'+ 390 '<li class="value-2">'+ '涨幅值: <span>'+(100*(data[data.length-1][3]/yesterdayClose-1)).toFixed(2)+'%</span></li>'+ 391 '</ul>'+ 392 '</div>' 393 ); 394 } 395 } 396 }, 397 tooltip:{ 398 enabled:false, 399 crosshairs:false 400 }, 401 rangeSelector:{ 402 enabled: false, 403 }, 404 /*导出配置*/ 405 exporting: { 406 enabled: false, 407 }, 408 /*创建者信息*/ 409 credits: { 410 enabled: false, 411 }, 412 /*下部时间拖拉选择*/ 413 navigator: { 414 enabled: false, 415 /*关闭时间选择*/ 416 baseseries: 10 417 }, 418 scrollbar: { 419 enabled: false /*关闭下方滚动条*/ 420 }, 421 /*底部滚动条*/ 422 scrollbar: { 423 enabled: false 424 }, 425 plotOptions:{ 426 //去掉分时线上的hover事件 427 series:{ 428 states: { 429 hover: { 430 enabled: false 431 } 432 }, 433 line: { 434 marker: { 435 enabled: false 436 } 437 }, 438 } 439 }, 440 xAxis:{ 441 showFirstLabel: true, 442 showLastLabel:true, 443 scrollbar:{enabled:true}, 444 labels: { 445 // staggerLines:5 446 style: { //字体样式 447 font: 'normal 5px Verdana, sans-serif' 448 }, 449 formatter:function(){ 450 var returnTime=Highcharts.dateFormat('%H:%M ', this.value); 451 if(returnTime=="11:30 ") 452 { 453 return "11:30/13:00"; 454 } 455 return returnTime; 456 }, 457 }, 458 tickPositioner:function(){ 459 var positions=[am_startTimeUTC,am_midTimeUTC,am_lastTimeUTC,pm_midTimeUTC,pm_lastTimeUTC]; 460 return positions; 461 }, 462 gridLineWidth: 1, 463 }, 464 yAxis: [{ 465 opposite: false,//是否把它显示到另一边(右边) 466 labels: { 467 style: { //字体样式 468 font: 'normal 5px Verdana, sans-serif' 469 }, 470 overflow: 'justify', 471 align: 'right', 472 x: -3, 473 y:5, 474 formatter:function(){ 475 //最新价 px_last/preclose昨收盘-1 476 return (this.value).toFixed(2); 477 } 478 }, 479 title: { 480 text: '' 481 }, 482 top:'0%', 483 height: '65%', 484 lineWidth: 1, 485 showFirstLabel: true, 486 showLastLabel:true, 487 488 tickPositioner:function(){ //以yesterdayClose为界限,统一间隔值,从 最小到最大步进 489 positions = [], 490 tick = Number((avg_pxyAxisMin)), 491 increment = Number(((avg_pxyAxisMax - avg_pxyAxisMin) / 5)); 492 var tickMin=Number((avg_pxyAxisMin)),tickMax=Number((avg_pxyAxisMax)); 493 if(0==data.length){//还没有数据时,yesterdayClose 的幅值 在 -1% - 1%上下浮动 494 tickMin=0.99*yesterdayClose; 495 tickMax=1.01*yesterdayClose; 496 }else if(0==increment){//有数据了 但是数据都是一样的幅值 497 if(yesterdayClose>Number(avg_pxyAxisMin)){ 498 tickMin=Number(avg_pxyAxisMin); 499 tickMax=2*yesterdayClose-Number(avg_pxyAxisMin); 500 }else if(yesterdayClose<Number(avg_pxyAxisMin)){ 501 tickMax=Number(avg_pxyAxisMax); 502 tickMin=yesterdayClose-(Number(avg_pxyAxisMax)-yesterdayClose); 503 }else{ 504 tickMin=0.99*yesterdayClose; 505 tickMax=1.01*yesterdayClose; 506 } 507 }else if(avg_pxyAxisMin-yesterdayClose<0&&avg_pxyAxisMax-yesterdayClose>0){//最小值在昨日收盘价下面,最大值在昨日收盘价上面 508 var limit=Math.max(Math.abs(avg_pxyAxisMin-yesterdayClose),Math.abs(avg_pxyAxisMax-yesterdayClose)); 509 tickMin=yesterdayClose-limit; 510 tickMax=yesterdayClose+limit; 511 }else if(avg_pxyAxisMin>yesterdayClose&&avg_pxyAxisMax>yesterdayClose){//最小最大值均在昨日收盘价上面 512 tickMax=avg_pxyAxisMax; 513 tickMin=yesterdayClose-(tickMax-yesterdayClose); 514 515 }else if(avg_pxyAxisMin<yesterdayClose&&avg_pxyAxisMax<yesterdayClose){//最小最大值均在昨日收盘价下面 516 tickMin=avg_pxyAxisMin; 517 tickMax=yesterdayClose+(yesterdayClose-tickMin); 518 } 519 if(tickMax>2*yesterdayClose){//数据超过100%了 520 tickMax=2*yesterdayClose; 521 tickMin=0; 522 } 523 var interval=Number(tickMax-yesterdayClose)/10; 524 tickMax+=interval; 525 tickMin=yesterdayClose-(tickMax-yesterdayClose); 526 increment=(tickMax-yesterdayClose)/3; 527 tick=tickMin; 528 var i=0; 529 for (tick;i ++ <7 ; tick += increment) { 530 positions.push(Number(tick)); 531 } 532 533 return positions; 534 }, 535 }, 536 { 537 opposite: true,//是否把它显示到另一边(右边) 538 showFirstLabel: true, 539 showLastLabel:true, 540 labels: { 541 overflow: 'justify', 542 style: { //字体样式 543 font: 'normal 5px Verdana, sans-serif' 544 }, 545 align: 'right', 546 x: 25, 547 y:5, 548 formatter:function(){//最新价 px_last/preclose昨收盘-1 549 return (100*(this.value/yesterdayClose-1)).toFixed(2)+"%"; 550 } 551 }, 552 title: { 553 text: '' 554 }, 555 lineWidth: 1, 556 top:'0%', 557 height: '65%', 558 gridLineWidth: 1, 559 tickPositioner:function(){ 560 return positions; 561 } 562 }, 563 { 564 opposite: false,//是否把它显示到另一边(右边) 565 labels: { 566 overflow: 'justify', 567 style: { //字体样式 568 font: 'normal 5px Verdana, sans-serif' 569 }, 570 align: 'right', 571 x: -3, 572 y:5, 573 formatter:function(){ 574 if(this.value>1000000000){ 575 return Number((this.value/1000000000).toFixed(2))+"G"; 576 }else if(this.value>1000000){ 577 return Number((this.value/1000000).toFixed(2))+"M"; 578 }else if(this.value>1000){ 579 return Number((this.value/1000).toFixed(2))+"K"; 580 }else{ 581 return Number(this.value.toFixed(2)); 582 } 583 } 584 }, 585 title: { 586 text: '' 587 }, 588 top: '70%', 589 height: '30%', 590 width:'100%', 591 offset: 0, 592 lineWidth: 1, 593 showFirstLabel: true, 594 showLastLabel:true, 595 tickPositioner:function(){ 596 var positions = [], 597 tickMax=volume_yAxisMax, 598 tickMin=volume_yAxisMin, 599 tick = 0, 600 increment = 0; 601 var limit=tickMax/2; 602 tickMax+=limit; 603 increment=tickMax/2; 604 tick=0; 605 for (tick; tick <= tickMax; tick += increment) { 606 positions.push(Number(tick.toFixed(2))); 607 if(increment==0){ 608 break; 609 } 610 } 611 return positions; 612 }, 613 }], 614 series : [{ 615 name : 'AAPL Stock Price', 616 data : ohlc, 617 type : 'areaspline', 618 tooltip : { 619 valueDecimals : 2 620 }, 621 fillColor : { 622 linearGradient : { 623 x1: 0, 624 y1: 0, 625 x2: 0, 626 y2: 1 627 }, 628 stops : [ 629 [0, Highcharts.getOptions().colors[0]], 630 [1, Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0).get('rgba')] 631 ] 632 }, 633 yAxis:0, 634 }, 635 { 636 name : 'AAPL Stock Price', 637 data : ohlc, 638 type : 'scatter', 639 cursor:'pointer', 640 onSeries : 'candlestick', 641 color:'transparent', 642 tooltip : { 643 valueDecimals : 2 644 }, 645 style:{ 646 fontSize: '0px', 647 fontWeight: '0', 648 textAlign: 'center' 649 }, 650 zIndex:-1000, 651 yAxis:1, 652 }, 653 { 654 type: 'column', 655 name: '成交量', 656 data: volume, 657 dataGrouping: { 658 enabled: false, 659 forced: true 660 }, 661 yAxis:2, 662 zIndex:-1000 663 }] 664 }); 665 } 666 /** 667 * 错误处理 668 */ 669 function failCallback(){ 670 var last_dataTime=new Date(); 671 var $reporting = $("#report"); 672 $reporting.html(""); 673 // Create the chart 674 var am_startTime=new Date(last_dataTime); 675 am_startTime.setHours(9, 30, 0, 0); 676 var am_startTimeUTC=Number(Date.UTC(am_startTime.getFullYear(),am_startTime.getMonth(),am_startTime.getDate(),am_startTime.getHours(),am_startTime.getMinutes())); 677 678 var am_midTime=new Date(last_dataTime); 679 am_midTime.setHours(10, 30, 0, 0); 680 var am_midTimeUTC=Number(Date.UTC(am_midTime.getFullYear(),am_midTime.getMonth(),am_midTime.getDate(),am_midTime.getHours(),am_midTime.getMinutes())); 681 682 //股票交易早上最后的时间 683 var am_lastTime=new Date(last_dataTime); 684 am_lastTime.setHours(11, 30, 0, 0); 685 var am_lastTimeUTC=Number(Date.UTC(am_lastTime.getFullYear(),am_lastTime.getMonth(),am_lastTime.getDate(),am_lastTime.getHours(),am_lastTime.getMinutes())); 686 //股票交易下午最后的时间 687 var pm_startTime=new Date(last_dataTime); 688 pm_startTime.setHours(13, 1, 0, 0); 689 var pm_startTimeUTC=Number(Date.UTC(pm_startTime.getFullYear(),pm_startTime.getMonth(),pm_startTime.getDate(),pm_startTime.getHours(),pm_startTime.getMinutes())); 690 691 var pm_midTime=new Date(last_dataTime); 692 pm_midTime.setHours(14, 0, 0, 0); 693 var pm_midTimeUTC=Number(Date.UTC(pm_midTime.getFullYear(),pm_midTime.getMonth(),pm_midTime.getDate(),pm_midTime.getHours(),pm_midTime.getMinutes())); 694 695 696 var pm_lastTime=new Date(last_dataTime); 697 pm_lastTime.setHours(15, 0, 0, 0); 698 var pm_lastTimeUTC=Number(Date.UTC(pm_lastTime.getFullYear(),pm_lastTime.getMonth(),pm_lastTime.getDate(),pm_lastTime.getHours(),pm_lastTime.getMinutes())); 699 var data=[]; 700 data.push({x:am_startTimeUTC,y:1}); 701 data.push({x:am_midTimeUTC,y:2}); 702 data.push({x:am_lastTimeUTC,y:3}); 703 data.push({x:pm_midTimeUTC,y:4}); 704 data.push({x:pm_lastTimeUTC,y:5}); 705 //常量本地化 706 Highcharts.setOptions({ 707 global : { 708 useUTC : true 709 } 710 }); 711 $(DIVID).highcharts('StockChart', { 712 chart:{ 713 renderTo : "line_map", 714 margin: [25, 25,25, 25], 715 plotBorderColor: '#3C94C4', 716 plotBorderWidth: 0.3, 717 // zoomType:false, 718 }, 719 tooltip:{ 720 enabled:false 721 }, 722 rangeSelector:{ 723 enabled: false, 724 }, 725 /*导出配置*/ 726 exporting: { 727 enabled: false, 728 }, 729 /*创建者信息*/ 730 credits: { 731 enabled: false, 732 }, 733 /*下部时间拖拉选择*/ 734 navigator: { 735 enabled: false, 736 /*关闭时间选择*/ 737 baseseries: 10 738 }, 739 /*底部滚动条*/ 740 scrollbar: { 741 enabled: false 742 }, 743 plotOptions:{ 744 //去掉分时线上的hover事件 745 series: { 746 states: { 747 hover: { 748 enabled: false 749 } 750 }, 751 line: { 752 marker: { 753 enabled: false 754 } 755 }, 756 }, 757 }, 758 xAxis:{ 759 showFirstLabel: true, 760 showLastLabel:true, 761 tickInterval: 1, 762 labels: { 763 style: { //字体样式 764 font: 'normal 5px Verdana, sans-serif' 765 }, 766 formatter:function(){ 767 var labels=['9:30','10:30','11:30/13:00','14:00','15:00'] 768 return labels[this.value]; 769 }, 770 }, 771 categories:['9:30','10:30','11:30/13:00','14:00','15:00'], 772 gridLineWidth: 1, 773 }, 774 yAxis: [{ 775 showFirstLabel: true, 776 showLastLabel:true, 777 opposite: false,//是否把它显示到另一边(右边) 778 labels: { 779 align: 'right', 780 x: -3, 781 y:5 782 }, 783 title: { 784 text: '' 785 }, 786 height: '50%', 787 lineWidth: 1, 788 gridLineWidth: 1, 789 }, 790 { 791 showFirstLabel: true, 792 showLastLabel:true, 793 opposite: false,//是否把它显示到另一边(右边) 794 labels: { 795 align: 'right', 796 x: -3, 797 y:5 798 }, 799 title: { 800 text: '' 801 }, 802 top: '60%', 803 height: '40%', 804 offset: 0, 805 lineWidth: 1, 806 gridLindeWidth:1, 807 }], 808 series : [{ 809 name : 'AAPL Stock Price', 810 data :[10,20,30,40,50],// [["9:30",200],["10:30",205]["11:30/13:00",210],["14:00",215],["15:00",220]], 811 type:'column', 812 color:'transparent', 813 fillColor : { 814 linearGradient : { 815 x1: 0, 816 y1: 0, 817 x2: 0, 818 y2: 1 819 }, 820 stops : [ 821 [0, Highcharts.getOptions().colors[0]], 822 [1, Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0).get('rgba')] 823 ] 824 }, 825 dataGrouping: { 826 enabled: false, 827 forced: true 828 }, 829 yAxis:0, 830 }, 831 { 832 type: 'column', 833 name: '成交量', 834 fillColor : { 835 linearGradient : { 836 x1: 0, 837 y1: 0, 838 x2: 0, 839 y2: 1 840 }, 841 stops : [ 842 [0, Highcharts.getOptions().colors[0]], 843 [1, Highcharts.Color(Highcharts.getOptions().colors[0]).setOpacity(0).get('rgba')] 844 ] 845 }, 846 data : [10,20,30,40,50],//[[0, 15], [10, -50], [20, -56.5], [30, -46.5], [40, -22.1], 847 //[50, -2.5], [60, -27.7], [70, -55.7], [80, -76.5]], 848 color:'transparent', 849 yAxis: 1, 850 dataGrouping: { 851 enabled: false, 852 forced: true 853 }, 854 yAxis:1, 855 }] 856 }); 857 } 858 /** 859 * 获取日期对象,如果isUTC为true获取 日期的UTC对象,false则获取普通日期对象 860 * @param date 861 * @param isUTC 862 * @returns 863 */ 864 function getDateUTCOrNot(date,isUTC){ 865 if(! (date instanceof String)) 866 { 867 date+=""; 868 } 869 var dArr = new Array(); 870 for(var hh=0;hh<5;hh++){ 871 var numb ; 872 if(hh==0){ 873 numb = Number(date.slice(0,4)); 874 } 875 else { 876 numb= Number(date.slice((hh-1)*2+4,hh*2+4)); 877 }; 878 dArr.push(numb); 879 } 880 if(isUTC==false){ 881 return new Date(dArr[0],dArr[1]-1,dArr[2],dArr[3],dArr[4]); 882 } 883 var dateUTC = Number(Date.UTC(dArr[0],dArr[1]-1,dArr[2],dArr[3],dArr[4]));//得出的UTC时间 884 return dateUTC; 885 } 886 887 //数据补全 888 function appendTimeMessage(ohlc,volume,data){ 889 var date=data[data.length-1][0]+""; 890 var last_dataTime=getDateUTCOrNot(date,false); 891 892 //股票交易早上最后的时间 893 var am_lastTime=new Date(last_dataTime); 894 am_lastTime.setHours(11, 30, 0, 0); 895 //股票交易下午最后的时间 896 var pm_startTime=new Date(last_dataTime); 897 pm_startTime.setHours(13, 1, 0, 0); 898 var pm_lastTime=new Date(last_dataTime); 899 pm_lastTime.setHours(15, 0, 0, 0); 900 //把时间日期格式转化成utc格式 901 function convertDateToUTC(date){ 902 return Number(Date.UTC(date.getFullYear(),date.getMonth(),date.getDate(),date.getHours(),date.getMinutes())); 903 } 904 //如果获取的时间11::30之前的计算 905 if(last_dataTime<am_lastTime){ 906 var i=last_dataTime; 907 i.setMinutes((i.getMinutes()+1)); 908 for(;i<=am_lastTime;i.setMinutes((i.getMinutes()+1))) 909 { 910 ohlc.push({x:convertDateToUTC(i)}); 911 volume.push({x:convertDateToUTC(i)}); 912 } 913 i=pm_startTime; 914 for(;i<=pm_lastTime;i.setMinutes((i.getMinutes()+1))) 915 { 916 ohlc.push({x:convertDateToUTC(i)}); 917 volume.push({x:convertDateToUTC(i)}); 918 } 919 }else if(last_dataTime<pm_lastTime){ //获取的时间下午13:00之后的计算 920 var i; 921 if(Number(last_dataTime)==Number(am_lastTime)){ 922 i=pm_startTime; 923 }else{ 924 i=last_dataTime; 925 } 926 i.setMinutes((i.getMinutes()+1)); 927 for(;i<=pm_lastTime;i.setMinutes((i.getMinutes()+1))) 928 { 929 ohlc.push({x:convertDateToUTC(i)}); 930 volume.push({x:convertDateToUTC(i)}); 931 } 932 } 933 }