echarts的分時(shí)圖實(shí)現(xiàn)

微信圖片_20191024134934.jpg

如上圖所示,前端時(shí)間做了個(gè)期權(quán)交易項(xiàng)目,涉及到該分時(shí)圖的實(shí)現(xiàn)锉罐,沒(méi)有在網(wǎng)上找到現(xiàn)成的配置号涯,后面自己寫(xiě)了個(gè),是用echarts(版本4.1.0)實(shí)現(xiàn)的青扔,我會(huì)將相關(guān)配置項(xiàng)代碼貼在下方:

let interval;//用作y軸的坐標(biāo)軸分割間隔的值
  let min;//當(dāng)前實(shí)時(shí)數(shù)據(jù)源织,價(jià)格最低
  let max;//當(dāng)前實(shí)時(shí)數(shù)據(jù),價(jià)格最高
  let judgePrice;//昨日行權(quán)價(jià)格微猖,用來(lái)作為今日的漲跌判斷基準(zhǔn)值
  let responseData;//后臺(tái)獲取的實(shí)時(shí)行情買賣數(shù)據(jù)谈息,屬性i為數(shù)據(jù)時(shí)間(如:10:30:20),p為數(shù)據(jù)買賣價(jià)格凛剥,v為數(shù)據(jù)當(dāng)次交易量
  let baseNumber = Math.max(Math.abs(max - junglePrice), Math.abs(min - junglePrice));
  interval = (baseNumber / 2).toFixed(4);

  let option = {
    backgroundColor: '#1f2025',
    animation: false,
    tooltip: {
      trigger: 'axis',
      axisPointer: {
        type: 'cross'
      },
      showContent: false
    },
    axisPointer: {
      link: {xAxisIndex: 'all'},
      label: {
        backgroundColor: '#777'
      }
    },
    visualMap: {
      show: false,
      seriesIndex: 4,
      dimension: 2,
      pieces: [{
        value: 1,
        color: 'red'
      }, {
        value: -1,
        color: 'green'
      },
        {
          value: 0,
          color: '#ffffff'
        }
      ]
    },
    grid: [
      {
        top: '5%',
        left: '15%',
        width:'35%',
        height: '50%'
      },
      {
        top: '5%',
        left: '50%',
        width:'35%',
        height: '50%'
      },
      {
        left: '15%',
        right: '8%',
        top: '72%',
        height: '20%'
      }
    ],
    xAxis: [
      {
        type: 'time',
        boundaryGap: true,
        axisLine: {
          onZero: false,
          lineStyle: {
            color: '#666'
          }
        },
        axisLabel: {
          formatter: function (val,index) {
            if(index === 2){
              return ''
            }
            return moment(val).format('HH:mm');
          }
        },
        splitLine: {
          show: true,
          lineStyle: {
            color: '#666'
          }
        },
        splitArea: {
          areaStyle: {
            color: '#1f2025'
          }
        },
        // splitNumber: 5,
        min: 946690200000,
        max: 946697400000,
        interval: 3600000,
        axisTick: {show: false},
        axisPointer: {
          z: 100,
          label: {
            formatter: function (params) {
              return moment(params.value).format('HH:mm');
            }
          }
        }
      },
      {
        type: 'time',
        gridIndex: 1,
        boundaryGap: true,
        axisLine: {
          onZero: false,
          lineStyle: {
            color: '#666'
          }
        },
        axisLabel: {
          formatter: function (val,index) {
            if(index === 0){
              return '11:30/13:00'
            }
            return moment(val).format('HH:mm');
          }
        },
        splitLine: {
          show: true,
          lineStyle: {
            color: '#666'
          }
        },
        splitArea: {
          areaStyle: {
            color: '#1f2025'
          }
        },
        // splitNumber: 5,
        min: 946702800000,
        max: 946710000000,
        interval: 3600000,
        axisTick: {show: false},
        axisPointer: {
          z: 100,
          label: {
            formatter: function (params) {
              return moment(params.value).format('HH:mm');
            }
          }
        }
      },
      {
        type: 'category',
        gridIndex: 2,
        data: responseData.map(item => item.i),
        // scale: true,
        boundaryGap: true,
        axisLine: {onZero: false},
        axisTick: {show: false},
        splitLine: {
          show: true,
          lineStyle: {
            color: '#666'
          }
        },
        splitArea: {
          areaStyle: {
            color: '#1f2025'
          }
        },
        axisLabel: {show: false},
        splitNumber: 20,
        min: 'dataMin',
        max: 'dataMax'
      }
    ],
    yAxis: [
      {
        min: function (val) {
          return (parseFloat(junglePrice) - 2 * parseFloat(interval)).toFixed(4);
        },
        max: function (val) {
          return (parseFloat(junglePrice) + 2 * parseFloat(interval)).toFixed(4);
        },
        interval: Math.abs(interval),
        axisLabel: {
          formatter: function (val) {
            return val.toFixed(4);
          },
          color:function (value) {
            return value-junglePrice === 0?'#cccccc':value-junglePrice > 0 ? 'red' : 'green';
          }
        },
        axisPointer: {
          show: true,
          label: {
            formatter: function (params) {
              return (params.value).toFixed(4);
            }
          }
        },
        axisLine: {
          lineStyle: {
            color: '#666'
          }
        },
        axisTick: {show: false},
        splitLine: {
          lineStyle: {
            color: '#666'
          }
        },
        splitArea: {
          areaStyle: {
            color: '#1f2025'
          }
        },
      },
      {
        gridIndex: 1,
        position:'right',
        min: function (val) {
          return (parseFloat(junglePrice) - 2 * parseFloat(interval)).toFixed(4);
        },
        max: function (val) {
          return (parseFloat(junglePrice) + 2 * parseFloat(interval)).toFixed(4);
        },
        interval: Math.abs(interval),
        axisLabel: {
          formatter: function (val) {
            let data = (val - junglePrice)/junglePrice*100;
            return data.toFixed(2)+'%';
          },
          color:function (value) {
            return value-junglePrice === 0?'#cccccc':value-junglePrice > 0 ? 'red' : 'green';
          }
        },
        axisPointer: {
          show: true,
          label: {
            formatter: function (params) {
              return (params.value).toFixed(4);
            }
          }
        },
        axisLine: {
          lineStyle: {
            color: '#666'
          }
        },
        axisTick: {show: false},
        splitLine: {
          lineStyle: {
            color: '#666'
          }
        },
        splitArea: {
          areaStyle: {
            color: '#1f2025'
          }
        },
      },
      {
        min: 'dataMin',
        max: 'dataMax',
        gridIndex: 2,
        splitNumber: 1,
        interval: 10000,
        showMinLabel: true,
        showMaxLabel: true,
        axisLabel: {
          formatter: function (value, index) {
            if (index === 0) {
              return '張'
            } else {
              return value;
            }
          },
        },
        axisPointer: {
          show: true,
          label: {
            formatter: function (params) {
              return (params.value).toFixed(0);
            }
          }
        },
        axisTick: {show: false},
        axisLine: {
          lineStyle: {
            color: '#666'
          }
        },
        splitLine: {
          lineStyle: {
            color: '#666'
          }
        },
        splitArea: {
          areaStyle: {
            color: '#1f2025'
          }
        },
      }
    ],
    series: [
      {
        name: '當(dāng)前價(jià)',
        type: 'line',
        data: responseData.map(item => {
          let date = '2000-01-01' + ' ' + item.i;
          let dateNumber = Date.parse(new Date(date));
          return [dateNumber, item.p];
        }),
        smooth: true,
        symbol: 'none',
        areaStyle: {
          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
            offset: 0,
            color: 'rgb(2,228,253)'
          }, {
            offset: 1,
            color: 'transparent'
          }])
        },
        lineStyle: {
          color: 'rgb(2,228,253)',
          width: 1
        }
      },
      {
        name: '當(dāng)前價(jià)',
        type: 'line',
        xAxisIndex: 1,
        yAxisIndex: 1,
        data: responseData.map(item => {
          let date = '2000-01-01' + ' ' + item.i;
          let dateNumber = Date.parse(new Date(date));
          return [dateNumber, item.p];
        }),
        smooth: true,
        symbol: 'none',
        areaStyle: {
          color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
            offset: 0,
            color: 'rgb(2,228,253)'
          }, {
            offset: 1,
            color: 'transparent'
          }])
        },
        lineStyle: {
          color: 'rgb(2,228,253)',
          width: 1
        }
      },
      {
        name: '行權(quán)價(jià)',
        type: 'line',
        data: responseData.map(item => {
          let date = '2000-01-01' + ' ' + item.i;
          let dateNumber = Date.parse(new Date(date));
          return [dateNumber, judgePrice];
        }),
        smooth: true,
        symbol: 'none',
        lineStyle: {
          color: 'rgb(248,185,0)',
          width: 1
        }
      },
      {
        name: '行權(quán)價(jià)',
        type: 'line',
        xAxisIndex: 1,
        yAxisIndex: 1,
        data: responseData.map(item => {
          let date = '2000-01-01' + ' ' + item.i;
          let dateNumber = Date.parse(new Date(date));
          return [dateNumber, judgePrice];
        }),
        smooth: true,
        symbol: 'none',
        lineStyle: {
          color: 'rgb(248,185,0)',
          width: 1
        }
      },
      {
        name: '買賣量',
        type: 'bar',
        xAxisIndex: 2,
        yAxisIndex: 2,
        itemStyle: {
          normal: {
            color: 'green',
            color0: 'red',
            borderColor: null,
            borderColor0: null
          }
        },
        data: responseData.map((item, index, arr) => {
          let judge = item.p === junglePrice ? 0 : item.p > junglePrice ? 1 : -1;
          if (index === 0) {
            judge = item.p === junglePrice ? 0 : item.p > junglePrice ? 1 : -1;
          } else {
            judge = item.p === arr[index - 1].p ? 0 : item.p > arr[index - 1].p ? 1 : -1;
          }
          return [index, item.v, judge];
        })
      }
    ]
  }; 

