vue echarts 甘特圖功能
index.vue
<template><div ref="echart" id="echart" class="echart"></div>
</template><script setup>import { nextTick, onMounted, ref } from "vue";import * as echarts from "echarts";let colorTheme = ["#4150d8","#28bf7e","#ed7c2f","#ff0000","#f9cf36","#4a5bdc","#7b04f4","#ee04f4","#04a0f4","#1af404","#d4f404","#f404f1",];const YData = ["示例1", "示例2", "示例3", "示例5", "示例6", "示例6", "示例7"];// 0 代表y軸索引(示例的下標) 后面0 代表 甘特圖一個數據有多行 0 代表1個 1 代表2個// [0, "2021-07-19 03:29:19", "2021-07-19 08:38:50", 0]**多個數組代表多組數據,即每種“示例”會在多個時間段分布**let showData = [[{value: [0, "2021-07-19 03:29:19", "2021-07-19 08:38:50", 0],},{value: [1, "2021-07-19 03:53:07", "2021-07-19 21:00:08", 0],},{value: [4, "2021-07-19 03:29:19", "2021-07-19 08:38:50", 0],},],[{value: [0, "2021-07-19 05:00:00", "2021-07-19 06:08:02", 0],},{value: [1, "2021-07-19 00:00:00", "2021-07-19 05:08:02", 0],},{value: [3, "2021-07-19 00:00:00", "2021-07-19 05:08:02", 0],},],];// 分配y值const produceSeries = (data) => {let len = data.length;let step = len % 2 == 1 ? -5 : 2;let series = [];data.map((val, index) => {// if (step == -5) {series.push(configSeriec(val, index, 0));step = step + 30;// return;// }// if (index % 2 == 0) {// series.push(configSeriec(val, index, step));// step = step + 20;// } else {// series.push(configSeriec(val, index, -step));// step = step + 10;// }});function configSeriec(val, index, step) {return {type: "custom",renderItem: (params, api) => {//開發者自定義的圖形元素渲染邏輯,是通過書寫 renderItem 函數實現的var categoryIndex = api.value(0); //這里使用 api.value(0) 取出當前 dataItem 中第一個維度的數值。var start = api.coord([api.value(1), categoryIndex]); // 這里使用 api.coord(...) 將數值在當前坐標系中轉換成為屏幕上的點的像素值。var end = api.coord([api.value(2), categoryIndex]);var height = 10;return {type: "rect", // 表示這個圖形元素是矩形。還可以是 'circle', 'sector', 'polygon' 等等。y: step,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], // data 中『維度1』和『維度2』對應到 X 軸y: 0, // data 中『維度0』對應到 Y 軸},itemStyle: {normal: {color: function (params) {//return colorTheme[params.value[0]];return colorTheme[index];},},},data: val,};}return series;};let option = {title: {text: "",top: "1%",x: "center",textStyle: {fontSize: 20,color: "#333333",},},tooltip: {enterable: true,backgroundColor: "rgba(255,255,255,1)", //背景顏色(此時為默認色)borderRadius: 5, //邊框圓角padding: 10, // [5, 10, 15, 20] 內邊距textStyle: {color: "#000",},position: function (point, params, dom, rect, size) {dom.innerHTML = params.name + '<br/>' +'開始時間:' + params.value[1] + '<br/>' +'結束時間:' + params.value[2];},},legend: {auto: true// //圖例// data: "我是圖例",// left: "90px",// top: 22,// itemWidth: 16,// itemHeight: 16,// selectedMode: false, // 圖例設為不可點擊// textStyle: {// color: "#333333",// fontSize: 16,// },},// grid: {// top: 10,// bottom: 10,// left: 100,// right: 20,// containLabel: true// },xAxis: {name: "",nameTextStyle: {color: "#333333",fontSize: 18,},position: 'top',type: "time",splitNumber: 6,max: "2021-07-20 00:00:00",min: "2021-07-19 00:00:00", //將data里最小時間的整點時間設為min,否則min會以data里面的min為開始進行整點遞增axisLabel: {show: true,formatter: function (value) {//在這里寫你需要的時間格式var t_date = new Date(value);let month = t_date.getMonth() + 1;let day = t_date.getDate();let hours = t_date.getHours();let minutes = t_date.getMinutes();return ([t_date.getFullYear(),month < 10 ? '0' + month : month,day < 10 ? '0' + day : day,].join("-") +"\n" +[hours < 10 ? '0' + hours : hours, minutes < 10 ? '0' + minutes : minutes].join(" : "));},},splitLine: {show: true,lineStyle: {color: "#333333",},},axisLine: {show: true,color: "#333333",// symbol: ["none", "arrow"],lineStyle: {color: "#333333",width: 1,type: "solid",},},},yAxis: {name: "",nameTextStyle: {color: "#333333",fontSize: 18,},axisLine: {color: "#333333",lineStyle: {color: "#333333",},},axisLabel: {show: true,textStyle: {color: "#333333", //這里用參數代替了},},data: YData,},dataZoom: [// {// show: true,// realtime: true,// start: 0,// end: 100,// height: 20,// borderColor: "rgba(43,48,67,0.5)",// fillerColor: "#269cdb", //滑動塊的顏色// backgroundColor: "rgba(44, 92, 170, 0.35)", //兩邊未選中的滑動條區域的顏色// xAxisIndex: [0, 1],// width: "86%",// },// {// type: "inside",// realtime: true,// start: 30,// end: 70,// // xAxisIndex: [0, 1],// },{type: "slider",show: true,// 設置組件控制的y軸yAxisIndex: 0,right: 15,// top: 60,// 數據窗口范圍的起始百分比。范圍是:0 ~ 100。表示 0% ~ 100%// 也可以用 startValue設置起始值// start: "0",// end: "50",maxSpan: 20,maxValueSpan: 5, // 最大顯示y軸的條數width: 10, //滾動條的粗細// height: 450,// 組件的背景顏色// left: 600, //左邊的距離// right: 8,//右邊的距離borderRadius: 8,borderColor: "rgba(43,48,67,0.5)",fillerColor: "#269cdb", //滑動塊的顏色backgroundColor: "rgba(44, 92, 170, 0.35)", //兩邊未選中的滑動條區域的顏色// 是否顯示detail,即拖拽時候顯示詳細數值信息showDetail: false,// 控制手柄的尺寸handleSize: 16,// 是否在 dataZoom-silder 組件中顯示數據陰影。數據陰影可以簡單地反應數據走勢。showDataShadow: false,// zoomLock: true, //禁止拖拽 y軸固定,不能拉長滾動條},{type: "inside",yAxisIndex: [0],start: 1,end: 36,// 鼠標滾輪Y軸能觸發縮放 false 禁止滾輪縮放 true 滾輪可以縮放// zoomOnMouseWheel: false,// 不按任何功能鍵,鼠標移動能觸發數據窗口平移moveOnMouseMove: true,moveOnMouseWheel: true},],series: produceSeries(showData),};let echart = ref();let myChart;const setDatas = (XData, YData) => {option.yAxis.data = YData;option.series = produceSeries(XData);myChart.setOption(option);myChart.resize();}onMounted(() => {nextTick(() => {myChart = echarts.init(echart.value);option.yAxis.data = YData;option.series = produceSeries(showData);myChart.setOption(option);});});const watchResize = () => {setTimeout(() => {myChart.resize();}, 200)}//暴露方法,父組件才能調用defineExpose({setDatas,watchResize,})
</script>
<style lang="less">.echart {width: 100%;height: 1000px;}
</style>