使用百度echarts仿雪球分时图(三)
这章节将完成我们的分时图,并使用真实的数据来进行展示分时图。
一天的交易时间段分为上午的09:30~11:30,下午的13:00~15:00两个时间段,因为分时间段的关系,数据是不连续的,所以会先分为2个grid,上午的grid跟下午的grid,又因为分时图是由折线图跟柱状图来组成的,所以又把上下午的grid再一分为二,变成了4个grid,这也是为什么会分解成4个grid的原因。
先看看分时图的数据。
现在我们再重新看一下雪球的分时图
根路径的last_price指的是昨日收盘价,这个数值很重要,我们需要这个数值来建立一条基准线;然后items里面就是今天的交易数据了,current表示这一分钟应该取的价格,一般是指一分钟内最后一笔成交的价格,也是折线图的数据;volume则是这一分钟的成交量,也就是下方柱状图的数据;timestamp表示这是哪个时间的数据,我们用来作为x轴的数据。
将x轴的type设置成“time”。为了方便我们也把坐标轴的最大最小值设置成随数据的最大最小值,把max设置成"dataMax",min设置成"dataMin"。
type: 'time',
max:'dataMax',
min:'dataMin'
y轴也是需要进行一些配置,已达到完全对称的效果,需要配置interval属性以及max,min属性。x轴的时间是已经固定了09:30~11:30,13:00~15:00,所以可以直接写死,但是y轴的价格是会波动的,所以这三个数值是要经过运算得来的。
我们先配置上方的折线图的y轴坐标轴线为9条,设置splitNumber属性为9即可,定义变量priceMax、priceMin、priceInterval(priceInterval表示价格的差值),以及左边的数据数组grid1Data,右边的数据数组grid3Data。(注:由于x轴的type修改成了'time'类型,所以去掉x轴的data属性)。下方的柱状图也是这样,下方的柱状图一共是3条坐标轴线,设置splitNumber属性为3即可,定义变量volumeMax,volumeMin,volumeInterval(volumeInterval表示价格的差值),以及左边的数据数组grid2Data,右边的数据数组grid4Data;柱状图每一条柱子的颜色设置方式为
color: function (params) {
// params.dataIndex 柱子的下标
return "#000";
}
所以要新建两个数组volumeColor1,volumeColor2来存放柱子的颜色。接下来,我们要遍历我们拿到的分时图数据data,来组成我们需要的数据。
for(var i in data.data.items){
// 上午的数据
if(i < 121){
if(data.data.items[i].current > priceMax){
priceMax = data.data.items[i].current;
}
if(data.data.items[i].current < priceMin || priceMin == 0){
priceMin = data.data.items[i].current;
}
// 左上方折线图
grid1Data.push([data.data.items[i].timestamp,data.data.items[i].current]); if(data.data.items[i].volume > volumeMax){
volumeMax = data.data.items[i].volume;
}
if(data.data.items[i].volume < volumeMin ){
volumeMin = data.data.items[i].volume;
} if(i == 0){ if(data.data.items[i].current >= lastPrice){
volumeColor1.push(UP_COLOR);
}else{
volumeColor1.push(DOWN_COLOR);
} }else{
if(data.data.items[i].current >= data.data.items[i-1].current){
volumeColor1.push(UP_COLOR);
}else{
volumeColor1.push(DOWN_COLOR);
} } // 左下方柱状图
grid2Data.push([data.data.items[i].timestamp,data.data.items[i].volume]); }else{// 下午的数据 if(data.data.items[i].current > priceMax){
priceMax = data.data.items[i].current;
}
if(data.data.items[i].current < priceMin || priceMin == 0){
priceMin = data.data.items[i].current;
}
// 右上方折线图
grid3Data.push([data.data.items[i].timestamp,data.data.items[i].current]); if(data.data.items[i].volume > volumeMax){
volumeMax = data.data.items[i].volume;
}
if(data.data.items[i].volume < volumeMin){
volumeMin = data.data.items[i].volume;
} if(data.data.items[i].current >= data.data.items[i-1].current){
volumeColor2.push(UP_COLOR);
}else{
volumeColor2.push(DOWN_COLOR);
} // 右下方柱状图
grid4Data.push([data.data.items[i].timestamp,data.data.items[i].volume]); }
}
遍历完成后,得到了价格的最大最小值,成交量的最大值,接下来还要处理一下价格的最大最小值,以达到对称的效果。列入,昨日收盘价是1,今日最高价是上涨了0.5块,最高价是1+0.5 = 1.5块,那么为了达到对称的效果,下方的价格线应该是1-0.5=0.5块。
// 重新计算价格的最大最小值,以达到对称的效果
if((lastPrice - priceMax) * -1 > (lastPrice - priceMin)){
priceMin = (lastPrice - ((lastPrice - priceMax)* -1));
}else{
priceMax =(lastPrice + (lastPrice - priceMin));
} priceInterval = (priceMax - lastPrice) / 4;
volumeInterval = volumeMax / 2;
重新计算了最大最小价格,并得到了价格的差值,成交量的差值,把这些数值设置到对应的位置上。第一个跟第三个grid的y轴属性max,min,interval分别设置成priceMax,priceMin,priceInterval;第二个跟第四个grid的y轴属性max,min,interval分别设置成volumeMax,0,volumeInterval。然后我们会发现,y轴上的值的小数位非常大,x轴上显示的是月日时分的格式,所以还要对这些显示的数值进行格式化。首先对y轴的数据进行格式化,左上方的y轴设置:
axisLabel:{
fontSize:10,
margin:0,
// y轴的数值向内显示
align:"left",
formatter: function (value, index) {
return value.toFixed(2);
},
color: function (value, index) { // 中间基准线的数值为黑色
if(parseFloat(value).toFixed(2) == lastPrice){
return NORMAL_COLOR;
} // 上涨区域的数字为红色
if(value > lastPrice){
return UP_COLOR;
} // 下方下跌的数值为绿色
if(value < lastPrice){
return DOWN_COLOR;
} }
},
右上方的y轴的设置:
axisLabel:{
fontSize:10,
margin:0,
// y轴的数值向内显示
align:"right",
formatter: function (value, index) {
var persent = (value - lastPrice) / lastPrice;
persent = (persent < 0) ? persent * -1 : persent;
persent = persent * 100; return persent.toFixed(2) + '%';
},
color: function (value, index) { // 中间基准线的数值为黑色
if(parseFloat(value).toFixed(2) == lastPrice){
return NORMAL_COLOR;
} // 上涨区域的数字为红色
if(value > lastPrice){
return UP_COLOR;
} // 下方下跌的数值为绿色
if(value < lastPrice){
return DOWN_COLOR;
} }
},
下方的柱状图的y轴数值则隐藏不显示,只需要把第二个第四个grid的y轴的axisLabel.show设置成false即可
axisLabel:{
//设置显示坐标轴的数值为不显示
show:false
},
然后重新对x轴的时间进行格式化成HH:mm的格式,只需要对第二个跟第四个grid的x轴进行配置即可。
第二个grid的x轴的配置
axisLabel: {
fontSize:12,
show: true,
color:'#888',
formatter: function (value) {
var a = echarts.format.formatTime('hh:mm', value);
if(a == "11:30"){
return "";
}
if(a == "09:30"){
return " 09:30";
}
return a;
}
},
第四个grid的x轴的配置
axisLabel: {
fontSize:12,
show: true,
showMinLabel:false,
color:'#888',
formatter: function (value) {
var a = echarts.format.formatTime('hh:mm', value);
if(a == "13:00"){
return "11:30/13:00";
}
if(a == "15:00"){
return "15:00 ";
}
return a;
}
},
接下来配置一下柱状图的柱子颜色。在series里找到柱状图的配置,对itemStyle进行配置即可。
第一个柱状图的配置
itemStyle:{
normal: {
color: function (params) {
return volumeColor1[params.dataIndex];
}
}
}
第二个柱状图的配置
itemStyle:{
normal: {
color: function (params) {
return volumeColor2[params.dataIndex];
}
}
}
最后我们把各个坐标轴的小尖刺,就是刻度值旁边的短线去掉。把各个坐标轴的axisTick.show设置成false即可。
axisTick:{show:false}
做完这一步后,我们的代码就成了这样
// 雪球json数据 https://stock.xueqiu.com/v5/stock/chart/minute.json?symbol=SH000001&period=1d
var jsonData = '';
var data = JSON.parse(jsonData); // 第一个grid的数据(折线图)
var grid1Data = [];
// 第二个grid的数据(柱状图)
var grid2Data = [];
// 第三个grid数据(折线图)
var grid3Data = [];
// 第四个grid数据(柱状图)
var grid4Data = []; // 柱状图的颜色
// 柱状图的红绿规则比较麻烦,所以本次采用的规则则是根据价格的涨跌来区分
var volumeColor1 = [];
var volumeColor2 = []; var UP_COLOR = "#E24528";
var DOWN_COLOR = "#009933";
var NORMAL_COLOR = "#33353C"; var priceMax = 0,priceMin = 0,priceInterval = 0,volumeMax = 0,volumeMin = 0,volumeInterval = 0;
var lastPrice = data.data.last_close; initData(); function initData(){ for(var i in data.data.items){
// 上午的数据
if(i < 121){
if(data.data.items[i].current > priceMax){
priceMax = data.data.items[i].current;
}
if(data.data.items[i].current < priceMin || priceMin == 0){
priceMin = data.data.items[i].current;
}
// 左上方折线图
grid1Data.push([data.data.items[i].timestamp,data.data.items[i].current]); if(data.data.items[i].volume > volumeMax){
volumeMax = data.data.items[i].volume;
}
if(data.data.items[i].volume < volumeMin ){
volumeMin = data.data.items[i].volume;
} if(i == 0){ if(data.data.items[i].current >= lastPrice){
volumeColor1.push(UP_COLOR);
}else{
volumeColor1.push(DOWN_COLOR);
} }else{
if(data.data.items[i].current >= data.data.items[i-1].current){
volumeColor1.push(UP_COLOR);
}else{
volumeColor1.push(DOWN_COLOR);
} } // 左下方柱状图
grid2Data.push([data.data.items[i].timestamp,data.data.items[i].volume]); }else{// 下午的数据 if(data.data.items[i].current > priceMax){
priceMax = data.data.items[i].current;
}
if(data.data.items[i].current < priceMin || priceMin == 0){
priceMin = data.data.items[i].current;
}
// 右上方折线图
grid3Data.push([data.data.items[i].timestamp,data.data.items[i].current]); if(data.data.items[i].volume > volumeMax){
volumeMax = data.data.items[i].volume;
}
if(data.data.items[i].volume < volumeMin){
volumeMin = data.data.items[i].volume;
} if(data.data.items[i].current >= data.data.items[i-1].current){
volumeColor2.push(UP_COLOR);
}else{
volumeColor2.push(DOWN_COLOR);
} // 右下方柱状图
grid4Data.push([data.data.items[i].timestamp,data.data.items[i].volume]); }
} // 重新计算价格的最大最小值,以达到对称的效果
if((lastPrice - priceMax) * -1 > (lastPrice - priceMin)){
priceMin = (lastPrice - ((lastPrice - priceMax)* -1));
}else{
priceMax =(lastPrice + (lastPrice - priceMin));
} priceInterval = (priceMax - lastPrice) / 4;
volumeInterval = volumeMax / 2; setOptions();
} function setOptions(){ // 初始化一个echarts的对象
var chart = echarts.init(document.getElementById('charts')); // echarts折线图的配置项
var option = {
// grid
grid:[
// 第一个grid
{
top:10,// 图表的外边距
height:200,// 图表的高度
left:'0',
width:'50%',//因为是左右各一个图表,使用百分比的方式显得更方便,
},
// 第二个grid,第二个图表是在第一个图表的下方,所以要把它定位到底部
{
top:240,//设置上方的外边距是第一个图表的高度再加10,使用top是方便我们调整下方grid的高度
left:'0',
width:'50%',// 宽度与第一个图表一个大
height:100
},
// 第三个grid,第三个图表是在第一个图表的右方,所以要把它定位到右方
{
top:10,// 图表的外边距
left:'50%',//设置右边图表的左边距是第一个图表的大小,达到定位右边的效果
width:'50%',// 宽度与第一个图表一个大
height:200
},
// 第四个grid,第四个图表是在第三个图表的下方,所以要把它定位到底部
{
top:240,//设置上方的外边距是第三个图表的高度再加10,使用top是方便我们调整下方grid的高度
left:'50%',//设置右边图表的左边距是第三个图表的大小,达到定位右边的效果
width:'50%',// 宽度与第一个图表一个大
height:100
}
],
// 多个图表则会存在对个x轴y轴,所以这里的配置我们也换成数组的方式
// x轴配置,
xAxis:[
// 第一个grid的x轴属性
{ // 告诉echarts,这个第一个grid的x轴
gridIndex:0,
// 坐标轴是否留白
boundaryGap:false,
// x轴的刻度
axisTick:{show:false},
// x轴的刻度值
axisLabel:{show:false},
max:'dataMax',
min:'dataMin',
type: 'time',
axisLine:{
lineStyle:{
color:"#ECEEF2"
}
},
splitLine:{
lineStyle:{
color:"#ECEEF2",
// 设置线条喂风格为虚线
type:"dashed"
}
},
},
// 第二个grid的x轴属性
{
// 告诉echarts,这个第一个grid的x轴
gridIndex:1,
// 坐标轴是否留白
boundaryGap:false,
// x轴的刻度
axisTick:{show:false},
max:'dataMax',
min:'dataMin',
type: 'time',
axisLabel: {
fontSize:12,
show: true,
color:'#888',
formatter: function (value) {
var a = echarts.format.formatTime('hh:mm', value);
if(a == "11:30"){
return "";
}
if(a == "09:30"){
return " 09:30";
}
return a;
}
},
axisLine:{
lineStyle:{
color:"#ECEEF2"
}
},
splitLine:{
lineStyle:{
color:"#ECEEF2",
// 设置线条喂风格为虚线
type:"dashed"
}
},
},
// 第三个grid的x轴属性
{
// 告诉echarts,这个第一个grid的x轴
gridIndex:2,
// 坐标轴是否留白
boundaryGap:false,
// x轴的刻度
axisTick:{show:false},
// x轴的刻度值
axisLabel:{show:false},
type: 'time',
max:'dataMax',
min:'dataMin',
axisLine:{
lineStyle:{
color:"#ECEEF2"
}
},
splitLine:{
lineStyle:{
color:"#ECEEF2",
// 设置线条喂风格为虚线
type:"dashed"
}
},
},
// 第四个grid的x轴属性
{
// 告诉echarts,这个第一个grid的x轴
gridIndex:3,
// 坐标轴是否留白
boundaryGap:false,
// x轴的刻度
axisTick:{show:false},
type: 'time',
max:'dataMax',
min:'dataMin',
axisLabel: {
fontSize:12,
show: true,
showMinLabel:false,
color:'#888',
formatter: function (value) {
var a = echarts.format.formatTime('hh:mm', value);
if(a == "13:00"){
return "11:30/13:00";
}
if(a == "15:00"){
return "15:00 ";
}
return a;
}
},
axisLine:{
lineStyle:{
color:"#ECEEF2"
}
},
splitLine:{
lineStyle:{
color:"#ECEEF2",
// 设置线条喂风格为虚线
type:"dashed"
}
},
}
],
// y轴配置
yAxis: [
// 第一个grid的y轴属性
{
// 去掉刻度值旁边的指示线
axisTick:{show:false},
splitNumber:9,
gridIndex:0,
interval:priceInterval,
max:priceMax,
min:priceMin,
splitLine:{
lineStyle:{
color:"#ECEEF2",
// 设置线条喂风格为虚线
type:"dashed",
}
},
axisLine:{
lineStyle:{
color:"#ECEEF2"
}
},
axisLabel:{
fontSize:10,
margin:0,
// y轴的数值向内显示
align:"left",
formatter: function (value, index) {
return value.toFixed(2);
},
color: function (value, index) { // 中间基准线的数值为黑色
if(parseFloat(value).toFixed(2) == lastPrice){
return NORMAL_COLOR;
} // 上涨区域的数字为红色
if(value > lastPrice){
return UP_COLOR;
} // 下方下跌的数值为绿色
if(value < lastPrice){
return DOWN_COLOR;
} }
},
},
// 第二个grid的y轴属性
{
// 去掉刻度值旁边的指示线
axisTick:{show:false},
splitNumber:3,
gridIndex:1,
interval:volumeInterval,
max:volumeMax,
min:0,
splitLine:{
lineStyle:{
color:"#ECEEF2",
// 设置线条喂风格为虚线
type:"dashed"
}
},
axisLine:{
lineStyle:{
color:"#ECEEF2"
}
},
axisLabel:{
//设置显示坐标轴的数值为不显示
show:false
},
},
// 第三个grid的y轴属性
{
// 去掉刻度值旁边的指示线
axisTick:{show:false},
splitNumber:9,
position:'right',
gridIndex:2,
interval:priceInterval,
max:priceMax,
min:priceMin,
splitLine:{
lineStyle:{
color:"#ECEEF2",
// 设置线条喂风格为虚线
type:"dashed"
}
},
axisLine:{
lineStyle:{
color:"#ECEEF2"
}
},
axisLabel:{
fontSize:10,
margin:0,
// y轴的数值向内显示
align:"right",
formatter: function (value, index) {
var persent = (value - lastPrice) / lastPrice;
persent = (persent < 0) ? persent * -1 : persent;
persent = persent * 100; return persent.toFixed(2) + '%';
},
color: function (value, index) { // 中间基准线的数值为黑色
if(parseFloat(value).toFixed(2) == lastPrice){
return NORMAL_COLOR;
} // 上涨区域的数字为红色
if(value > lastPrice){
return UP_COLOR;
} // 下方下跌的数值为绿色
if(value < lastPrice){
return DOWN_COLOR;
} }
},
},
// 第四个grid的y轴属性
{
// 去掉刻度值旁边的指示线
axisTick:{show:false},
splitNumber:3,
position:'right',
gridIndex:3,
interval:volumeInterval,
max:volumeMax,
min:0,
axisLabel:{
//设置显示坐标轴的数值为不显示
show:false
},
splitLine:{
lineStyle:{
color:"#ECEEF2",
// 设置线条喂风格为虚线
type:"dashed"
}
},
axisLine:{
lineStyle:{
color:"#ECEEF2"
}
},
}
],
// 数据可以通过xAxisIndex,yAxisIndex属性,来指定是哪个grid的数据
series: [
// 第一个图表的数据
{
// 平滑曲线
smooth:true,
// 是否显示折线上的圆点
symbol:'none',
// 线条颜色
lineStyle:{
color:"#0481F8",
width:1
},
xAxisIndex:0,
yAxisIndex:0,
data: grid1Data,
type: 'line',
},
// 第二个图表的数据
{
xAxisIndex:1,
yAxisIndex:1,
// 柱状图柱子宽度
barWidth:1,
data: grid2Data,
type: 'bar',
// 设置柱状图颜色
itemStyle:{
normal: {
color: function (params) {
return volumeColor1[params.dataIndex];
}
}
}
},
// 第三个图表的数据
{
// 平滑曲线
smooth:true,
// 是否显示折线上的圆点
symbol:'none',
// 线条颜色
lineStyle:{
color:"#0481F8",
width:1
},
xAxisIndex:2,
yAxisIndex:2,
data: grid3Data,
type: 'line',
},
// 第四个图表的数据
{
xAxisIndex:3,
yAxisIndex:3,
// 柱状图柱子宽度
barWidth:1,
data: grid4Data,
type: 'bar',
// 设置柱状图颜色
itemStyle:{
normal: {
color: function (params) {
return volumeColor2[params.dataIndex];
}
}
}
}
]
}; chart.setOption(option); }
效果图如下:
我们的分时图已经基本完成了,但是我们还是能看到11:30/13:00这里有一段是没有连接上的,因为是两个图表的原因所以会断开,这个将在下一章修正。下一章我们将添加图表的一些指示器,修正一些小问题。
使用百度echarts仿雪球分时图(三)的更多相关文章
- 使用百度echarts仿雪球分时图(四)
这章节来收拾一下一些小BUG,顺便把各个小提示信息也补上,分时图也就完成了. 上章节末尾提到的一个bug,就是第一个grid跟第三个grid之间是断开的,折线并没有连在一起,所以先来收拾这个问题.没有 ...
- 使用百度echarts仿雪球分时图(一)
第一次写技术博客,有不足的地方希望大家指证出来,我再加以改正,谢谢大家. 之前一直没有找到一个合适的分时图项目,所以决定自己动手撸一个.接触的图表框架不多,在网上看到不少人推荐使用echarts,看了 ...
- 使用百度echarts仿雪球分时图(二)
上一章简单的介绍了一下分时图的构成,其实就是折线图跟柱状图的组成.本来这章打算是把分时图做完,然后再写一章来进行美化和总结,但是仔细观察了一下,发现其实东西还是有点多的.分时图的图表做完后,还要去美化 ...
- 使用百度Echarts制作力导向图
最近项目需求制作一个力导向图来展示企业的画像等关系信息,故想到了百度Echarts的关系图,在这使用Echarts3.0版本来实现.先上效果图,再看代吗 哎,本来想整个工程扔出来,发现好像没地方上传附 ...
- WPF仿百度Echarts人口迁移图
GitHub地址:https://github.com/ptddqr/wpf-echarts-map/tree/master 关于大名鼎鼎的百度Echarts我就不多说了 不了解的朋友直接看官方的例子 ...
- C#+JQuery+.Ashx+百度Echarts实现全国省市地图和饼状图动态数据图形报表的统计
在目前的一个项目中,需要用到报表表现数据,这些数据有多个维度,需要同时表现出来,同时可能会有大量数据呈现的需求,经过几轮挑选,最终选择了百度的echarts作为报表基础类库.echarts功能强大,界 ...
- 手把手教你画AndroidK线分时图及指标
先废话一下:来到公司之前.项目是由外包公司做的,面试初,没有接触过分时图k线这块,认为好难,我能搞定不.可是一段时间之后,发现之前做的那是一片稀烂,可是这货是主功能啊.迟早的自己操刀,痛下决心,开搞, ...
- iOS-Andriod百度地图仿百度外卖-饿了么-选择我的地址-POI检索/
http://zanderzhang.gitcafe.io/2015/09/19/iOS-Andriod百度地图仿百度外卖-饿了么-选择我的地址-POI检索/ 百度外卖选择送货地址: 饿了么选择送货地 ...
- Android 仿PhotoShop调色板应用(三) 主体界面绘制
版权声明:本文为博主原创文章,未经博主允许不得转载. Android 仿PhotoShop调色板应用(三) 主体界面绘制 关于PhotoShop调色板应用的实现我总结了两个最核心的部分: 1 ...
随机推荐
- Java同步数据结构之PriorityBlockingQueue
前言 接下来继续BlockingQueue的另一个实现,优先级阻塞队列PriorityBlockingQueue.PriorityBlockingQueue是一个无限容量的阻塞队列,由于容量是无限的所 ...
- PCA人脸识别学习笔记---代码篇
查看并改变当前的工作路径 path="D:\\python-file\\faker" os.chdir(path) retval=os.getcwd() print(retval) ...
- as 什么意思?
You can denote particular console messages and variable values as having different types using four ...
- natively 在本地机器
For JavaScript-based projects, it makes sense to have a command line task runner that executes Java ...
- ios 自动去重
//resultArrM 数据原//_indexArray 过滤后的数据//MYSelectAreaModel 模型 /* 重定义索引 */ - (void)sy_indexArray{ /* 索 ...
- nginx反向代理本地 单台wed -使用ip+端口代理
环境: 本地外网ip:123.58.251.166 .配置index.html网页 [root@host---- conf.d]# cat /web/sing/index.html <h1> ...
- C-Lodop提示Access violation at address ...in module 'CLodopPrint32.exe' write of address
C-Lodop提示 Access violation at address ……in module 'CLodopPrint32.exe' write of address ……最近遇到了个问题,上午 ...
- unity读取灰度图生成等值线图
准备灰度图 grayTest.png,放置于Assets下StreamingAssets文件夹中. 在场景中添加RawImage用于显示最后的等值线图. 生成等值线的过程,使用Marching ...
- 如何解决docker 官方镜像拉取慢的问题
转自: http://skycity.today/?thread-307.htm 国内从 docker 官方 Registry 拉取 image 慢的解决,步骤如下: 1.注册一个阿里云账号. 2.阿 ...
- HTML-T
a标签跳转 <a href="new_link" target="_blank">在新建页面打开链接</a>. <a href=& ...