解决echarts使用renderItem自定义图表时的残影问题

Posted 索美不达米亚

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了解决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方法里自定义绘制甘特图元素,因为每一行的元素非常多,所以只显示当前datazoom时间范围内元素。

// 计算视口内横向的显示图形
        var slider_x = this.myChart.getModel().option.dataZoom.filter(it => it.id == "slider_x")[0]
        var sliderXLeft = new Date(slider_x.startValue)
        var sliderXRight = new Date(slider_x.endValue)
// 根据视口的范围筛选元素
...

这时候碰到问题: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\'
    };

}

这样设置了以后,大量元素滚动也非常顺滑,解决问题

以上是关于解决echarts使用renderItem自定义图表时的残影问题的主要内容,如果未能解决你的问题,请参考以下文章

echarts 柱状图自定义tooltip的内容

使用echart的雷达图的时候,如果文字越界的解决办法记录,标签文字自动换行

echarts饼图,label多行重合问题解决

echarts的tooltip展示自定义值

echarts 自定义图表

Echarts.js 根据数值自定义radar雷达图拐点颜色