echarts 甘特圖組件

由于業(yè)務(wù)的需要忽媒,在echarts基礎(chǔ)上注竿,二次封裝了甘特圖組件來滿足業(yè)務(wù)的需要辰妙。

先看效果

無文字甘特圖

有文字甘特圖

技術(shù)實(shí)現(xiàn)

直接上代碼压状,組件封裝
placeholder-bar.vue

<template>
  <div>
    <div :id="idKey" class="placeholder-bar-box" />
  </div>
</template>

<script>
import * as echarts from 'echarts'

export default {
  name: 'Index',
  props: {
    idKey: {
      type: String,
      default: 'placeholder-bar'
    },
    dataList: {
      type: Array,
      default: () => []
    },
    xData: {
      type: Array,
      default: () => []
    },
    yData: {
      type: Array,
      default: () => []
    }
  },
  data() {
    return {
      myChart: ''
    }
  },
  computed: {
    option() {
      const colors = ['#0F62FE', '#0F62FE', '#0F62FE', '#0F62FE']

      return {
        color: colors,
        tooltip: {
          formatter: function(params) {
            return params.name + ':' + params.value[1] + '~' + params.value[2]
          }
        },
        grid: {
          left: '3%',
          right: '3%',
          top: '6%',
          bottom: '8%',
          containLabel: true
        },
        xAxis: {
          type: 'category',
          boundaryGap: false,
          data: this.xData || ['2022-06-15', '2022-06-18', '2022-06-20', '2022-06-25', '2022-07-01', '2022-08-25', '2022-11-14', '2022-12-13'],
          splitLine: {
            show: true,
            lineStyle: {
              type: 'dashed'
            }
          },
          axisLabel: {
            formatter: (value) => {
              const max = 10 
              const val = value.length 
              const rowM = Math.ceil(val / max) 
              if (rowM > 1) {
                let temp = ''
                const end = val 
                temp = value.substring(0, max) + '\n' + value.substring(max, end)
                return temp
              } else {
                return value
              }
            }
          }
        },
        yAxis: {
          data: this.yData || ['測試1', '測試2', '測試3', '測試4']
        },
        series: [
          {
            type: 'custom',
            renderItem: function(params, api) {
              var categoryIndex = api.value(0)
              var start = api.coord([api.value(1), categoryIndex])
              var end = api.coord([api.value(2), categoryIndex])
              var height = 5
              return {
                type: 'rect',
                shape: echarts.graphic.clipRectByRect({
                  x: start[0],
                  y: start[1] - height / 2,
                  width: end[0] - start[0],
                  height: height
                }, {
                  x: params.coordSys.x,
                  y: params.coordSys.y,
                  width: params.coordSys.width,
                  height: params.coordSys.height
                }),
                style: api.style()
              }
            },
            encode: {
              x: [1, 2],
              y: 0
            },
            data: this.dataList
          }
        ]
      }
    }
  },
  watch: {
    dataList: {
      handler(newName, oldName) {
        this.$nextTick(() => {
          this.updata()
        })
      },
      deep: true
    }
  },
  mounted() {
    const chartDom = document.getElementById(this.idKey)
    const myChart = echarts.init(chartDom)
    this.myChart = myChart
    const myObserver = new ResizeObserver(entry => {
      this.myChart && this.myChart.resize()
    })
    // 添加要監(jiān)聽的元素仆抵,把echart的container div添加為監(jiān)聽對象
    myObserver.observe(chartDom)
    window.addEventListener('resize', () => {
      this.resize()
    })
  },
  destroyed() {
    window.removeEventListener('resize', () => {
    })
  },
  methods: {
    resize() {
      this.myChart.resize()
    },
    updata() {
      this.onPlaceholderBarData()
      this.resize()
    },
    onPlaceholderBarData() {
      this.option && this.myChart.setOption(this.option)
      this.myChart.hideLoading()
    }
  }
}
</script>

<style lang="scss" scoped>

.placeholder-bar-box {
  width: 100%;
  height: 100%;
}

</style>

組件對外提供的參數(shù)
1、idKey:唯一標(biāo)識ID
2种冬、dataList:[] 需要的數(shù)據(jù)
數(shù)據(jù)格式:

[
    {
                itemStyle: { normal: { color: '#0F62FE' }}, // 條形顏色
                name: 測試,
                value: [0镣丑,2022-02-02,2022-03-02]// 0,1,2代表y軸的索引,后兩位代表x軸數(shù)據(jù)開始和結(jié)束
              }
]

3娱两、xData:X坐標(biāo)數(shù)據(jù)
4莺匠、yData:Y坐標(biāo)數(shù)據(jù)

