似乎可利用的插件或库有很多,比如echarts、highcharts、d3.js等。使用echarts是最简单的,有现成的demo可供参考,而d3可定制性是最高的,这些定制需要你一点点去写,也不好写,highcharts官网上没有demo,网上也没有相关的案例,但是通过阅读他的说明文档,发现了箱线图这一图表类型,这不正是highcharts实现k线图最好的方法吗?
箱线图中一个箱体包含五个值:上边缘(最大观测值或样品最大值)、上四分位数(Q3)、中位数(Q2)、下四分位数(Q1)和下边缘(最小观测值或样品最小值)。另外在箱体外还可以用圆形点表示异常值,下面是箱线图组成部分示意图:
在 Highcharts 中,箱线图的箱体由主箱体(Box)、中位线(median)、颈部(Stem)和须线(Whishker)组成,异常值是用散点的形式展现,下面是示意图:
正如上面说的,箱线图中每个箱体包含五个值,Highcharts 可以识别的箱线数据点的定义方式包括:
1、对象数组的形式,其中 x 值是可选的
{ x: Date.UTC(2013, 1, 7), low: 0, q1: 1, median: 2, q3: 3, high: 4 }
2、包含五个元素的数组,x 值自动计算
[0, 1, 2, 3, 4]
3、包含六个元素的数组,其中第一个值是 x 值
[Date.UTC(2013, 1, 7), 0, 1, 2, 3, 4]
我们可以用上须线(high)表示k线图数据的最大值,下须线(low)表示k线图的最小值,箱体(q1,q3)表示k线图的开盘/收盘价,我的数据格式:
0、数据的生成,只是简单模拟日数据(毕竟对股票数据这块不太熟,线上项目肯定是从后台取的数据吧?)
1、箱体颜色填充,看遍说明文档也没发现怎么填充不同的颜色
发现series 配置 data 中可以配置className,但是怎么也出不来,放弃
阅读源码,发现填充色默认为#ffffff,但如果设置为null,undefined或"",则根据设置的color来填充。苦笑...
2、x轴标签问题,数据过多,会自动旋转,取消旋转,会出现溢出隐藏(默认是溢出显示省略号)
设置 autoRotation 为 [-10],之前试了[0]不行,为什么[-10]是平的,而[0]不可以???坑!!!
3、像x轴的网格线,y轴的轴线,默认宽度为0,需要自己设置下
4、提示框悬停在箱线图上才会出现,需要设置shared为true,全屏扑捉提示框
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>基于Highcharts箱线图实现k线图title>
<style>
.myTooltip p{
margin: 0;
padding: 0;
height: 25px;
line-height: 25px;
width: 120px;
}
.myTooltip p.blockSpan{
text-align: center;
font-weight: bold;
}
.myTooltip p.myRed{
color:#E30000;
}
.myTooltip p.myGreen{
color:#007130;
}
.myTooltip p span:first-child{
display: inline-block;
width: 50px;
text-align: right;
padding-right: 10px;
}
style>
head>
<body>
<div id="container" style="height: 400px; margin: auto; width: 600px">div>
<script src="http://cdn.hcharts.cn/highcharts/highcharts.js">script>
<script src="http://cdn.hcharts.cn/highcharts/highcharts-more.src.js">script>
<script type="text/javascript">
//格式化时间
function formatDate(date){
//模拟股市开盘时间: 周一至周五(不考虑假期)
var date = new Date(date),
w = date.getDay(),
Y = date.getFullYear(),
M = date.getMonth() + 1,
D = date.getDate();
if(w>0 && w<6){
return Y+'-'+(M<10?"0":"")+M+'-'+(D<10?"0":"")+D;
//return date; //x轴为时间轴时的数据
}
return false;
}
function getDate(m){
var date = new Date().getTime(),
i = 0,
dates = [];
while(dates.lengthvar item = formatDate(date - i*24*60*60*1000);
item && dates.push(item);
i++;
}
dates.reverse();
//console.log(dates);
return dates;
}
//获取x轴数据
var xdata = getDate(40);
//获取涨跌幅随机数
function rand(){
var sum = 0;
for(var i=0;i<10;i++){
i%2==0?(sum += Math.random()):(sum -= Math.random());
}
return sum.toFixed(2)/100;//百分数
}
//获取 series 数据
function getData(m){
var data = [{
low: 3142,//最小值
q1: 3186,//最小实际值(开盘/收盘价)
median: null,//中位数
q3: 3225,//最大实际值(开盘/收盘价)
high: 3225,//最大值
name:xdata[0],
RiseAndFall:1.22,//涨跌幅 百分数
//className:'red',//给数据项加一个class,方便设置颜色,无效
color: "#ff0000"
}],
obj,RiseAndFall,kpj,spj,RiseAndFall2,RiseAndFall3;
for(var j=1;j//kpj 开盘价 开盘价 = 前一个交易日的收盘价
//前一个交易日是涨 收盘价为q3 否则为q1
kpj = data[j-1].RiseAndFall>0?data[j-1].q3:data[j-1].q1;
//spj 收盘价 收盘价 = 开盘价 + 开盘价*涨跌幅
spj = kpj + kpj * RiseAndFall;
RiseAndFall2 = rand();
RiseAndFall3 = rand();
obj = {
low:+function(){
if(RiseAndFall>0){//是涨 最小值<=开盘价
return RiseAndFall2>0?kpj:(kpj+kpj*RiseAndFall2)
}else{//是跌 最小值<=收盘价
return RiseAndFall2>0?spj:(spj+spj*RiseAndFall2)
}
}(),
q1:RiseAndFall>0?kpj:spj,
median: null,//中位数
q3:RiseAndFall>0?spj:kpj,
high:+function(){
if(RiseAndFall>0){//是涨 最大值>=收盘价
return RiseAndFall3>0?(spj+spj*RiseAndFall3):spj
}else{//是跌 最大值>=开盘价
return RiseAndFall3>0?(kpj+kpj*RiseAndFall3):kpj
}
}(),
name:xdata[j-1],
RiseAndFall:RiseAndFall*100,
color: RiseAndFall>0?"#ff0000":RiseAndFall<0?"#00ff00":"#bbbbbb"
}
data.push(obj);
}
return data;
}
var data = getData(xdata.length);
Highcharts.chart('container', {
chart: {
backgroundColor:'#000',
zoomType: 'x'//可以用鼠标缩放x轴
},
credits:{
enabled:false//不启用版权信息 否则会显示highcharts的一些信息
},
title: {
text: '上证指数[000001]',
style:{
color:'#ffffff'
}
},
legend: {
enabled: false
},
xAxis: {
//type: 'datetime',
//type:'category',
title: {visible:false},
categories: xdata,
labels:{
//autoRotation:false,//默认不旋转 无效 不会自动删减
autoRotation:[-10],
//overflow:undefined,
//tickInterval:null,//间隔多少条数据 无效
//tickPixelInterval:50,//间隔多少像素 无效
style:{
color:'#ffffff'
}
},
gridLineColor:'#666',
gridLineDashStyle:'LongDash',
gridLineWidth:1,
//crosshair: true
crosshair: {
width: 1,
color: '#ffffff',
dashStyle: 'shortdot'
}
},
yAxis: {
title: {visible:false},
lineWidth:1,
labels:{
style:{
color:'#ffffff'
}
},
gridLineColor:'#666',
gridLineDashStyle:'LongDash',
//crosshair: true
crosshair: {
width: 1,
color: '#ffffff',
dashStyle: 'shortdot'
}
},
tooltip:{
shared:true,//共享提示框,整个绘图区都将捕捉鼠标指针的移动,显示提示框,同时将多个数据列的信息展示在同一个提示框里
useHTML:true,
formatter:function(){
var options = this.points[0].point.options,
RiseAndFall = options.RiseAndFall,
high = options.high,
low = options.low,
kp = (options.q1*RiseAndFall)>(options.q3*RiseAndFall)?options.q3:options.q1,
sp = (options.q1*RiseAndFall)>(options.q3*RiseAndFall)?options.q1:options.q3,
html = ''+this.x+'
';
//这里顺便添加class,设置提示框不同字体颜色,我是随便设置的
html += "开盘:"+kp.toFixed(2)+"
";
html += "最高:"+high.toFixed(2)+"
";
html += "最低:"+low.toFixed(2)+"
";
html += "收盘:"+sp.toFixed(2)+"
";
html += "涨跌幅:"+RiseAndFall.toFixed(2)+"%
";
html += "";
return html;
}
},
plotOptions: {
boxplot: {
//中线
medianWidth: 0,
//上下边缘线
//whiskerColor:'#fff',
whiskerLength:0,
//className:'myBoxplot'
}
},
series: [{
//name: 'boxplot',
type: 'boxplot',
fillColor:null,//关键:填充色,不做设置,填充色为白色,设置为null,undefined,''等,填充色为data的color
data: data
}]
});
script>
body>
html>