由于分時(shí)圖的特殊性侠仇,只關(guān)注9:30到下午15:00間的實(shí)時(shí)交易數(shù)據(jù),并且中午11:30到下午13:00之間是暫停交易時(shí)間犁珠,所以該分時(shí)圖實(shí)現(xiàn)的難點(diǎn)一是x軸的實(shí)現(xiàn)逻炊,二是y軸的價(jià)格區(qū)間必須得是實(shí)時(shí)的當(dāng)日最高價(jià)格和當(dāng)日最高價(jià)格以行權(quán)價(jià)為基準(zhǔn)計(jì)算,以最高價(jià)和最低價(jià)與行權(quán)價(jià)相減值大的為基準(zhǔn)值犁享,然后除2得到y(tǒng)軸的分割間隔值余素。

上面的配置中,漲我用的顏色是red炊昆,跌用的green桨吊,具體色值根據(jù)實(shí)際項(xiàng)目需要調(diào)整。上圖實(shí)際將圖表渲染層分為三塊凤巨,用grid調(diào)整相應(yīng)布局视乐。由于橫坐標(biāo)需要用時(shí)間戳來(lái)計(jì)算interval,所以我都是用2000-01-01加相應(yīng)時(shí)間獲取到的時(shí)間戳敢茁,好用于設(shè)置x軸的min和max佑淀,并且將interval設(shè)置為3600000,那么x軸的間隔剛好是一小時(shí)卷要,并且09:30到11:30和13:00到15:00用兩個(gè)單獨(dú)的grid配置渣聚,組合為實(shí)際想要的一整個(gè)分時(shí)圖。

