使用百度echarts仿雪球分时图(四)

  这章节来收拾一下一些小BUG,顺便把各个小提示信息也补上,分时图也就完成了。

  上章节末尾提到的一个bug,就是第一个grid跟第三个grid之间是断开的,折线并没有连在一起,所以先来收拾这个问题。没有连着一起的原因主要是第一个grid的最后一条数据的值,跟第三个grid的第一条数据不一样,而且grid之间是不会帮你把这两个点连接起来的,所以会出现一上一下的断崖。知道了是什么原因,那就知道该怎么办了。在遍历数据的时候,我们先往grid3Data数据里加一条数据,这条数据的值是grid1Data的最后一条数据,也就是11:30的那条数据,这样第一个grid的最后一条数据跟第三个grid的第一条数据就一样了,这样就可以连起来了。但是还会有个问题,因为第三个grid跟第四个grid的x轴类型是 ‘time’类型,但是第一条数据是11:30,第二条数据是13:00,如果继续使用'time'类型的话,第三个grid会有很长一条直线,就是11:30到13:00之间这一段会很平的,所以第三第四个grid不能使用'time'类型了,改用'category'类目类型。改用'category'类型后,要新建两个数组来存放x轴的时间,分别是grid3DateData,grid4DateData,然后grid3Data和grid4Data存放的不再是数组,而是数值。

  遍历数据的代码稍微修改一下。下午数据的部分修改为

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;
                        }
                        // 第三grid的数据先添加一条数据
                        if(grid3Data.length == 0){        
                            grid3Data.push(data.data.items[i-1].current);
                            grid3DateData.push(data.data.items[i-1].timestamp);
                        }
                        // 右上方折线图
                        grid3Data.push(data.data.items[i].current);
                        grid3DateData.push(data.data.items[i].timestamp);
                        
                        
                        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);
                         }
                    
                        // 第四grid的数据先添加一条数据
                        if(grid4Data.length == 0){
                            grid4Data.push(data.data.items[i-1].volume);
                            grid4DateData.push(data.data.items[i-1].timestamp);
                        }
                        // 右下方柱状图
                        grid4Data.push(data.data.items[i].volume);
                        grid4DateData.push(data.data.items[i].timestamp);

然后第三第四个grid的x 轴配置中,data分别设置成grid3DateData和grid4DateData。然后又出现新的问题,x轴的坐标轴线分布不均匀,因为我们用的是 category 的类型,而且我们x轴的数据很多,echarts为了保证能够显示足够的x轴的文字,所以会出现跳跃性的线条,显得分布不均匀。还好,echarts中是有属性可以自定义去显示哪条x轴坐标轴线。就是xAxis.splitLine.interval这个属性,可以设置数字,也可以是回调方法,interval这个属性很熟悉了,就是线条的间隔,所以接下来使用回调方法的方式来显示需要显示的线条。第三第四个grid的xAxis.splitLine.interval属性都是这样写的

interval:function(index,value){
                                        // 第一条第二条线是不需要显示的,第一条是11:30的,第一个grid已经有这条数据了,所以不需要显示
                                        // 第二条显示的话,在中间部分会出现2条线,所以也不要显示
                                        if(index == 0 || index == 1){
                                            return false;
                                        }
                                        // 这里的意思是第一条数据后,每30分钟显示一条线
                                        if((index - 1) % 30 == 0){
                                            return true;
                                        }
                                        return false;
                                    }

这么一改,不连接的问题就解决了。

 

  接下来把各个提示信息调整出来。首先要把指示器axisPointer这个属性配置一下,axisPointer有分为公共配置和各个坐标轴的单独配置。公共配置是配置一些公共的属性,各个坐标轴的配置则是配置不同坐标轴的样式,以及文字的格式化。这里我们两者都需要进行配置。

  公共配置部分

  axisPointer.show默认是false的,我们设置成true,指示器就出来了,但是会发现,线条也是断开的,只会显示其中的一个grid的线条,这里需要配置一下axisPointer.link属性来联动。link属性的介绍:不同轴的 axisPointer 可以进行联动,在这里设置。联动表示轴能同步一起活动。轴依据他们的 axisPointer 当前对应的值来联动,link 是一个数组,其中每一项表示一个 link group,一个 group 中的坐标轴互相联动。这里我们属性link的xAxisIndex和yAxisIndex属性,这两个属性是数组类型,里面值是数值,也就是grid的下标。重新看一下分时图,我们放鼠标在左上方的的区域,我们希望的是x轴是第一个第二个grid联动,y轴则是第一个第三个联动;放在右上方边的区域的话,x轴是第三个第四个grid联动,y轴还是第一个第三个联动。以此类推出左下方右下方的联动,得到的代码是这样的

