注意,这里的 graphic 自定义图像和上一篇中的 series-custom 不一样,series-custom是根据数据项来绘制图像的,而这里要介绍的 graphic 则是原生图形元素组件,可以绘制水印、X、Y 轴坐标、饼图中在圆心位置绘制特别的图像等等这些不依赖 data 绘制的图像。如下图:
添加水印;
X 轴线被替换成了一个面;
如果你想了解如何将柱状图替换成 3D 类型的图案,可以点击这里
graphic
只配一个图形元素时的简写方法:
myChart.setOption({
...,
graphic: {
type: 'image',
...
}
});
配多个图形元素:
myChart.setOption({
...,
graphic: [
{ // 一个图形元素,类型是 image。
type: 'image',
...
},
{ // 一个图形元素,类型是 text,指定了 id。
type: 'text',
id: 'text1',
...
},
{ // 一个图形元素,类型是 group,可以嵌套子节点。
type: 'group',
children: [
{
type: 'rect',
id: 'rect1',
...
},
{
type: 'image',
...
},
...
]
}
...
]
});
组合类型
组合类型可以理解为有多个图形组合而成的,例如图一的水印,就是通过多个图形组合而成的,针对这种我们将其称之为组合类型。组合类型的 type 必须为 group,并通过 children 属性将多个图形组合成一个图形。
type
图形的类型,组合类型的值为 group。
x、y
图像的 x、y 坐标(像素)位置
rotation
图像旋转。Math.PI / 4 就是 45 度角。
scaleX、scaleY
图像的缩放
originX、originY
图像旋转、缩放的原点
transition
可以通过'all'指定所有属性都开启过渡动画,也可以指定单个或一组属性。
Transform 相关的属性:'x'、 'y'、'scaleX'、'scaleY'、'rotation'、'originX'、'originY'。例如:
{
type: 'rect',
x: 100,
y: 200,
transition: ['x', 'y']
}
还可以是这三个属性 'shape'、'style'、'extra'。表示这三个属性中所有的子属性都开启过渡动画。例如:
{
type: 'rect',
shape: { // ... },
// 表示 shape 中所有属性都开启过渡动画。
transition: 'shape',
}
在自定义系列中,当 transition 没有指定时,'x' 和 'y' 会默认开启过渡动画。如果想禁用这种默认,可设定为空数组:transition: []
enterFrom
配置图形的入场属性用于入场动画。例如:
{
type: 'circle',
x: 100,
enterFrom: {
// 淡入
style: { opacity: 0 },
// 从左飞入
x: 0
}
}
leaveTo
配置图形的退场属性用于退场动画。例如:
{
type: 'circle',
x: 100,
leaveTo: {
// 淡出
style: { opacity: 0 },
// 向右飞出
x: 200
}
}
enterAnimation
入场动画配置
{
// 动画时长,单位 ms
duration: 300,
// 动画缓动。不同的缓动效果可以参考 https://echarts.apache.org/examples/zh/editor.html?c=line-easing
delay:300,
// 动画延迟时长,单位 ms
easing: 'linear'
}
updateAnimation、leaveAnimation
更新动画配置、离场动画配置
width
用于描述此 group 的宽。
这个宽只用于给子节点定位。
即便当宽度为零的时候,子节点也可以使用 left: 'center' 相对于父节点水平居中。
height
用于描述此 group 的高。
这个高只用于给子节点定位。
即便当高度为零的时候,子节点也可以使用 top: 'middle' 相对于父节点垂直居中。
注意,设置了 width & height 属性和没有设置 width & height 的定位是不一样的。
- 如果设置了
width & height,并使用 x、y(或者 left、top)进行定位。也就是说矩形的左上角就是 x、y (或 left、top)指定的位置; - 如果设置了
width & height,并使用 right、bottom 进行定位。那么矩形的右下角就是 right、bottom 指定的位置。 - 如果没有设置
width & height,此时 group 下的所有子节点都将相对于 group 进行定位,换句话说,如果 group 指定了 right & bottom,那么所有的孩子节点都将相对于该位置进行定位。
left、right
描述怎么根据父元素进行定位。
『父元素』是指:如果是顶层元素,父元素是 echarts 图表容器。如果是 group 的子元素,父元素就是 group 元素。
值的类型可以是:
number:表示像素值。- 百分比值:如 '33%',用父元素的高和此百分比计算出最终值。
'center':表示自动居中。
如果指定 left 或 right,则 shape 里的 x、cx 等定位属性不再生效。
top、bottom
描述怎么根据父元素进行定位。
『父元素』是指:如果是顶层元素,父元素是 echarts 图表容器。如果是 group 的子元素,父元素就是 group 元素。
值的类型可以是:
number:表示像素值。- 百分比值:如 '33%',用父元素的宽和此百分比计算出最终值。
'middle':表示自动居中。
如果指定 top 或 bottom,则 shape 里的 y、cy 等定位属性不再生效。
注意:当 left、right、top、bottom的值为百分比或 center、middle时,是这样计算的:
/**
* @param container_width 表示父容器的宽度
* @param container_height 表示父容器的高度
* @param content_width 表示子节点的宽度
* @param content_height 表示子节点的高度
*/
// left: '50%' | 'center' 的实际偏移量计算
const distX = (container_width - content_width) * 0.5;
// top: '50%' | 'middle' 的实际偏移量计算
const distY = (container_height - content_height) * 0.5
// right: '30%' 的实际偏移量计算
const distX = (container_width - content_width) * (1 - 0.3);
// bottom: '30%' 的实际偏移量计算
const distY = (container_height - content_height) * (1 - 0.3);
当组合类型没有设置 width、height 时,我们可以理解为 container_width 和 container_height 都是 0。
这也就解释了为什么当 group 没有设置 width时,子节点也可以使用 <font style="background-color:rgb(244, 244, 244);">left: 'center'</font> 相对于父节点水平居中。
z
决定图像的层级关系
children
子节点列表,其中项都是一个图形元素定义。
单类型-text
我将其称之为文本类型,就是可以在图表上绘制文本内容,包括自定义文本样式等。
通用数据这里就不再介绍了,和组合类型是一样的。下面介绍文本类型独有的属性:
style
{
// 文本块文字。可以使用 \n 来换行。
text: 'hello world',
// 图形元素的左上角在父节点坐标系(以父节点左上角为原点)中的横坐标值。
x: 0,
// 图形元素的左上角在父节点坐标系(以父节点左上角为原点)中的纵坐标值。
y: 0,
// 字体大小、字体类型、粗细、字体样式。
font: '2em "STHeiti", sans-serif',
// 水平对齐方式,取值:'left', 'center', 'right'。
// 如果为 'left',表示文本最左端在 x 值上。如果为 'right',表示文本最右端在 x 值上。
textAlign: 'left',
// 垂直对齐方式,取值:'top', 'middle', 'bottom'。
// 如果为 top,表示文本的顶部在 y 上,如果为 bottom,表示文本的底部在 y 上
verticalTextAlign: 'top',
// 限制文本的宽度
width: 100,
// 当文本内容超出 width 时的文本显示策略,取值:'break', 'breakAll', 'truncate', 'none'。
// 'break': 尽可能保证完整的单词不被截断(类似 CSS 中的 word-break: break-word;)
// 'breakAll': 可在任意字符间断行
// 'truncate': 截断文本屏显示 '...',可以使用 ellipsis 来自定义省略号的显示
// 'none': 不换行
overflow:'none',
// 当 overflow 设置为 'truncate' 时生效,默认为 ...。
ellipse: '...',
// 填充色。
fill: '#fff',
// 描边色
stroke: '#ff4949',
// 线条宽度。
lineWidth:3,
// 线条样式。可选:'solid'、'dashed'、'dotted'
lineDash: 'solid',
// 阴影模糊半径
shadowBlur: 10,
// 阴影 X,Y 方向偏移。
shadowOffsetX: 10,
shadowOffsetY: 10,
// 阴影的颜色
shadowColor: 'rgba(0, 0, 0, 0.5)',
// 透明度
opacity: 1,
}
单类型-rect
绘制单个矩形,type 为 rect。特有的属性有 shape、style。
shape
{
// 图形元素的左上角在父节点坐标系(以父节点左上角为原点)中的横坐标值。
x: 100,
// 图形元素的左上角在父节点坐标系(以父节点左上角为原点)中的纵坐标值。
y: 100,
// 图形元素的宽度。
width: 100,
// 图形元素的高度。
height: 100,
// 圆角
r: [8],
// 可以是一个属性名,或者一组属性名。 被指定的属性,在其指发生变化时,会开启过渡动画。
// 只可以指定本 shape 下的属性。
transition: ['x', 'y'],
}
style
{
// 填充色
fill: '#fff',
// 描边色
stroke:'#ff4949',
// 线的宽度
lineWidth:3,
// 笔触的类型,round、butt、square
lineCap: 'round',
// 设置线条转折点的样式。默认 miter
lineJoin: 'miter',
// 阴影模糊半径
shadowBlur:5,
// 阴影 X 方向偏移。
shadowOffsetX: 5,
// 阴影 Y 方向偏移。
shadowOffsetY: 5,
// 阴影颜色。
shadowColor: 'rgba(0, 0, 0, 0.4)',
// 透明度。
opacity: 0.5,
}
单类型-image
绘图相片的,type 为 image。
style
{
// 图像 url
image,
// 图形元素的宽度。
width: 100,
// 图形元素的高度。
height: 100,
// 图形元素的左上角在父节点坐标系(以父节点左上角为原点)中的横坐标值。
x: 0,
// 图形元素的左上角在父节点坐标系(以父节点左上角为原点)中的纵坐标值。
y: 0,
// 填充色
fill: '#fff',
// 描边色
stroke:'#ff4949',
// 线的宽度
lineWidth:3,
// 笔触的类型,round、butt、square
lineCap: 'round',
// 设置线条转折点的样式。默认 miter
lineJoin: 'miter',
// 阴影模糊半径
shadowBlur:5,
// 阴影 X 方向偏移。
shadowOffsetX: 5,
// 阴影 Y 方向偏移。
shadowOffsetY: 5,
// 阴影颜色。
shadowColor: 'rgba(0, 0, 0, 0.4)',
// 透明度。
opacity: 0.5,
}
案例一(图1)
graphic: {
elements: [
{
type: 'group',
right: 100,
bottom: 100,
bounding: 'raw',
rotation: Math.PI / 4,
children: [
// group 没有设置 width、height、
// 所以子节点是相对于 right: 100 & bottom: 100 进行定位
{
type: 'rect',
// 图形相对于 group 居中
left: 'center',
top: 'middle',
shape: {
width: 400,
height: 80,
},
style: {
fill: '#fff',
opacity: 0.4,
},
z: 100,
},
{
type: 'text',
// 文本相对于 group 居中
top: 'middle',
left: 'center',
style: {
// @ts-ignore
textAlign: 'left',
verticalAlign: 'top',
fill: '#fff',
text: 'ECHARTS LINE CHART',
font: 'bold 24px sans-serif',
},
z: 100,
}
],
}
]
}
案例二(图2)
graphic: [
{
type: 'image',
left: 55,
bottom: 13,
style: {
image: bgIMG,
width: 410,
height: 39,
},
},
],
案例三
const options: EChartsOption = {
legend: {
show: true,
right: 50,
orient: 'vertical',
icon: 'circle',
textStyle: {
color: '#fff',
},
},
tooltip: {
show: true,
trigger: 'item',
},
grid: {
left: 20,
right: 20,
bottom: 0,
top: 50,
containLabel: true,
},
series: {
type: 'pie',
name: '年产值',
radius: ['40%', '70%'],
itemStyle: {
borderWidth: 2,
borderColor: 'rgba(0, 0, 0, 0.5)',
borderRadius: 10,
},
label: {
show: false,
// 设置 label 的宽高、以及背景
width: 100,
height: 100,
fontSize: 24,
formatter: '{title|{b}年产值}\n{value|{c}}',
// 富文本样式
rich: {
title: {
fontSize: 14,
padding: [35, 0, 10, 0],
},
value: {
fontSize: 20,
fontWeight: 'bold',
}
},
fontWeight: 'bold',
color: '#fff',
borderRadius: 50,
position: 'center',
backgroundColor: '#ff4949',
},
emphasis: {
label: {
show: true,
}
},
data: [
{ value: 19992, name: '2019' },
{ value: 25908, name: '2020' },
{ value: 28009, name: '2021' },
{ value: 30790, name: '2022' },
{ value: 25499, name: '2023' },
{ value: 18994, name: '2024' },
]
},
graphic: {
elements: [
{
type: 'group',
right: 'center',
bottom: 'center',
width: 100,
height: 100,
bounding: 'raw',
// 不要设置 z 属性,否则,series.emphasis.label 无法覆盖掉 graphic 绘制的图像。
children: [
{
// 在圆心位置绘制一个大小为 100 的圆
type: 'circle',
shape: {
cx: 50,
cy: 50,
r: 50,
},
style: {
fill: '#f80',
}
},
{
// 绘制文本标题
type: 'text',
top: 26,
left: 'left',
style: {
// @ts-ignore
textAlign: 'center',
verticalAlign: 'top',
width: 100,
overflow: 'truncate',
ellipsis: '...',
fill: '#fff',
text: '总产值',
font: 'bold 24px sans-serif',
},
},
{
// 绘制文本
type: 'text',
top: 60,
left: 'left',
style: {
// @ts-ignore
textAlign: 'center',
verticalAlign: 'top',
width: 100,
overflow: 'truncate',
ellipsis: '...',
fill: '#fff',
text: '149875',
font: 'bold 16px sans-serif',
},
},
],
}
]
}
};