「这是我参与2022首次更文挑战的第N天,活动详情查看:2022首次更文挑战」。
前言
杭州最近天气一直都不是很好,有是下雨又是下雪,刚开工设计那边就给了我一版数据可视化的设计稿让我做,我从中挑了一个比较值得记录的(好像也不太值得,因为并不难🐶🐶)就是下面这张
整体也并不难,重点是在画那根柱子上面,如何画这个柱子其实用Echarts中的自定义图表手动绘制路径就可以很简单的实现出来。
从图上可以看到我们要画一个蓝色的柱子和一块黄色的菱形,所以这里就需要分开画两个路径分别渲染出来
开始绘制🔛
首先我们要定义一个custom类型的图表,如下所示
接下来我们要关心的是
renderItem这里要返回什么,还有params和api参数分别都有什么,因为内容有点多,这里不过解释具体可以看官方文档,这里我们要用到的是api.value()和api.coord()两个方法
要知道上图中data的每一个数据项都会调用一次
renderItem
-
api.value():得到给定维度的数据值,说白了就是获取当前数据项的下标和值 -
@return {number} 给定维度上的值。
api.value(0):获取数据项的下标 -- 第执行得到 0 (对应上图第一个data数据项)api.value(1):获取数据项的值 -- 第执行得到 120(对应上图第一个data数据项)
-
api.coord():将数据值映射到坐标系上。也就是将上面所得到的数据当作数组传入其中-
@param {Array.} data 数据值。
-
@return {Array.} 画布上的点的坐标,至少包含:[x, y] 对于polar坐标系,还会包含其他信息: polar: [x, y, radius, angle]
-
使用自定义图表 💚
renderItem: function (params, api) {
//这里获取到的是柱状图顶部的坐标
const topAxis = api.coord([api.value(0), api.value(1)]);
//这里获取的是柱状图底部的坐标
const bottomAxis = api.coord([api.value(0), 0]);
return {
type: 'InclinedRoofBar', //这里是自定义类型,
shape: { //这里是传递的参数
topAxis,
bottomAxis
}
};
}
注意:x轴和y轴的 [0, 0] 点在左上角 上面获取的到的
topAxis和bottomAxis属性分别是顶部点的x轴和y轴、底部点的x轴和y轴
根据上面获取到的两个坐标点,我们就能根据坐标点进行绘制图形,这里涉及到canvas绘制路径,所以不熟的可以先看一下这篇文章:🚪传送门:canvas教程✈️
还有下面编写绘制自定义图形的方法,下面会用到以下两个方法,参考🚪传送门:Echarts文档✈️
绘制蓝色柱子路径并注册使用 💙
const InclinedRoofBar = echarts.graphic.extendShape({
//ctx : 当成canvas来绘制路径即可
// shape:renderItem返回的shape参数中包含的数据
buildPath: function (ctx, shape) {
// topAxis,bottomAxis
let topAxis = shape.topAxis;
let bottomAxis = shape.bottomAxis;
// 绘制的初始点
const path0 = [topAxis[0] + 10, topAxis[1]];
// 绘制的第一条线
const path1 = [topAxis[0] - 10, topAxis[1] + 10];
// 绘制第二条线
const path2 = [bottomAxis[0] - 10, bottomAxis[1]];
// 绘制第三条线
const path3 = [bottomAxis[0] + 10, bottomAxis[1]];
// 斜切柱子
ctx
.moveTo(path0[0], path0[1])
.lineTo(path1[0], path1[1])
.lineTo(path2[0], path2[1])
.lineTo(path3[0], path3[1])
//闭合路径
.closePath();
}
});
//绘制完成之后需要注册出来使用
echarts.graphic.registerShape('InclinedRoofBar', InclinedRoofBar);
option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
data: [120, 200, 150, 80, 70, 110, 130],
type: 'custom',
renderItem: function (params, api) {
const topAxis = api.coord([api.value(0), api.value(1)]);
const bottomAxis = api.coord([api.value(0), 0]);
return {
type: 'InclinedRoofBar', //使用自定义注册类型!!!!!
shape: {
topAxis,
bottomAxis
},
style:{ //给柱子添加颜色样式
fill:'blue'
}
};
}
}
]
};
上面的代码中主要是graphic.extendShape()方法中传递的buildPath方法,该参数需要分析和绘制路径,方法接收两个参数
- ctx : 当成canvas来绘制路径即可
- shape:renderItem返回的shape参数中包含的数据
需要注意的是canvas中 x轴和y轴的起始点是左上角 [ 0 , 0 ] ,x轴+10会坐标会往右移,y轴+10坐标会往下移。这样我们会会得到以下图表
绘制黄色菱形路径并注册使用
上面我们已经画过了蓝色柱子了,接下来可以直接复制修改即可,因为黄色菱形的第一个点和第二个点与蓝色柱子是重合的,所以只需要修改第三第四个点即可
// 绘制第二条线
const path2 = [topAxis[0]- 10, topAxis[1] + 20];
// 绘制第三条线
const path3 = [topAxis[0] + 10, topAxis[1] + 10];
将注册好的菱形路径替换掉原来的柱子查看效果
合并两个自定义类型 💛
使用 group类型组合两个自定义类型
group 是唯一的可以有子节点的容器。group 可以用来整体定位一组图形元素。
renderItem: function (params, api) {
const topAxis = api.coord([api.value(0), api.value(1)]);
const bottomAxis = api.coord([api.value(0), 0]);
return {
type: 'group', //使用自定义注册类型
children: [
{
type: 'InclinedRoofBar', //柱子路径
shape: {
topAxis,
bottomAxis
},
style: {
//上色
fill: 'blue'
}
},
{
type: 'InclinedRoofBar2', //菱形路径
shape: {
topAxis,
bottomAxis
},
style: {
//上色
fill: '#fee082'
}
}
]
};
}
最终代码(可粘贴到Echarts实例)🧡
const InclinedRoofBar = echarts.graphic.extendShape({
//ctx : 当成canvas来绘制路径即可
// shape:renderItem返回的shape参数中包含的数据
buildPath: function (ctx, shape) {
// topAxis,bottomAxis
let topAxis = shape.topAxis;
let bottomAxis = shape.bottomAxis;
// 绘制的初始点
const path0 = [topAxis[0] + 10, topAxis[1]];
// 绘制的第一条线
const path1 = [topAxis[0] - 10, topAxis[1] + 10];
// 绘制第二条线
const path2 = [bottomAxis[0] - 10, bottomAxis[1]];
// 绘制第三条线
const path3 = [bottomAxis[0] + 10, bottomAxis[1]];
// 斜切柱子
ctx
.moveTo(path0[0], path0[1])
.lineTo(path1[0], path1[1])
.lineTo(path2[0], path2[1])
.lineTo(path3[0], path3[1])
//闭合路径
.closePath();
}
});
//绘制完成之后需要注册出来使用
echarts.graphic.registerShape('InclinedRoofBar', InclinedRoofBar);
// 黄色菱形
const InclinedRoofBar2 = echarts.graphic.extendShape({
//ctx : 当成canvas来绘制路径即可
// shape:renderItem返回的shape参数中包含的数据
buildPath: function (ctx, shape) {
// topAxis,bottomAxis
let topAxis = shape.topAxis;
let bottomAxis = shape.bottomAxis;
// 绘制的初始点
const path0 = [topAxis[0] + 10, topAxis[1]];
// 绘制的第一条线
const path1 = [topAxis[0] - 10, topAxis[1] + 10];
// 绘制第二条线
const path2 = [topAxis[0]- 10, topAxis[1] + 20];
// 绘制第三条线
const path3 = [topAxis[0] + 10, topAxis[1] + 10];
// 斜切柱子
ctx
.moveTo(path0[0], path0[1])
.lineTo(path1[0], path1[1])
.lineTo(path2[0], path2[1])
.lineTo(path3[0], path3[1])
//闭合路径
.closePath();
}
});
//绘制完成之后需要注册出来使用
echarts.graphic.registerShape('InclinedRoofBar2', InclinedRoofBar2);
option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [
{
data: [120, 200, 150, 80, 70, 110, 130],
type: 'custom',
renderItem: function (params, api) {
const topAxis = api.coord([api.value(0), api.value(1)]);
const bottomAxis = api.coord([api.value(0), 0]);
return {
type: 'group', //使用自定义注册类型
children: [
{
type: 'InclinedRoofBar', //使用自定义注册类型
shape: {
topAxis,
bottomAxis
},
style: {
//上色
fill: 'blue'
}
},
{
type: 'InclinedRoofBar2', //使用自定义注册类型
shape: {
topAxis,
bottomAxis
},
style: {
//上色
fill: '#fee082'
}
}
]
};
}
}
]
};
共勉 💯
文章写的不太好,如果有问题可以评论回复😅