Echarts的custom类型绘制同一metrics的不同区间范围

【Echarts的custom类型绘制同一metrics的不同区间范围】接到的需求是为一个在大数据分析上叫做ABTest的结果绘制可视化图像,通过这个需求再一次刷新了对ECharts的认知,感觉这个强大的库几乎无所不能。
先附上一张完成之后的效果图:
Echarts的custom类型绘制同一metrics的不同区间范围
文章图片

讲述一下从开始选类型到最后确定的过程,需求是为每一个metrics展示它的三个区间范围以及一个中间值,相当于1个纵轴值对应4个横轴值,并且横轴的值包括三对范围值和一个确定的值。我刚开始找了一个叫做rangbar的第三方类库实现了部分需求,原因是中间确切的值也是取了一个范围,导致最终的显示效果并不是完全契合需求,并且这个累类库是收费的。后来就选用了ECharts,一个精通ECharts的同事推荐了自定义系列里的Profile,就是如下:
Echarts的custom类型绘制同一metrics的不同区间范围
文章图片

然后,把这些断续的区间,取成重合的区间范围,就可以满足需求,同时还有一个问题,跟rangebar一样的问题,中间确切值也是一个范围。后来发现ECharts还有一项配置,在renderItem的时候可以return一组图形,并且图形也是自定义的,这样的话,就可以返回三个矩形和一条直线,完美符合需求,以下分别是data数据结构,options的配置,以及renderItem的配置:

dataSource = { categories: [metrics1,metrics2,metrics3], data: [ { value: [index, rangeStart1, rangeEnd1,rangeStart2, rangeEnd2,rangeStart3, rangeEnd3, mean], itemStyle: {} }, ] }; option = { tooltip: { formatter(params: any) { return `${params.marker + params.name}: ${params.value[7]}%`; }, }, dataZoom: [ { type: 'slider', filterMode: 'weakFilter', }, ], grid: { top: 30, }, xAxis: { axisLabel: { formatter: '{value}%', }, }, yAxis: { type: 'category', data: dataSource.categories, inverse: true, }, series: [ { type: 'custom', renderItem: renderMetricItem, itemStyle: { opacity: 0.8, }, encode: { x: [1, 2], y: 0, }, data: dataSource.data, }, ], }; renderMetricItem (params, api){ const children = []; const colors = [RANGE_LEVEL1, RANGE_LEVEL2, RANGE_LEVEL3]; const categoryIndex = api.value(0); const height = api.size([0, 1])[1] * 0.5; // confidence interval rect shapes for (let i = 0; i < 3; i += 1) { const start = api.coord([api.value(i * 2 + 1), categoryIndex]); const end = api.coord([api.value(i * 2 + 2), categoryIndex]); const rectShape = echarts.graphic.clipRectByRect( { x: start[0], y: start[1] - height / 2, width: end[0] - start[0], height, }, { x: params.coordSys.x, y: params.coordSys.y, width: params.coordSys.width, height: params.coordSys.height, }, ); const item = { type: 'rect', transition: ['shape'], shape: rectShape, style: { fill: colors[i], }, }; children.push(item); const s = api.coord([api.value(7), categoryIndex]); children.push({ type: 'line', shape: { x1: s[0], y1: s[1] - height / 2, x2: s[0], y2: s[1] + height / 2, }, style: { stroke: RANGE_LEVEL4, lineWidth: 5, }, }); return { type: 'group', children, }; }

    推荐阅读