日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

echart 时间滚动_基于 ECharts 封装甘特图并实现自动滚屏

發布時間:2025/3/20 编程问答 62 豆豆
生活随笔 收集整理的這篇文章主要介紹了 echart 时间滚动_基于 ECharts 封装甘特图并实现自动滚屏 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

項目中需要用到甘特圖組件,之前的圖表一直基于 EChart 開發,但 EChart 本身沒有甘特圖組件,需要自行封裝

經過一番鏖戰,終于完成了...

我在工程中參考 v-chart?封裝了一套圖表組件,所以這里只介紹甘特圖組件的實現,圖表的初始化、數據更新、自適應等不在這里介紹

一、約定數據格式

EChart 本身沒有甘特圖,但可以通過 EChart 提供的“自定義”方法 type: 'custom' 開發

const option ={

series: [{

type:'custom',

renderItem: (params, api) =>{//do sth

},

data,

}]

}

這里的 data 就是數據集,它是一個二維數組,主要需要兩個參數:

name:名稱,可以在 legend 和 tooltip 中展示

value:參數集合,自定義的圖表時需要的參數都可以放到這個數組里

如果需要其它的配置,也可以按照 ECharts 的 series 結構添加別的字段

我自定義的數據結構是這樣的:

{

name,

itemStyle: {

normal: {

color: color||defaultColor,

},

},//value 為約定寫法,依序為“類目對應的索引”、“狀態類型”、“狀態名稱”、“開始時間”、“結束時間”

value: [

index,

type,

name,newDate(start).getTime(),

new Date(end ||Date.now()).getTime(),

],

}

注意:series.data 中的元素需要根據狀態劃分,不能根據類目(Y軸)劃分,這樣才能保證圖例 legend 的正常顯示

最終的 data 結構如圖:

自定義的核心是 renderItem 函數,這個函數的本質就是:將 data 中的參數 value 處理之后,映射到對應的坐標軸上,具體處理參數的邏輯完全自定義

甘特圖就需要計算出各個數據塊的高度和寬度,然后映射到對應的類目軸(Y軸)和時間軸(X軸)上

由于甘特圖會用到時間軸(X軸),所以定義的 value 中需要開始時間和結束時間的時間戳

為了區分該數據屬于類目軸(Y軸)的哪一條類目,還需要對應類目的索引 index

如果還有其它的需要,比如自定義 tooltip,還可以在 value 中添加其它的參數

但一定要約定好參數的順序,因為 renderItem 函數是根據 value 的索引去取對應的參數

二、處理數據?Series

//處理數據

function getGantSeries(args) {const { innerRows, columns } =argsconst baseItem ={

type:'custom',

renderItem: (params, api) => renderGanttItem(params, api),

dimensions: columns,

};return innerRows.map(row =>{return{

...baseItem,

name: row[0].name,

data: row,

};

});

}

當 type 指定為 'custom' 的時候,series 的元素可以添加?dimensions 字段,用來定義每個維度的信息

處理數據的核心是 renderItem 方法,該方法提供了 params 和 api 兩個參數,最后需要返回對應的圖形元素信息

const DIM_CATEGORY_INDEX = 0; //value 中類目標識的索引

const DIM_CATEGORY_NAME_INDEX = 1; //value 中對應元素類型的索引

const DIM_START_TIME_INDEX = 3; //value 中開始時間的索引

const DIM_END_TIME_INDEX = 4; //value 中結束時間的索引

const HEIGHT_RATIO = 0.6; //甘特圖矩形元素高度縮放比例

const CATEGORY_NAME_PADDING_WIDTH = 20; //在甘特圖矩形元素上展示文字時,左右 padding 的最小長度

/**

* 計算元素位置及寬高

* 如果元素超出了當前坐標系的包圍盒,則剪裁這個元素

* 如果元素完全被剪掉,會返回 undefined*/function clipRectByRect(params, rect) {returnecharts.graphic.clipRectByRect(rect, {

x:params.coordSys.x,

y:params.coordSys.y,

width:params.coordSys.width,

height:params.coordSys.height,

});

}//渲染甘特圖元素