axisPointer:{
    show:true,
    // 配置线条风格为虚线风格
    lineStyle:{
        type:'dashed'
    },
    link:[
        {
            xAxisIndex:[0,1],
        },{
            xAxisIndex:[2,3],
        },{
            yAxisIndex:[0,2]
        },{
            yAxisIndex:[1,3]
        }
    ]
},

再看一下雪球的分时图,发现分时图有指示器的地方分别是第一个第二个第三个grid的y轴,第二个第四个grid的x轴,那么接下来要单独配置一下各个坐标轴的指示器。

所有指示器的show属性都设置成true,显示与否则通过label.show属性来控制。第一个第二个第三个grid的y轴的指示器的 label.show属性我们都设置成true,第四个则设置成false。第二个第四个grid的x轴的指示器的label.show属性设置成true,第一个第三个grid的x轴的指示器设置成false。设置完成后,成功的只显示了需要显示的指示器,但是默认的样式却不是我们想看到的样式。接下来美化一下

  1.字体太大了,把label.fontSize调成10。

  2.内边距太大了,把label.padding调成2即可。

  3.阴影效果也不需要了,把label.shadowBlur调成0。

  4.字体颜色也改成深色的,设置label.color即可。

经过调整后,样式已经达到我们的要求,但是指示器上的文字还没达到要求,那么就使用label.formatter的回调函数进行格式化,不同的坐标轴的格式化方式不一样,这里不花太大篇幅去讲解。

第一个第三个grid的x轴指示器配置

axisPointer:{
    show:true,
    label:{
        show:false
    }
}

第一个grid的y轴指示器配置

axisPointer:{
    show:true,
    type:"line",
    label:{
        show:true,
        fontSize:10,
        margin:-44,
        padding:2,
        shadowBlur:0,
        color:"#33353C",
        formatter:function(data){
            
            return data.value.toFixed(2);
        }
    },
}

第三个grid的y轴指示器配置

axisPointer:{
    show:true,
    type:"line",
    label:{
        show:true,
        fontSize:10,
        margin:-34,
        padding:2,
        shadowBlur:0,
        color:"#33353C",
        formatter:function(data){
            var persent = (data.value - lastPrice) / lastPrice;
            persent = (persent < 0) ? persent * -1 : persent;
            persent = persent * 100;

            return persent.toFixed(2) + '%';
        }
    },
 }

第二个grid的x轴指示器配置

axisPointer:{
    show:true,
    type:"line",
    label:{
        show:true,
        fontSize:10,
        margin:0,
        padding:2,
        shadowBlur:0,
        color:"#33353C",
        formatter:function(data){
            return echarts.format.formatTime('hh:mm', parseFloat(data.value))
        }
    },
}

第二个grid的y轴指示器配置

axisPointer:{
    show:true,
    type:"line",
    label:{
        show:true,
        fontSize:10,
        padding:2,
        shadowBlur:0,
        color:"#33353C",
        formatter:function(data){
            if(data.value > 1000000){
                return parseFloat(data.value / 1000000).toFixed(2)+"万手";
            }
            return data.value;
        }
    },
}

第四个grid的x轴指示器配置

axisPointer:{
    show:true,
    type:"line",
    label:{
        show:true,
        fontSize:10,
        margin:0,
        padding:2,
        shadowBlur:0,
        color:"#33353C",
        formatter:function(data){
            return echarts.format.formatTime('hh:mm', parseFloat(data.value));
        }
    },
}

第四个grid的y轴指示器配置