使用說明

引入組件
import placeholderBar from '@/views/common/placeholder-bar'

<placeholderBar ref="placeholderBarRef" :x-data="xData" :y-data="yData" style="width: 100%;height: 250px" :data-list="placeholderBarData" />

需要文字填充

修改renderItem
思路:用下標(biāo)記錄是否相同Y坐標(biāo),如果相同計數(shù)取值
(歡迎大家提出不同的解決問題思路)

renderItem: (params, api) => {
              const categoryIndex = api.value(0)
              const start = api.coord([api.value(1), categoryIndex])
              const end = api.coord([api.value(2), categoryIndex])
              const name = this.yData[categoryIndex]
              const list = this.dataList.filter(item => item.name === name)
              const height = 20
              let text = ''
              if (this.indexY === categoryIndex) {
                this.indexItem += 1
                text = list[this.indexItem]?.name2
                if (!text) {
                  this.indexItem = 0
                  text = list[this.indexItem]?.name2
                }
              } else {
                text = list[0]?.name2
                this.indexY = categoryIndex
                this.indexItem = 0
              }
              return {
                type: 'rect',
                shape: echarts.graphic.clipRectByRect({
                  x: start[0],
                  y: start[1] - height / 2,
                  width: end[0] - start[0],
                  height: height
                }, {
                  x: params.coordSys.x,
                  y: params.coordSys.y,
                  width: params.coordSys.width,
                  height: params.coordSys.height
                }),
                style: api.style(
                  {
                    text: text,
                    fontSize: '8px',
                    textFill: '#fff'
                  }
                )
              }
            },

這里不在詳細(xì)介紹每個API的使用了十兢,不懂得可以去官網(wǎng)查看相關(guān)API配置趣竣。
大家可直接復(fù)制代碼運(yùn)行demo吧,多看文檔多動手嘗試旱物,可解決一切問題遥缕。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市宵呛,隨后出現(xiàn)的幾起案子单匣,更是在濱河造成了極大的恐慌,老刑警劉巖宝穗,帶你破解...
    沈念sama閱讀 211,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件户秤,死亡現(xiàn)場離奇詭異,居然都是意外死亡逮矛,警方通過查閱死者的電腦和手機(jī)鸡号,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,347評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來须鼎,“玉大人膜蠢,你說我怎么就攤上這事堪藐。” “怎么了挑围?”我有些...
    開封第一講書人閱讀 157,435評論 0 348
  • 文/不壞的土叔 我叫張陵礁竞,是天一觀的道長。 經(jīng)常有香客問我杉辙,道長模捂,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,509評論 1 284
  • 正文 為了忘掉前任蜘矢,我火速辦了婚禮狂男,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘品腹。我一直安慰自己岖食,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,611評論 6 386
  • 文/花漫 我一把揭開白布舞吭。 她就那樣靜靜地躺著泡垃,像睡著了一般。 火紅的嫁衣襯著肌膚如雪羡鸥。 梳的紋絲不亂的頭發(fā)上蔑穴,一...
    開封第一講書人閱讀 49,837評論 1 290
  • 那天,我揣著相機(jī)與錄音惧浴,去河邊找鬼存和。 笑死,一個胖子當(dāng)著我的面吹牛衷旅,可吹牛的內(nèi)容都是我干的捐腿。 我是一名探鬼主播,決...
    沈念sama閱讀 38,987評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼柿顶,長吁一口氣:“原來是場噩夢啊……” “哼茄袖!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起九串,我...
    開封第一講書人閱讀 37,730評論 0 267
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎寺鸥,沒想到半個月后猪钮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,194評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡胆建,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,525評論 2 327
  • 正文 我和宋清朗相戀三年烤低,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片笆载。...
    茶點(diǎn)故事閱讀 38,664評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡扑馁,死狀恐怖涯呻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情腻要,我是刑警寧澤复罐,帶...
    沈念sama閱讀 34,334評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站雄家,受9級特大地震影響效诅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜趟济,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,944評論 3 313
  • 文/蒙蒙 一乱投、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧顷编,春花似錦戚炫、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,764評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至层宫,卻和暖如春杨伙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背萌腿。 一陣腳步聲響...
    開封第一講書人閱讀 31,997評論 1 266
  • 我被黑心中介騙來泰國打工限匣, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人毁菱。 一個月前我還...
    沈念sama閱讀 46,389評論 2 360
  • 正文 我出身青樓米死,卻偏偏與公主長得像,于是被迫代替她去往敵國和親贮庞。 傳聞我的和親對象是個殘疾皇子峦筒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,554評論 2 349

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