responseData為后臺(tái)獲取數(shù)據(jù)僧叉,由于從新浪期權(quán)抓取的數(shù)據(jù)奕枝,屬性名依照接口返回的有相應(yīng)的v(交易量),i(時(shí)間),p(價(jià)格)幾個(gè)屬性,大家在實(shí)際使用該配置時(shí)瓶堕,還是得根據(jù)自己得后臺(tái)接口做相應(yīng)調(diào)整隘道。min和max根據(jù)自己接口獲取得值設(shè)置,若接口未提供該值,就需要前端從實(shí)時(shí)數(shù)據(jù)中遍歷獲取實(shí)時(shí)得min和max值谭梗。

綜上忘晤,我為大家提供了現(xiàn)成得配置,具體實(shí)現(xiàn)還得實(shí)際在項(xiàng)目中進(jìn)行調(diào)試激捏,有什么問(wèn)題可以在評(píng)論中提問(wèn)或者私信我设塔,我會(huì)及時(shí)回答。走過(guò)路過(guò)远舅,記得幫忙點(diǎn)個(gè)贊喲

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末闰蛔,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子图柏,更是在濱河造成了極大的恐慌序六,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,888評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蚤吹,死亡現(xiàn)場(chǎng)離奇詭異例诀,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)裁着,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門繁涂,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人跨算,你說(shuō)我怎么就攤上這事爆土⊥职茫” “怎么了诸蚕?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,386評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)氧猬。 經(jīng)常有香客問(wèn)我背犯,道長(zhǎng),這世上最難降的妖魔是什么盅抚? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,726評(píng)論 1 297
  • 正文 為了忘掉前任漠魏,我火速辦了婚禮,結(jié)果婚禮上妄均,老公的妹妹穿的比我還像新娘柱锹。我一直安慰自己,他們只是感情好丰包,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布禁熏。 她就那樣靜靜地躺著,像睡著了一般邑彪。 火紅的嫁衣襯著肌膚如雪瞧毙。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,337評(píng)論 1 310
  • 那天,我揣著相機(jī)與錄音宙彪,去河邊找鬼矩动。 笑死,一個(gè)胖子當(dāng)著我的面吹牛释漆,可吹牛的內(nèi)容都是我干的悲没。 我是一名探鬼主播,決...
    沈念sama閱讀 40,902評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼男图,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼檀训!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起享言,我...
    開(kāi)封第一講書(shū)人閱讀 39,807評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤峻凫,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后览露,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體荧琼,經(jīng)...
    沈念sama閱讀 46,349評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評(píng)論 3 340
  • 正文 我和宋清朗相戀三年差牛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了命锄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,567評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡偏化,死狀恐怖脐恩,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情侦讨,我是刑警寧澤驶冒,帶...
    沈念sama閱讀 36,242評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站韵卤,受9級(jí)特大地震影響骗污,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜沈条,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評(píng)論 3 334
  • 文/蒙蒙 一需忿、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蜡歹,春花似錦屋厘、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,420評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至景鼠,卻和暖如春仲翎,著一層夾襖步出監(jiān)牢的瞬間痹扇,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,531評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工溯香, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留鲫构,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,995評(píng)論 3 377
  • 正文 我出身青樓玫坛,卻偏偏與公主長(zhǎng)得像结笨,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子湿镀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容