axisPointer:{
    show:true,
    label:{
        show:false
    }
}

到这里,所有坐标轴的指示器都设置完成了,效果也如预期那样。最后还有一个悬浮的提示框需要配置,配置完后我们的分时图就完成了。

配置悬浮的提示框主要是配置根属性的tooltip属性。tooltip有个一个trigger的触发类型属性,item:数据项图形触发,主要在散点图,饼图等无类目轴的图表中使用;axis:坐标轴触发,主要在柱状图,折线图等会使用类目轴的图表中使用;none:什么都不触发因为默认是item这里把触发类型改成 axis ,提示框就会出来了。但是提示框的位置还有样式,都不是我们想要的,又要再给它美化一下。首先我们先对它的位置进行固定,使用position属性进行配置,position可以是字符串,数组,回调函数,要高度自定义的话,显然回调函数比较合适,回调函数返回一个对象,这个对象与CSS的position属性类型,对象里面是使用top,right,bottom,left属性来控制位置的,我们可以根据回调函数里的5个回调参数来进行相应的配置,这5个回调参数分别是:

point: 鼠标位置,如 [20, 40]。
params: 同 formatter 的参数相同。
dom: tooltip 的 dom 对象。
rect: 只有鼠标在图形上时有效,是一个用xywidthheight四个属性表达的图形包围盒。
size: 包括 dom 的尺寸和 echarts 容器的当前尺寸,例如:{contentSize: [width, height], viewSize: [width, height]}

point属性是鼠标当前的x值和y值;params跟formatter的参数相同,但是我们不需要格式化的相关配置,所以这个可以不用;dom对象,这个先保留;rect这个属性是鼠标放在提示框上才会有效,否则就是undefined,要想鼠标能放到提示框上,要配置enterable属性为true,但是我们不需要放鼠标上去,所以不需要;size属性,里面的contentSize属性指的是提示框的宽高,viewSize则是整个图表的大小,我们需要size的viewSize结合point鼠标位置属性来对提示框进行一个位置的定位。

我们要做的效果是鼠标在左边图表的时候,提示框在右边,鼠标在右侧图表的的时候,提示框在左边,那么就要对返回对象的left值或者right值进行配置了。判断鼠标是在左边还是在右边很简单,只需要判断鼠标的x值是否大于第一个第二个grid的宽度即可,因为左右两边的宽度是相等的,所以第一个第二个grid的宽度就是viewSize[width] / 2,只要鼠标位置的x值大于这个值,那就是鼠标在右边,小于这个值那就是在左边;同时我们要固定在头部,所以要把top值也设置一下。

position:function(point, params, dom, rect, size){
    var obj ={
        top:10
    }
    
    if(point[0] > size.viewSize[0] / 2){
        obj["left"] = 70;
    }else{
        obj["right"] = 70;
    }

    return obj;
}

位置调整好后,开始整理样式。

  1.文字的颜色通过textStyle.color属性设置成黑色

  2.设置边框,borderWidth:1,borderColor:'#ECEEF2'

  3.设置背景色为白色半透明,backgroundColor:'rgba(255,255,255,0.9)'

  4.动画效果也不要了,直接设置动画时长为0,transitionDuration:0

样式调整好后,提示框的文字也需要进行一次格式化,在formatter的回调函数中进行配置。因为提示框的渲染方式renderMode,默认是html,所以回调函数里面我们可以配合CSS来编写我们自己的html。formatter的回调参数有3个,分别是:

  1.params,这是提示框里面展示的数据的数据集。

  2.ticket,这是异步回调的标识,数据格式跟params是一样的,一般配合第三个参数callback使用

  3.callback,异步回调,与第二个参数ticket配合进行异步的数据展示。例如提示框中需要进行数据获取的请求时,可以用到这个组合。

这里我们不需要异步请求数据,所以直接使用params的数据进行展示。首先我们要遍历params数据集,拿到里面的数据,再通过数据集的数据名称seriesName进行判断是什么数据,对数据进行格式化,最后拼接成一段html用于渲染。(注:seriesName可以在series中,对数据进行命名) 

  命名数据

