【Echart】想在图表中使用自定义Icon?看这一篇就够了!

3,705 阅读3分钟

我们在平时的业务开发过程中不可避免的会与图表打交道,有时候UI会为图表设计一些特别的Icon进行展示。比如图例(legend)、提示浮层(tooltip)以及表中数据点(symbol)。

Snipaste_2023-05-23_19-34-39.png

马赛克部分为图例所对应的文字,由于不明原因先打上马赛克。

从上面的图中可以看到,图例、tooltip以及表中的数据点都添加了自定义icon【闪电】。那么具体是如何实现的呢?

一、图例legend

Echart官方虽然有提供默认的图例icon,circlerectroundRecttrianglediamondpinarrownone,但还是太少了。

legend: {
    data: [
        {icon: 'circle', name: '圆形'},
        {icon: 'rect', name: '矩形'},
        {icon: 'roundRect', name: '圆角矩形'},
        {icon: 'triangle', name: '三角形'},
        {icon: 'diamond', name: '菱形'},
        {icon: 'pin', name: '图钉'},
        {icon: 'arrow', name: '箭头'}
    ],
    ...
}

使用图片链接或base64图片

图片使用前缀为 image://

示例如下:

legend: {
   top: '5%',
   left: 'center',
   itemWidth: 30,
   itemHeight: 30,
   data: [
       {icon: 'image://https://profile.csdnimg.cn/F/0/1/3_rudy_zhou', name: '一个'},
       {icon: 'image://data:image/jpg;base64,iVBORw0KGgoAAAANSUhEUgAAAEsAAABLCAYAAAA4TnrqAAAI2klEQVR4nO2bf2hUVxbHP29mkkwy+Wkm2fywxtRutia7htSa7dYatbBChbBQ...', name: '一个base64的图例'}
   ]
},

这种方式虽然能自定义任意UI设计的图标,但是不支持动态置灰,无法跟随默认图表数据颜色。

使用矢量路径

我们最常见到的svg图片里面的形状就是使用矢量路径绘制:

<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
  <g id="lightningdeal" transform="translate(-1217 -338)">
    <rect id="&#x77E9;&#x5F62;_862" width="12" height="12" transform="translate(1217 338)" fill="none"></rect>
    <path id="lightningdeal-2" d="M1,6,8.5,1,7.25,5H11L3.5,11,4.75,6Z" transform="translate(1217 338)" fill="#f54242"></path>
  </g>
</svg>

上面代码里path标签中的属性d的值,就是矢量路径。

Echart使用:

legend: {
    top: '5%',
    left: 'center',
    itemWidth: 12,
    itemHeight: 12,
    icon: 'path://M1,6,8.5,1,7.25,5H11L3.5,11,4.75,6Z'
},

由于一般的SVG具有viewbox,单一写矢量路径无法确定具体大小,因此一律按viewbox为1算,也就是说,你的图标会非常非常小,这个时候不要忘了使用itemWidthitemHeight来设置大小。

由于这样的设置itemWidthitemHeight是批量的,如果此时我并不希望其他图标也是12 * 12,需要将legend对象字面量改成legend数组。

legend:[{
    itemWidth:10,
    itemHeight:10,
    data:[{name:'数量',icon:'rect'}],
    textStyle: { color: "#3BAEFE", fontSize: 8, fontFamily: "微软雅黑" }, // 设置样式
    bottom:5, //调整位置
    left:'45%' //调整位置 
    },{
    itemWidth:12,
    itemHeight:12,
    data:[{name:'价值',icon:'path://M1,6,8.5,1,7.25,5H11L3.5,11,4.75,6Z'}],
    textStyle: { color: "#3BAEFE", fontSize: 12, fontFamily: "微软雅黑" }, // 设置样式
    bottom:5, //调整位置
    right:'45%' //调整位置 
}]

二、浮层tooltip

这里我们要借用tooltip属性的formatter函数来完成。

formatter的第一个参数接收一个数据集,就是我们渲染表格用的数据集。

const getTooltips = (marker, name, value) => (
    `<div class="tooltip_item">
        <div>${marker}<span>${name}</span></div>
        <div class="tooltip_value">${value}</div>
    </div>`
)

tooltip: {
    formatter(params) {
        let htmStr = ``
        let title = ''

        params.forEach(item => {
            if (!title) {
                title = `<div>${item.name}</div>`
                htmStr += title
            }
            if (item.seriesName === '自定义icon legend') {
                if (item.value === null) return // 若值为null,不拼接html
                const marker = '<span><i class="icon_iconfont"></i></span>'
                htmStr += getTooltips(marker, item.seriesName, item.value)
            } else {
                htmStr += getTooltips(item.marker, item.seriesName, item.value)
            }
        })
        return htmStr
    },
    ...
},

其实item.marker就是Echart默认的tooltip图标,我们将其进行替换掉即可。但这里我们用的不是path,而是基础的html模板字符串,通过类名使用iconfont来展示自定义图标。

注意if (item.value === null) return // 若值为null,不拼接html,它会带来如图所示的效果

Snipaste_2023-05-23_19-34-59.png

三、数据点symbol

自定义symbol的图标与自定义legend的图标类似,也是利用path来完成。

series: [
    {
        name: 'A',
        type: 'line',
        data: dataA,
        smooth: true,
        showSymbol: false,
        ...
    },
    {
        name: 'B',
        type: 'scatter',
        data: dataB,
        symbol: 'path://M1,6,8.5,1,7.25,5H11L3.5,11,4.75,6Z',
        showSymbol: true,
        ...
    }
]

我们使用scatter来让自定义的图标进行离散,以达到文章第一张图展示的效果。