在UI提供的效果图中,总有些平常开发遇到很少的图表展示情况。本篇文章就是总结了几个实际开发中遇到的两个地方来说一下。
饼图的展示问题
当 radius 设置为一个值时,在 echarts v4 版本和 v5 版本的不一样的展示问题。
{
type: 'pie',
radius: ['55%'],
center: ['50%', '50%'],
data: [
{
name: "1",
value: "3720"
},
{
name: "2",
value: "2920"
},
{
name: "3",
value: "2200"
},
{
name: "4",
value: "1420"
}
]
}
复制代码
上面是饼图设置中 series 的配置,radius 是设置饼图的半径。
这里数组的第一项是内半径,第二项是外半径,而有时我们实现一些非数据展示的圆环内边线和外边线之类的,就可能数组中只设置一个值,在这个情况下,我们会发现 v4 和 v5 版本会有不同的展示问题,在 v4 中 tooltip 是不显示的,这个是我们要的,因为特殊线只是展示效果,但在 v5 中就会有 tooltip 的提示。
这个问题就让我们探究一下到底是什么原因导致的。
这个图就是在 v4 版本下面的效果,相当于 radius 中只设置了外半径,内半径不存在,这个圆环的环宽是没有的。
这个则是v5版本下面的效果,radius 设置的值是为外半径,内半径则被认为是 0,此时环宽就是这个外半径,展示出的效果就是一个圆。
现在,我们应该就清楚为什么两个版本的 tooltip 一个显示,一个不显示的问题所在了。
3d 柱状图
v3 版本实现
因为 UI 提供了一个 3d 柱状图的效果图,所以就去查了一下 echarts 里面有什么方法可以实现。
在百度查找中,找到一个可以实现的 demo。
引入 echarts-bar3d 插件后,其他配置和平常柱状图没有区别,效果也算可以。
series: [
{
type: 'bar3d',
zlevel: 1,
data: [400, 400, 400, 400, 400, 400, 400],
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(
0, 0, 0, 1,
[
{ offset: 0, color: '#17404d' },
{ offset: 1, color: '#051a2e' }
]
),
opacity: 0.8
}
}
},
{
type: 'bar3d',
zlevel: 2,
barGap: '-100%',
data: [300, 120, 175, 20, 230, 350, 400],
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(
0, 0, 0, 1,
[
{ offset: 0, color: '#ffcd98' },
{ offset: 1, color: '#e19709' }
]
),
opacity: 0.8
}
}
}
]
复制代码
可以看到和我们正常的 bar 图表配置没有区别,只是这个 y 轴的分隔线加上效果就不太一样了。
可以明显看到这个 3d 效果会让分隔线也有个 3d 效果,但是这个问题可以和 UI 商量,还是在接受范围内,可最后去使用,才发现,这个 echarts 版本也是完全不一样,这个是在 v3.7 版本中实现的,现在都已经到 v5 版本,现在的 3d 效果已经完全不是这个样子,在项目中也不可能再引入一个 v3 的版本。所以需要再去换个方向了。
gl 配置 3d 展示
在 echarts 的 GL 配置中找到 bar3D,可以发现已经和原先柱状图的配置有一些差别了,先是坐标轴多出一个 z 轴,而且配置也都相应的变成 xAxis3D,yAxis3D 等,但基本上的配置都还是和原先无差,需要特别注意的就是 data 的数据是一个数组表示一个数据在 x,y,z 三个坐标轴下的位置。
但是实现效果还是和我们想要的差很多,这个完全 3d 的效果完全不是我们想要的,我们需要的只是一个伪 3d 的展示即可。
伪 3d 展示柱状图
去 echarts 图表平台的示例库中可以找到一些参考。
简单的就是这种,只需要 series 中再多加入两个 pictorialBar 配置。这个是象形柱图配置,就是设置各种具象图形元素(如图片、SVG PathData 等)的柱状图,这里我们只需要简单的图形类型即可,这个 demo 使用的就是 rect。
但是这个效果跟我们想要的也差的有点太多,所以又找到另外一种的图表设置。
自定义图表
echarts还有一个自定义图表功能, custom series 自定义系列能让用户定制渲染逻辑。
我们可以用此方法写出一个伪3d柱状图图表。
const CubeLeft = echarts.graphic.extendShape({
shape: {
x: 0,
y: 0
},
buildPath: function(ctx, shape) {
const xAxisPoint = shape.xAxisPoint
const c0 = [shape.x + 8, shape.y]
const c1 = [shape.x - 8, shape.y]
const c2 = [xAxisPoint[0] - 8, xAxisPoint[1]]
const c3 = [xAxisPoint[0] + 8, xAxisPoint[1]]
ctx.moveTo(c0[0], c0[1]).lineTo(c1[0], c1[1]).lineTo(c2[0], c2[1]).lineTo(c3[0], c3[1]).closePath()
}
})
const CubeRight = echarts.graphic.extendShape({
shape: {
x: 0,
y: 0
},
buildPath: function(ctx, shape) {
const xAxisPoint = shape.xAxisPoint
const c1 = [shape.x + 8, shape.y]
const c2 = [xAxisPoint[0] + 8, xAxisPoint[1]]
const c3 = [xAxisPoint[0] + 13, xAxisPoint[1] - 3]
const c4 = [shape.x + 13, shape.y - 3]
ctx.moveTo(c1[0], c1[1]).lineTo(c2[0], c2[1]).lineTo(c3[0], c3[1]).lineTo(c4[0], c4[1]).closePath()
}
})
const CubeTop = echarts.graphic.extendShape({
shape: {
x: 0,
y: 0
},
buildPath: function(ctx, shape) {
const c1 = [shape.x - 8, shape.y]
const c2 = [shape.x + 8, shape.y]
const c3 = [shape.x + 13, shape.y - 3]
const c4 = [shape.x - 3, shape.y - 3]
ctx.moveTo(c1[0], c1[1]).lineTo(c2[0], c2[1]).lineTo(c3[0], c3[1]).lineTo(c4[0], c4[1]).closePath()
}
})
echarts.graphic.registerShape('CubeLeft', CubeLeft)
echarts.graphic.registerShape('CubeRight', CubeRight)
echarts.graphic.registerShape('CubeTop', CubeTop)
option = {
series: [{
type: 'custom',
renderItem: (params, api) => {
// 对于 data 中的每个 dataItem,都会调用这个 renderItem 函数。
// (但是注意,并不一定是按照 data 的顺序调用)
const location = api.coord([api.value(0), api.value(1)])
return {
type: 'group',
children: [{
type: 'CubeLeft',
shape: {
api,
xValue: api.value(0),
yValue: api.value(1),
x: location[0],
y: location[1],
xAxisPoint: api.coord([api.value(0), 0])
},
style: {
fill: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: '#02ffff'
},
{
offset: 1,
color: '#069095'
}
])
}
}, {
type: 'CubeRight',
shape: {
api,
xValue: api.value(0),
yValue: api.value(1),
x: location[0],
y: location[1],
xAxisPoint: api.coord([api.value(0), 0])
},
style: {
fill: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: '#199d9d'
},
{
offset: 1,
color: '#0b6c70'
}
])
}
}, {
type: 'CubeTop',
shape: {
api,
xValue: api.value(0),
yValue: api.value(1),
x: location[0],
y: location[1],
xAxisPoint: api.coord([api.value(0), 0])
},
style: {
fill: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: '#397b92'
},
{
offset: 1,
color: '#55b6ce'
}
])
}
}]
}
},
data: [2012, 1230, 3790, 2349, 1654]
}]
}
复制代码
这个实现明显复杂很多,相当于所有位置都是我们自己去定义。
可以看到我们这里是用了 type: ‘group’ ,这个 type 是有多种选择的。
group:group 是唯一的可以有子节点的容器。group 可以用来整体定位一组图形元素。
path:可使用 SVG PathData 做路径。 可以用来画图标,或者其他各种图形,因为可以很便捷得缩放以适应给定尺寸。
image:图形。
text:文本块。
rect:矩形。
circle:圆。
ring:圆环。
sector:扇形。
arc:圆弧。
polygon:多边形。
polyline:折线。
line:直线。
bezierCurve:二次或三次贝塞尔曲线。
我们可以用一个最简单的自定义图表来看一下这个 custom 实现:
// 单独一个矩形
{
type: 'rect',
shape: {
x: x, y: y, width: width, height: height
},
style: api.style()
}
复制代码
可以看出结构还是比较简单的,类型,形状,样式这个三个配置就可以实现一个自定义图表。
// 一组图形元素
{
type: 'group',
// 如果 diffChildrenByName 设为 true,则会使用 child.name 进行 diff,
// 从而能有更好的过度动画,但是降低性能。缺省为 false。
// diffChildrenByName: true,
children: [{
type: 'circle',
shape: {
cx: cx, cy: cy, r: r
},
style: api.style()
}, {
type: 'line',
shape: {
x1: x1, y1: y1, x2: x2, y2: y2
},
style: api.style()
}]
}
复制代码
进而可以用多个简单的自定义图表来形成一组元素。
这个整体结构我们明白了,接下来就要看下用到 graphic 方法都是做什么的。
graphic:图形相关帮助方法。
官方 graphic 下的五种具体方法。
extendShape:创建一个新的 shape class。
registerShape:注册一个开发者定义的 shape class。
getShapeClass:得到一个 注册 好的 class。
clipPointsByRect:输入一组点,和一个矩形,返回被矩形截取过的点。
clipRectByRect:输入两个矩形,返回第二个矩形截取第一个矩形的结果。
我们这里就用到了 extendShape 和 registerShape,一个是去创建我们想要的图形,一个是引入我们创建的图形。
可以看到这个跟我们想要的 UI 就已经差不多了,接着去改样式就行了。
本篇文章到此结束,希望有帮助到看这篇文章的小伙伴。
浙江大华技术股份有限公司-软研-智慧城市产品研发部招聘高级前端!!!!! 欢迎大家来聊,有意向可发送简历到 chen_zhen@dahuatech.com,加入我们,可以一起进步,一起聚餐,一起旅游,让我们从世界村的小伙伴变成大华村的小伙伴。