// 第一个图表的数据
{
    name:"最新1",
    // 平滑曲线
    smooth:true,
    // 是否显示折线上的圆点
    symbol:'none',
    // 线条颜色
    lineStyle:{
        color:"#0481F8",
        width:1
    },
    xAxisIndex:0,
    yAxisIndex:0,
    data: grid1Data,
    type: 'line',
    z:3,
    areaStyle:{
        color:"#F8FAFF"
    }
},

formatter回调函数

formatter:function(params,ticket,callback){
    var html = '';
    var x,j,c;

    for(var d in params){
        if(params[d].seriesName == '成交量1' || params[d].seriesName == '成交量2' ){
            c = params[d];
        }
        if(params[d].seriesName == '最新1' || params[d].seriesName == '最新2' ){
            x = params[d];
        }

    }
     
    if(!c.axisValue){
        return;
    }
    

    html += '<div class="tooltips-item"><span class="name">时间</span><span class="value">'+ echarts.format.formatTime('MM-dd hh:mm',parseFloat(c.axisValue)) +'</span></div>';
    html += '<div class="tooltips-item"><span class="name">最新</span><span class="value '+ colorCls((typeof x.data == 'number' ? x.data : x.data[1])) +'">'+ (typeof x.data == 'number' ? x.data : x.data[1]) +'</span></div>';
    html += '<div class="tooltips-item"><span class="name">涨跌幅</span><span class="value '+ colorCls((typeof x.data == 'number' ? x.data : x.data[1])) +'">'+ ((((typeof x.data == 'number' ? x.data : x.data[1]) - lastPrice)/ lastPrice * 100).toFixed(2)) +'%</span></div>';
    html += '<div class="tooltips-item"><span class="name">涨跌额</span><span class="value '+ colorCls((typeof x.data == 'number' ? x.data : x.data[1])) +'">'+ ((typeof x.data == 'number' ? x.data : x.data[1])- lastPrice).toFixed(2) +'</span></div>';
    html += '<div class="tooltips-item"><span class="name">成交量</span><span class="value">'+ (typeof c.data == 'number' ? (c.data / 1000000).toFixed(2) : (c.data[1] / 1000000).toFixed(2)) +'万手</span></div>';

    return html;
}

部分CSS

#charts{
    /*折线图的宽度*/
    width:640px;
    /*折线图的高度*/
    height:390px;
}
.tooltips-item{
    display:flex;
    display:-webkit-flex;
    justify-content: space-between;
    color:#33333c;
    font-size:10px;
    width:120px;
}
.green{
    color:#009933
}
.red{
    color:#E24528
}

到这里,提示框的配置也完成了。仿分时图系列就结束了。

