解決echarts使用renderItem自定義圖表時的殘影問題


公司有一個需求是繪制人員的排班任務甘特圖,因為有大量自定義元素和復雜交互,在初版時采用dom+Virtual List的辦法來做,顯示和交互的效果都不錯,但是一旦數據量大的時候,就算是Virtual List在滾動時都會很卡,於是就有了通過echarts使用canvas來繪制甘特圖的想法,主要是通過echarts的renderItem自定義圖表來展示,於是開始踩坑。

option

yAxis: {
  type: 'value'
}.
xAxis: {
  type: 'time'
}
series: [
    {
        id: 'flightData',
        type: 'custom',
        renderItem: this.renderGanttItem,
        dimensions: [null, { type: 'time' }, { type: 'time' }, { type: 'ordinal' }],
        encode: {
            x: [1, 2],
            y: 0,
        },
        data: echarts.util.map(_missions, (item, index) => {
            let startTime = new Date(this.root.options.startTime)
            let endTime = new Date(this.root.options.endTime)
            return [index, startTime, endTime].concat(item);
        }),
    },
    {
        type: 'custom',
        renderItem: this.renderAxisLabelItem,
        dimensions: [null, { type: 'ordinal' }],
        encode: {
            x: -1, // Then this series will not controlled by x.
            y: 0
        },
        data: echarts.util.map(_staffList, function (item, index) {
            return [index].concat(item);
        }),
    }
],
dataZoom:[
    {
        id: 'slider_x',
        type: 'slider',
        xAxisIndex: 0,
        filterMode: 'none',
        height: 20,
        bottom: 0,
        start: this.zoom.x_left,
        end: this.zoom.x_right,
        handleIcon: dragIcon,
        handleSize: '80%',
        showDetail: false,
        backgroundColor:'#E4E7ED9E',
        throttle: 100
    },
    {
        id: 'slider_y',
        type: 'slider',
        filterMode: 'weakFilter',
        fillerColor:'#d2d9e4',
        yAxisIndex: 0,
        zoomLock: true,
        width: 20,
        right: 0,
        start: this.zoom.y_top,
        end: this.zoom.y_bottom,
        handleSize: 0,
        showDetail: false,
        backgroundColor:'#E4E7ED9E',
        throttle: 100
    },
    {
        type: 'inside',
        id: 'insideX',
        xAxisIndex: 0,
        throttle: 100,
        zoomOnMouseWheel: false,
        moveOnMouseMove: true
    },
    {
        type: 'inside',
        id: 'insideY',
        yAxisIndex: 0,
        throttle: 100,
        zoomOnMouseWheel: false,
        moveOnMouseMove: true,
        moveOnMouseWheel: true
    }
]

 

這時候碰到問題:renderGanttItem返回的元素group數量是變化的,因為時間軸的移動,顯示的元素在不停變化,元素數量當然在變化,echarts對於減少和新增的元素,在界面上會出現殘影、動畫跳動的問題。參考了文檔嚴格定義了唯一的series-custom.renderItem.return_rect.id也不能解決。

解決辦法一

通過設置series-custom.renderItem.return_rect.ignore,節點是否完全被忽略(既不渲染,也不響應事件)。當視口離開元素時,把元素的ignore設置為true,當元素一定出現添加和減少時,先 調用this.myChart.clear(),保證不會在renderItem中有元素增減。

這個辦法有用,但是碰到每行元素很多的時候,就算時設置了ignore,也可以看到卡頓,沒有canvas對比dom的流暢,只能修改dataZoom-slider.throttle增加節流來減少卡頓。

解決辦法二

通過查看源碼,看到這樣一段注釋:

// Usage:
// (1) By default, `elOption.$mergeChildren` is `'byIndex'`, which indicates that
//     the existing children will not be removed, and enables the feature that
//     update some of the props of some of the children simply by construct
//     the returned children of `renderItem` like:
//     `var children = group.children = []; children[3] = {opacity: 0.5};`
// (2) If `elOption.$mergeChildren` is `'byName'`, add/update/remove children
//     by child.name. But that might be lower performance.
// (3) If `elOption.$mergeChildren` is `false`, the existing children will be
//     replaced totally.
// (4) If `!elOption.children`, following the "merge" principle, nothing will happen.
//
// For implementation simpleness, do not provide a direct way to remove sinlge
// child (otherwise the total indicies of the children array have to be modified).
// User can remove a single child by set its `ignore` as `true` or replace
// it by another element, where its `$merge` can be set as `true` if necessary.

 

在renderItem返回的group元素中設置$mergeChildren='byName',並且給每一類元素設置一個name,這樣每次都會根據name來更新元素

renderGanttItem = (params, api) => {
   ...

    return {
      type: 'group',
      name: 'gantt-group',
      id: categoryIndex,
      info: {data:item},
      children: allChildren,
      $mergeChildren: 'byName'
    };

}

這樣設置了以后,大量元素滾動也非常順滑,解決問題


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM