不知道该怎么称呼,总之设计师出图如图所示,要求用echarts绘制。普通的柱状图无法满足如上图形,好在echarts提供了pictorialBar象形柱状图,可以自定义柱的形状。
简单配置如下:
<template>
<div class="container">
<div id="chart"></div>
</div>
</template>
<script setup>
import * as echarts from "echarts";
import { onMounted } from "vue";
const xdata = ref([])
const option = {
legend: {
show: false,
},
xAxis: {
data: ['数据1', '数据2', '数据3', '数据4', '数据5'],
},
yAxis: {
},
series: [
{
name: '随机数据',
type: 'pictorialBar',
symbol: 'roundRect',
symbolRepeat: true,
symbolSize: [20, 10],
itemStyle: {
normal: {
barBorderRadius: 5,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#FBDA61" },
{ offset: 0.5, color: "#FF5ACD" },
{ offset: 1, color: "#FF6A88" }
])
}
},
barWidth: 16,
barGap: 0.2,
data: xdata.value
}
]
}
function setXdata() {
// 设置5个随机数作为数据
for (let i = 0; i < 5; i++) {
xdata.value.push(Math.floor(Math.random() * 100))
}
}
onMounted(() => {
setXdata();
// 绘制echarts图形
const chart = echarts.init(document.getElementById('chart');
chart.setOption(option)
})
</script>
<style scoped>
</style>
得到的效果如下:
上面代码的渐变色被加到了每个单独的roundRect当中,这并不是我想要的效果,我想要的是整体有一个渐变的背景色作为底,上面显示圆角矩形,相当于镂空了固定的形状。
在echarts官网上搜索了半天,接近我想要的效果的是如下的图,用到了symbolClip属性,然而直接尝试之后依旧不行。
转变思路,既然echarts支持柱状图变成自己绘制的任意形状,那我为什么不直接绘制一个圆角矩形堆叠的图形?这样一来所有矩形被视为整体,渐变色自然能整体显示出来。
要想自己绘制形状,就要用到echarts的path进行绘制,官方给出的文档链接如下:
SVG的路径绘制非常复杂,研究了下。首先,绘制以path:// 开头,后面跟着用来画图的内容。
画图的内容为字母+数字的形式,字母代表操作,即绘制直线、曲线或者半圆;数字代表参数,不同的操作对应的参数个数不同,但是必定包含坐标。
将需要用到的规则总结如下
1. 画幅坐标:横向为x轴,纵向为y轴,左上角为原点(0, 0)
2. M写在最前面,表示开始,后面紧跟两个坐标,表示起始点的位置。例如 M 10 20 就是将起始点放到(10, 20)的位置,接下来的绘制从此处开始。
3. z写在最后面,表示闭合路径,也就是将z前面到达的点和起始点连接起来。例如 z之前进行的操作停在了(20, 20)的位置,那么加入z之后,自动给(20, 20)和(10, 20)之间绘制一条直线,闭合路径;如果z之前的点与起始点相同,则不做重复
4. 不同的数字之间要加空格间隔开,也可以加逗号;字母和数字之间可以加空格,也可以不加。"M 10 20", "M10, 20"的写法都是合法的,但是不能写成"M,10,20" 或者"M1020"的样子。
5. 绘制直线有3个字母,分别是L(line), H(horizontal), V(vertical)。L后面跟两个坐标,表示从前面的坐标到此坐标连接一条直线;H后面跟一个坐标x1,表示从前面的(x0, y)到(x1, y)绘制一条直线;V后面跟一个坐标y1,表示从前面的(x, y0)到(x, y1)绘制一条直线。形象化如图所示:
6. 绘制圆弧用到的字母是A,这个比较复杂,后面跟着7个参数,(rx ry x-axis-rotation large-arc-flag sweep-flag x y),前两个参数是x方向和y方向上的半径,如果一样,绘制出的就是圆形,不一样就可以绘制出椭圆;最后两个参数是弧线停止的位置;中间三个参数都是布尔值,官网上分别提供了0 1 0和0 0 0的案例,目前我不知道x-axis-rotation和sweep-flag是做什么用的,中间的large-arc-flag表示的是你要大的圆弧还是小的圆弧,例如,设置(10, 0)为起点,(0, 10)为终点,10为半径,large-arc-flag设置为0的时候绘制1/4圆,设置为1时绘制3/4圆。
知道了以上的内容,就可以开始绘制了!
因为ehcarts会将path生成的svg图像进行自适应,所以不用设置成实际的宽度和高度,暂定为宽100高40的矩形,矩形之间的距离为10.
示意图如下:
根据上面学习到的内容,可以轻松写出最上方矩形对应的path路径
M0 10 A10 10 0 0 1 10 0 H90 A10 10 0 0 1 100 10 V30 A10 10 0 0 1 90 40 H10 A10 10 0 0 1 0 30 V10z
因为形状是竖向摞着的,所以每次变化的只有y坐标。将y坐标替换为变量。
将之前的代码修改一下,可以得到最终的结果。
import * as echarts from "echarts";
import { onMounted } from "vue";
const xdata = ref([])
const option = {
legend: {
show: false,
},
xAxis: {
data: ['数据1', '数据2', '数据3', '数据4', '数据5'],
},
yAxis: {
},
series: [
{
name: '随机数据',
type: 'pictorialBar',
symbolRepeat: false, // 不再需要设置symbol的形状,采用自定义形状
itemStyle: {
normal: {
barBorderRadius: 5,
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{ offset: 0, color: "#FBDA61" },
{ offset: 0.5, color: "#FF5ACD" },
{ offset: 1, color: "#FF6A88" }
])
}
},
barWidth: 16,
barGap: 0.2,
data: xdata.value
}
]
}
function setXdata() {
// 设置5个随机数作为数据
for (let i = 0; i < 5; i++) {
xdata.value.push(Math.floor(Math.random() * 100))
}
// 获取最大值,用来计算步数
const maxVal = Math.floor(Math.max(...xdata));
// 处理数据
xdata = xdata.map(item => {
let str = 'path://'; //path字符串
let step = item / maxVal * 20; //步数,即要绘制多少个圆角矩形,可以自定义
let pos = 0; //从0位置开始
for (let i = 0; i < step; i++) {
str += `M0 ${pos + 10} A10 10 0 0 1 10 ${pos} H90 A10 10 0 0 1 100 ${pos + 10} V${pos + 30} A10 10 0 0 1 90 ${pos + 40} H10 A10 10 0 0 1 0 ${pos + 30} V${pos + 10} `;
pos += 50;
}
str += 'z'; //闭合路径
return {
value: item,
symbolClip: true, //为每个柱设置形状
symbol: str
}
})
}
onMounted(() => {
setXdata();
// 绘制echarts图形
const chart = echarts.init(document.getElementById('chart');
chart.setOption(option)
})