最终效果图如下

  

 完整的代码

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>分时图</title>
        <script type="text/javascript" src="js/jQuery.js" ></script>
        <script type="text/javascript" src="js/echarts.min.js" ></script>
        <style>
            #charts{
                /*折线图的宽度*/
                width:640px;
                /*折线图的高度*/
                height:390px;
            }
            .tooltips-item{
                display:flex;
                display:-webkit-flex;
                justify-content: space-between;
                color:#33333c;
                font-size:10px;
                width:120px;
            }
            .green{
                color:#009933
            }
            .red{
                color:#E24528
            }
        </style>
    </head>
    <body>
        <div id="charts">
            
        </div>
        <script type="text/javascript">
            // 雪球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 = [];
            var grid3DateData = [];
            // 第四个grid数据(柱状图)
            var grid4Data = [];
            var grid4DateData = [];
            
            // 柱状图的颜色
            // 柱状图的红绿规则比较麻烦,所以本次采用的规则则是根据价格的涨跌来区分
            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 colorCls(num){
                if(num > lastPrice){
                    return "red";
                }else if(num == lastPrice){
                    return "";
                }
                return "green";
            }
            
            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;
                        }
                        // 第三grid的数据先添加一条数据
                        if(grid3Data.length == 0){        
                            grid3Data.push(data.data.items[i-1].current);
                            grid3DateData.push(data.data.items[i-1].timestamp);
                        }
                        // 右上方折线图
                        grid3Data.push(data.data.items[i].current);
                        grid3DateData.push(data.data.items[i].timestamp);
                        
                        
                        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);
                         }
                    
                        // 第四grid的数据先添加一条数据
                        if(grid4Data.length == 0){
                            grid4Data.push(data.data.items[i-1].volume);
                            grid4DateData.push(data.data.items[i-1].timestamp);
                        }
                        // 右下方柱状图
                        grid4Data.push(data.data.items[i].volume);
                        grid4DateData.push(data.data.items[i].timestamp);
                        
                        
                    }
                }
                
                // 重新计算价格的最大最小值,以达到对称的效果
                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(){
                
                var nowDate;
                
                // 初始化一个echarts的对象
                var chart =  echarts.init(document.getElementById('charts'));
                
                // echarts折线图的配置项
                var option = {
                    animation:false,
                    //坐标轴指示器
                    axisPointer:{
                        show:true,
                        // 配置线条风格为虚线风格
                        lineStyle:{
                            type:'dashed'
                        },
                        link:[
                            {
                                xAxisIndex:[0,1],
                            },{
                                xAxisIndex:[2,3],
                            },{
                                yAxisIndex:[0,2]
                            },{
                                yAxisIndex:[1,3]
                            }
                        ]
                    },
                    // 悬浮框
                    tooltip:{
                        trigger:'axis',
                        position:function(point, params, dom, rect, size){
                            var obj ={
                                top:10
                            }
                            
                            console.log(size);
                            
                            if(point[0] > size.viewSize[0] / 2){
                                obj["left"] = 70;
                            }else{
                                obj["right"] = 70;
                            }

                            return obj;
                        },
                        formatter:function(params,ticket,callback){
                            var html = '';
                            var x,j,c;
            
                            for(var d in params){
                                if(params[d].seriesName == '成交量1' || params[d].seriesName == '成交量2' ){
                                    c = params[d];
                                }
                                if(params[d].seriesName == '最新1' || params[d].seriesName == '最新2' ){
                                    x = params[d];
                                }

                            }
                             
                            if(!c.axisValue){
                                return;
                            }
                            
            
                            html += '<div class="tooltips-item"><span class="name">时间</span><span class="value">'+ echarts.format.formatTime('MM-dd hh:mm',parseFloat(c.axisValue)) +'</span></div>';
                            html += '<div class="tooltips-item"><span class="name">最新</span><span class="value '+ colorCls((typeof x.data == 'number' ? x.data : x.data[1])) +'">'+ (typeof x.data == 'number' ? x.data : x.data[1]) +'</span></div>';
                            html += '<div class="tooltips-item"><span class="name">涨跌幅</span><span class="value '+ colorCls((typeof x.data == 'number' ? x.data : x.data[1])) +'">'+ ((((typeof x.data == 'number' ? x.data : x.data[1]) - lastPrice)/ lastPrice * 100).toFixed(2)) +'%</span></div>';
                            html += '<div class="tooltips-item"><span class="name">涨跌额</span><span class="value '+ colorCls((typeof x.data == 'number' ? x.data : x.data[1])) +'">'+ ((typeof x.data == 'number' ? x.data : x.data[1])- lastPrice).toFixed(2) +'</span></div>';
                            html += '<div class="tooltips-item"><span class="name">成交量</span><span class="value">'+ (typeof c.data == 'number' ? (c.data / 1000000).toFixed(2) : (c.data[1] / 1000000).toFixed(2)) +'万手</span></div>';

                            return html;
                        },
                        textStyle:{
                            color:"#000"
                        },
                        borderWidth:1,
                        borderColor:"#ECEEF2",
                        backgroundColor:"rgba(255,255,255,0.9)",
                        transitionDuration:0,
                        axisPointer:{
                            animation:false,
                            type:"cross"
                        }
                    },
                    // grid
                    grid:[
                        // 第一个grid
                        {
                            top:10,// 图表的外边距
                            height:240,// 图表的高度
                            left:'5%',
                            width:'45%',//因为是左右各一个图表,使用百分比的方式显得更方便,
                        },
                        // 第二个grid,第二个图表是在第一个图表的下方,所以要把它定位到底部
                        {
                            top:280,//设置上方的外边距是第一个图表的高度再加10,使用top是方便我们调整下方grid的高度
                            left:'5%',
                            width:'45%',// 宽度与第一个图表一个大
                            height:80,
                        },
                        // 第三个grid,第三个图表是在第一个图表的右方,所以要把它定位到右方
                        {
                            top:10,// 图表的外边距
                            left:'50%',//设置右边图表的左边距是第一个图表的大小,达到定位右边的效果
                            width:'45%',// 宽度与第一个图表一个大
                            height:240,
                        },
                        // 第四个grid,第四个图表是在第三个图表的下方,所以要把它定位到底部
                        {
                            top:280,//设置上方的外边距是第三个图表的高度再加10,使用top是方便我们调整下方grid的高度
                            left:'50%',//设置右边图表的左边距是第三个图表的大小,达到定位右边的效果
                            width:'45%',// 宽度与第一个图表一个大
                            height:80,
                        }
                    ],
                    // 多个图表则会存在对个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',
                                axisPointer:{
                                    show:true,
                                    label:{
                                        show:false
                                    }
                                },
                                axisLine:{
                                    lineStyle:{
                                        color:"#ECEEF2"
                                    }
                                },
                                splitLine:{
                                    lineStyle:{
                                        color:"#ECEEF2",
                                        type:"solid"
                                    }
                                },
                            },
                            // 第二个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 "11:30/13:00";
                                        }
                                        if(a == "09:30"){
                                            return "        09:30";
                                        }
                                        return a;
                                    }
                                },
                                axisLine:{
                                    lineStyle:{
                                        color:"#ECEEF2"
                                    }
                                },
                                splitLine:{
                                    lineStyle:{ 
                                        color:"#ECEEF2",
                                        type:"solid"
                                    }
                                },
                                axisPointer:{
                                    show:true,
                                    type:"line",
                                    label:{
                                        show:true,
                                        fontSize:10,
                                        margin:0,
                                        padding:2,
                                        shadowBlur:0,
                                        color:"#33353C",
                                        formatter:function(data){
                                            return echarts.format.formatTime('hh:mm', parseFloat(data.value))
                                        }
                                    },
                                },
                            },
                            // 第三个grid的x轴属性
                            {
                                // 告诉echarts,这个第一个grid的x轴
                                gridIndex:2,
                                // 坐标轴是否留白
                                boundaryGap:false,
                                // x轴的刻度
                                axisTick:{show:false},
                                // x轴的刻度值
                                axisLabel:{show:false},
                                type: 'category',
                                data:grid3DateData,
                                axisLine:{
                                    lineStyle:{
                                        color:"#ECEEF2"
                                    }
                                },
                                max:"dataMax",
                                min:"dataMin",
                                axisPointer:{
                                    show:true,
                                    label:{
                                        show:false
                                    }
                                },
                                splitLine:{
                                    show:true,
                                    lineStyle:{
                                        color:"#ECEEF2",
                                        type:"solid"
                                    },
                                    interval:function(index,value){
                                        if(index == 0 || index == 1){
                                            return false;
                                        }
                                        
                                        if((index - 1) % 30 == 0){
                                            return true;
                                        }
                                        return false;
                                    },
                                },
                            },
                            // 第四个grid的x轴属性
                            {
                                // 告诉echarts,这个第一个grid的x轴
                                gridIndex:3,
                                // 坐标轴是否留白
                                boundaryGap:false,
                                // x轴的刻度
                                axisTick:{
                                    show:false
                                },
                                type: 'category',
                                max:"dataMax",
                                min:"dataMin",
                                data:grid4DateData,
                                axisLabel: {
                                    fontSize:12,
                                    show: true,
                                    showMinLabel:false,
                                    color:'#888',
                                    interval:function(index,value){
                                        
                                        if((index - 1)  % 30 == 0){
                                            return true;
                                        }
                                        return false;
                                    },
                                    formatter: function (value) {
                                        var a = echarts.format.formatTime('hh:mm', parseFloat(value));
                                        if(a == "15:00"){
                                            return "15:00        ";
                                        }
                                        return a;
                                    }
                                },
                                axisLine:{
                                    lineStyle:{
                                        color:"#ECEEF2"
                                    }
                                },
                                splitLine:{
                                    show:true,
                                    lineStyle:{
                                        color:"#ECEEF2",
                                        type:"solid"
                                    },
                                    interval:function(index,value){
                                        // 第一条第二条线是不需要显示的,第一条是11:30的,第一个grid已经有这条数据了,所以不需要显示
                                        // 第二条显示的话,在中间部分会出现2条线,所以也不要显示
                                        if(index == 0 || index == 1){
                                            return false;
                                        }
                                        // 这里的意思是第一条数据后,每30分钟显示一条线
                                        if((index - 1) % 30 == 0){
                                            return true;
                                        }
                                        return false;
                                    },
                                },
                                axisPointer:{
                                    show:true,
                                    type:"line",
                                    label:{
                                        show:true,
                                        fontSize:10,
                                        margin:0,
                                        padding:2,
                                        shadowBlur:0,
                                        color:"#33353C",
                                        formatter:function(data){
                                            return echarts.format.formatTime('hh:mm', parseFloat(data.value));
                                        }
                                    },
                                },
                            }
                        ],
                    // y轴配置
                    yAxis: [
                        // 第一个grid的y轴属性
                        {    
                            // 去掉刻度值旁边的指示线
                            axisTick:{show:false},
                            splitNumber:9,
                            gridIndex:0,
                            interval:priceInterval,
                            max:priceMax,
                            min:priceMin,
                            splitLine:{
                                lineStyle:{
                                    color:"#ECEEF2",
                                    type:"solid",
                                }
                            },
                            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;
                                    }
                                    
                                }
                            },
                            z:3,
                            axisPointer:{
                                show:true,
                                type:"line",
                                label:{
                                    show:true,
                                    fontSize:10,
                                    margin:-44,
                                    padding:2,
                                    shadowBlur:0,
                                    color:"#33353C",
                                    formatter:function(data){
                                        
                                        return data.value.toFixed(2);
                                    }
                                },
                            },
                        },
                        // 第二个grid的y轴属性
                        {
                            // 去掉刻度值旁边的指示线
                            axisTick:{show:false},
                            splitNumber:3,
                            gridIndex:1,
                            interval:volumeInterval,
                            max:volumeMax,
                            min:0,
                            splitLine:{
                                lineStyle:{
                                    color:"#ECEEF2",
                                    type:"solid"
                                }
                            },
                            axisLine:{
                                lineStyle:{
                                    color:"#ECEEF2"
                                }
                            },
                            axisPointer:{
                                show:true,
                                type:"line",
                                label:{
                                    show:true,
                                    fontSize:10,
                                    padding:2,
                                    shadowBlur:0,
                                    color:"#33353C",
                                    formatter:function(data){
                                        if(data.value > 1000000){
                                               return parseFloat(data.value / 1000000).toFixed(2)+"万手";
                                           }
                                        return data.value;
                                    }
                                },
                            },
                            axisLabel:{
                                align:"left",
                                verticalAlign:"top",
                                //设置显示坐标轴的数值为不显示
                                show:true,
                                fontSize:10,
                                margin:0,
                                showMaxLabel:true,
                                showMinLabel:false,
                                color:"#33353C",
                                formatter: function (value, index) {
                                    // 格式化成月/日,只在第一个刻度显示年份 
                                   if(value == volumeMax){
                                           // 方便演示
                                           if(value > 1000000){
                                               value = parseFloat(value / 1000000).toFixed(2)+"万手"
                                           }
                                           
                                           return value;
                                   }
                                   return "";
                                }
                            },
                        },
                        // 第三个grid的y轴属性
                        {
                            // 去掉刻度值旁边的指示线
                            axisTick:{show:false},
                            splitNumber:9,
                            position:'right',
                            gridIndex:2,
                            interval:priceInterval,
                            max:priceMax,
                            min:priceMin,
                            splitLine:{
                                lineStyle:{
                                    color:"#ECEEF2",
                                    type:"solid"
                                }
                            },
                            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;
                                    }
                                    
                                }
                            },
                            z:3,
                            axisPointer:{
                                show:true,
                                type:"line",
                                label:{
                                    show:true,
                                    fontSize:10,
                                    margin:-34,
                                    padding:2,
                                    shadowBlur:0,
                                    color:"#33353C",
                                    formatter:function(data){
                                        var persent = (data.value - lastPrice) / lastPrice;
                                        persent = (persent < 0) ? persent * -1 : persent;
                                        persent = persent * 100;
                
                                        return persent.toFixed(2) + '%';
                                    }
                                },
                            },
                        },
                        // 第四个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:"solid"
                                }
                            },
                            axisPointer:{
                                show:true,
                                label:{
                                    show:false
                                }
                            },
                            axisLine:{
                                lineStyle:{
                                    color:"#ECEEF2"
                                }
                            },
                        }
                    ],
                    // 数据可以通过xAxisIndex,yAxisIndex属性,来指定是哪个grid的数据
                    series: [
                        // 第一个图表的数据
                        {
                            name:"最新1",
                            // 平滑曲线
                            smooth:true,
                            // 是否显示折线上的圆点
                            symbol:'none',
                            // 线条颜色
                            lineStyle:{
                                color:"#0481F8",
                                width:1
                            },
                            xAxisIndex:0,
                            yAxisIndex:0,
                            data: grid1Data,
                            type: 'line',
                            z:3,
                            areaStyle:{
                                color:"#F8FAFF"
                            }
                        },
                         // 第二个图表的数据
                        {
                            name:"成交量1",
                            xAxisIndex:1,
                            yAxisIndex:1,
                            // 柱状图柱子宽度
                            barWidth:1,
                            data: grid2Data,
                            type: 'bar',
                            // 设置柱状图颜色
                            itemStyle:{
                                normal: {
                                    color: function (params) {
                                        return volumeColor1[params.dataIndex];
                                    }
                                }
                            }
                        },
                         // 第三个图表的数据
                        {
                            name:"最新2",
                            // 平滑曲线
                            smooth:true,
                            // 是否显示折线上的圆点
                            symbol:'none',
                            // 线条颜色
                            lineStyle:{
                                color:"#0481F8",
                                width:1
                            },
                            z:3,
                            xAxisIndex:2,
                            yAxisIndex:2,
                            data: grid3Data,
                            type: 'line',
                            areaStyle:{
                                color:"#F8FAFF"
                            }
                        },
                         // 第四个图表的数据
                        {
                            name:"成交量2",
                            xAxisIndex:3,
                            yAxisIndex:3,
                            // 柱状图柱子宽度
                            barWidth:1,
                            data: grid4Data,
                            type: 'bar',
                            // 设置柱状图颜色
                            itemStyle:{
                                normal: {
                                    color: function (params) {
                                        return volumeColor2[params.dataIndex];
                                    }
                                }
                            }
                        }
                    ]
                };
                
                chart.setOption(option);
                
            }

        </script>
    </body>
</html>

 

  总结:一开始做分时图的时候我也不懂从哪开始做,慢慢观察后才发现其实可以由折线图跟柱状图来拼接而成。知道拼接可以达到效果后,就开始写代码,期间也是遇到了很多问题,最开始是用两个echarts来组合,发现效果很丑,去查了一下文档,发现可以用grid来解决,接着就拆成了上下两个grid;然后上下午时间段这个问题,由于不是连续的,所以一个折线图解决不了,再次拆图表,把上下方的图表再一拆为二,拆成了两个后折线图出现了断崖式的效果,经过很多尝试后,把x轴的type修改成category属性,再对下午数据进行一些修改才解决了这个问题。做复杂的图表时,可以先分析一下这个图表可以由哪些图表来组成,然后再根据需求来对各个图表进行修改。echarts这个框架还是很好用的,图表类型丰富,文档全,能够高度自定义,重要还是免费的...

  

posted @ 2019-07-27 14:08  盛夏荼靡  阅读(2838)  评论(9编辑  收藏  举报