echars.toolbox 除了各个内置的工具按钮外,还可以自定义工具按钮,每个工具按钮都可以通过icon自定义展示图标,同时配置iconStyle设置图标样式。
icon 选项
-
可以通过
'image://url'
设置为图片,其中 URL 为图片的链接,或者dataURI
。- URL 为图片链接例如:
rust'image://http://example.website/a/b.png'
- URL 为
dataURI
例如:
rust'image://data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7'
-
可以通过
'path://'
将图标设置为任意的矢量路径。这种方式相比于使用图片的方式,不用担心因为缩放而产生锯齿或模糊,而且可以设置为任意颜色。路径图形会自适应调整为合适的大小。路径的格式参见 SVG PathData。可以从 Adobe Illustrator 等工具编辑导出。
rust
'path://M30.9,53.2C16.8,53.2,5.3,41.7,5.3,27.6S16.8,2,30.9,2C45,2,56.4,13.5,56.4,27.6S45,53.2,30.9,53.2z M30.9,3.5C17.6,3.5,6.8,14.4,6.8,27.6c0,13.3,10.8,24.1,24.101,24.1C44.2,51.7,55,40.9,55,27.6C54.9,14.4,44.1,3.5,30.9,3.5z M36.9,35.8c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H36c0.5,0,0.9,0.4,0.9,1V35.8z M27.8,35.8 c0,0.601-0.4,1-0.9,1h-1.3c-0.5,0-0.9-0.399-0.9-1V19.5c0-0.6,0.4-1,0.9-1H27c0.5,0,0.9,0.4,0.9,1L27.8,35.8L27.8,35.8z'
缺点:只能设置线性图标-无背景
iconStyle 选项
配置过的都知道,只能配置线性图标颜色或者阴影(基本少用),无法添加背景色,只能设置简单的线性图标按钮样式。
如果我们的设计稿是实现这样的图标,那该如何处理?
思路
- 通过你所掌握的任意绘图工具,获得对应图标的
image://[url]
或image://[dataURI]
链接,通过icon
选项配置得到自定义图标
通过 image://
格式指定的自定义图标,会有尺寸缩放问题,所以需要稍微调整实际尺寸。
例子通过 svg + btoa
获取一个dataURI:
arduino
const customIconSVG = `<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 30 30"><rect x="0" y="0" width="30" height="30" rx="5" fill="#F7F7F7" /><polyline points="10 13 15 18 20 13" fill="black" /><line x1="15" y1="13" x2="15" y2="5" stroke="black" stroke-width="2" stroke-linecap="round" /><line x1="6" y1="23" x2="24" y2="23" stroke="black" stroke-width="2" stroke-linecap="round" /></svg>`
const iconDataURI = 'data:image/svg+xml;base64,' + btoa(customIconSVG);
// data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIzMCIgaGVpZ2h0PSIzMCIgdmlld0JveD0iMCAwIDMwIDMwIj48cmVjdCB4PSIwIiB5PSIwIiB3aWR0aD0iMzAiIGhlaWdodD0iMzAiIHJ4PSI1IiBmaWxsPSIjRjdGN0Y3IiAvPjxwb2x5bGluZSBwb2ludHM9IjEwIDEzIDE1IDE4IDIwIDEzIiBmaWxsPSJibGFjayIgLz48bGluZSB4MT0iMTUiIHkxPSIxMyIgeDI9IjE1IiB5Mj0iNSIgc3Ryb2tlPSJibGFjayIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIC8+PGxpbmUgeDE9IjYiIHkxPSIyMyIgeDI9IjI0IiB5Mj0iMjMiIHN0cm9rZT0iYmxhY2siIHN0cm9rZS13aWR0aD0iMiIgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIiAvPjwvc3ZnPg==
- 定义每个图标的普通状态icon和悬浮状态icon
js
// 定义每个图标的普通状态和鼠标悬浮状态的路径
const iconInfo = {
save: {
normal: 'image://data:image/png;base64,XXXXX', // 保存图标的普通状态路径
hover: 'image://data:image/png;base64,YYYYY' // 保存图标的鼠标悬浮状态路径
},
dataZoom: {
normal: 'image://data:image/png;base64,AAAAA', // 数据区域缩放图标的普通状态路径
hover: 'image://data:image/png;base64,BBBBB' // 数据区域缩放图标的鼠标悬浮状态路径
},
// 其他图标的普通状态和鼠标悬浮状态路径 // ...
};
- 声明echart实例
js
const option = {
// ...
toolbox: {
feature: {
saveAsImage: {
icon: iconInfo.save.normal, // 保存图标的普通状态路径
},
dataZoom: {
icon: iconInfo.dataZoom.normal, // 数据区域缩放图标的普通状态路径
}
// 其他图标的配置
},
// ...
}
// ...
};
- 最后通过echart实例监听鼠标
mousemove
事件,通过echartInstance.containPixel
api判断鼠标位置,如果是toolbox对应图标,则进行图标替换:
js
myChart.getZr().on('mousemove', function (params) {
var pointInPixel = [params.offsetX, params.offsetY];
for (var key in iconInfo) {
if (myChart.containPixel('toolbox', pointInPixel, {icon: key})) {
// 根据图标名称切换图标显示
myChart.dispatchAction({
type: 'updateAxisPointer',
axisPointer: {
toolboxIcon: iconInfo[key].hover // 切换为鼠标悬浮状态的图标
}
});
} else {
// 鼠标不在该图标区域内,恢复普通状态的图标
myChart.dispatchAction({
type: 'updateAxisPointer',
axisPointer: {
toolboxIcon: iconInfo[key].normal // 恢复为普通状态的图标
}
});
}
}
});
最终实现
js
var customIconSVG = `<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 30 30"><rect x="0" y="0" width="30" height="30" rx="5" fill="#F7F7F7" /><polyline points="10 13 15 18 20 13" fill="black" /><line x1="15" y1="13" x2="15" y2="5" stroke="black" stroke-width="2" stroke-linecap="round" /><line x1="6" y1="23" x2="24" y2="23" stroke="black" stroke-width="2" stroke-linecap="round" /></svg>`;
var customIconHoverSVG = `<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 30 30"><rect x="0" y="0" width="30" height="30" rx="5" fill="#3D97D0" /><polyline points="10 13 15 18 20 13" fill="white" /><line x1="15" y1="13" x2="15" y2="5" stroke="white" stroke-width="2" stroke-linecap="round" /><line x1="6" y1="23" x2="24" y2="23" stroke="white" stroke-width="2" stroke-linecap="round" /></svg>`;
// 自定义图标
var iconInfo = {
saveAsImage: {
normal: 'image://data:image/svg+xml;base64,' + btoa(customIconSVG), // 保存图标的普通状态路径
hover: 'image://data:image/svg+xml;base64,' + btoa(customIconHoverSVG), // 保存图标的鼠标悬浮状态路径
}
};
// 配置项
option = {
// ...
toolbox: {
feature: {
saveAsImage: {
title: 'Save as image', // 基于title值进行判断
icon: iconInfo.saveAsImage.normal
}
}
},
// ...
};
// 事件监听
// 不同版本echarts实现方式有差异
myChart.getZr().on('mousemove', function (params) {
var pointInPixel = [params.offsetX, params.offsetY];
if (params.topTarget && params.topTarget.__title === 'Save as image') { // 基于title值进行判断
// 鼠标悬浮在保存图标区域内,切换图标显示
option.toolbox.feature.saveAsImage.icon = iconInfo.saveAsImage.hover; // 切换为鼠标悬浮状态的图标
myChart.setOption(option);
} else {
// 鼠标不在保存图标区域内,恢复普通状态的图标
option.toolbox.feature.saveAsImage.icon = iconInfo.saveAsImage.normal; // 恢复为普通状态的图标
myChart.setOption(option);
}
});
normal:
hover:
注:不同版本ecahrts监听鼠标移动到toolbox有差异
注:setOption引发重绘导致悬浮文字不显示