function renderGanttItem(params, api, extra) {const { isShowText, barMaxHeight, barHeight } =extra;//使用 api.value(index) 取出當前 dataItem 的維度

const categoryIndex =api.value(DIM_CATEGORY_INDEX);//使用 api.coord(...) 將數值在當前坐標系中轉換成為屏幕上的點的像素值

const startPoint =api.coord([api.value(DIM_START_TIME_INDEX), categoryIndex]);const endPoint =api.coord([api.value(DIM_END_TIME_INDEX), categoryIndex]);//使用 api.size(...) 取得坐標系上一段數值范圍對應的長度

const baseHeight = Math.min(api.size([0, 1])[1], barMaxHeight);const height = barHeight * HEIGHT_RATIO || baseHeight *HEIGHT_RATIO;const width = endPoint[0] - startPoint[0];const x = startPoint[0];const y = startPoint[1] - height / 2;//處理類目名,用于在圖形上展示

const categoryName = api.value(DIM_CATEGORY_NAME_INDEX) + '';const categoryNameWidth =echarts.format.getTextRect(categoryName).width;const text = width > categoryNameWidth + CATEGORY_NAME_PADDING_WIDTH ? categoryName : '';const rectNormal = clipRectByRect(params, { x, y, width, height });const rectText = clipRectByRect(params, { x, y, width, height });return{

type:'group',

children: [

{//圖形元素形狀: 'rect', circle', 'sector', 'polygon'

type: 'rect',

ignore:!rectNormal, //是否忽略(忽略即不渲染)

shape: rectNormal,//映射 option 中 itemStyle 樣式

style: api.style(),

},

{//在圖形上展示類目名

type: 'rect',

ignore:!isShowText || !rectText,

shape: rectText,

style: api.style({

fill:'transparent',

stroke:'transparent',

text: text,

textFill:'#fff',

}),

},

],

};

}

上面是我用的 renderItem 方法全貌,主要是使用 api 提供的工具函數計算出元素的視覺寬高

再使用?echarts 提供的 graphic.clipRectByRect 方法,結合參數?params 提供的坐標系信息,截取出元素的圖形信息

三、自定義 tooltip

如果數據格式正確,到這里已經能渲染出甘特圖了,但一個圖表還需要其它的細節,比如 tooltip 的自定義

在 renderItem 中有一個字段?encode 可以用來自定義 tooltip,但只能定義展示的文字

具體的 tooltip 排版和圖例顏色(特別是漸變色)無法通過 encode 實現自定義,最終還是得通過 formatter 函數

formatter: params =>{const { value = [], marker, name, color } = params;const axis = this.columns; //類目軸(Y軸)數據//刪除空標題

let str = '';

isArray(axis[value[0]]) && axis[value[0]].map(item =>{

item&& (str += `${item}/`);

});

str= str.substr(0, str.length - 1);//顏色為對象時,為漸變顏色,需要手動拼接

let mark =marker;if(isObject(color)) {const { colorStops = [] } =color;const endColor = colorStops[0] && colorStops[0].color;const startColor = colorStops[1] && colorStops[1].color;const colorStr = `background-image: linear-gradient(90deg, ${startColor}, ${endColor});`;

mark=``;

}//計算時長

const startTime = moment(value[3]);const endTime = moment(value[4]);

let unit= '小時';

let duration= endTime.diff(startTime, 'hours');return`

${str}${mark}${name}: ${duration}${unit}開始時間:${startTime.format('YYYY-MM-DD HH:mm')}結束時間:${endTime.format('YYYY-MM-DD HH:mm')}`;

},

},

四、自動滾屏

如果甘特圖的數據過多,堆在一屏展示就會顯得很窄,這時候可以結合 dataZoom 實現滾屏

首先需要在組件中引入 dataZoom

import 'echarts/lib/component/dataZoom';//配置項

const option ={

...,

dataZoom: {

type:'slider',

id:'insideY01',

yAxisIndex:0,

zoomLock:true,

bottom:-10,

startValue:this.dataZoomStartVal,

endValue:this.dataZoomEndVal,

handleSize:0,

borderColor:'transparent',

backgroundColor:'transparent',

fillerColor:'transparent',

showDetail:false,

},

{

type:'inside',

id:'insideY02',

yAxisIndex:0,

startValue:this.dataZoomStartVal,

endValue:this.dataZoomEndVal,

zoomOnMouseWheel:false,

moveOnMouseMove:true,

moveOnMouseWheel:true,

}

}

然后需要設定甘特圖每一行的高度 barHeight,同時獲取甘特圖組件的高度

通過這兩個高度計算出每屏可以展示的甘特圖數據的數量 pageSize

const GANT_ITEM_HEIGHT = 56;const height = this.$refs.chartGantRef.$el.clientHeight;this.pageSize = Math.floor(height /GANT_ITEM_HEIGHT);//設置 dataZoom 的起點

this.dataZoomStartVal = 0;this.dataZoomEndVal = this.pageSize - 1;

然后通過定時器派發事件,修改 dataZoom 的?startValue 和 endValue,實現自動滾屏的效果

const Timer = null;

dataZoomAutoScoll() {

Timer= setInterval(() =>{const max = this.total - 1;if(this.dataZoomEndVal > max ||

this.dataZoomStartVal > max - this.pageSize

) {this.dataZoomStartVal = 0;this.dataZoomEndVal = this.pageSize - 1;

}else{this.dataZoomStartVal += 1;this.dataZoomEndVal += 1;

}

echarts.dispatchAction({

type:'dataZoom',

dataZoomIndex:0,

startValue:this.dataZoomStartVal,

endValue:this.dataZoomEndVal

});

},2000);

},

總結

以上是生活随笔為你收集整理的echart 时间滚动_基于 ECharts 封装甘特图并实现自动滚屏的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。