python 动态仪表盘_使用Echarts3实现渐变仪表盘需求

Echarts 仪表盘实践

项目过程中遇到一个这样的需求:

bVXBAU?w=249&h=153

这明显是一个仪表盘类型的图表,打开echarts的官方文档,可以看到有一个默认的实现,如下:

bVXBAZ?w=337&h=262

使用了默认的参数

option = {

tooltip : {

formatter: "{a}
{b} : {c}%"

},

toolbox: {

feature: {

restore: {},

saveAsImage: {}

}

},

series: [

{

name: '业务指标',

type: 'gauge',

detail: {formatter:'{value}%'},

data: [{value: 50, name: '完成率'}]

}

]

};

分析需求后,我们从以下几个方面入手

轴线类别

从第一张图我们可以看出,需求中的轴线不是连续的,而是被分割成了一个个的长条形状。

从官方示例来看,轴线被白色的刻度分成了很多小段,如果刻度的宽度变大,刻度变密集的话是可以达到我们想要的效果的

option = {

...

series: [

{

name: '业务指标',

type: 'gauge',

// 去掉多余的分段

splitNumber: 1,

axisLine: {

lineStyle: {

width: 20

}

},

splitLine: {

show: false

},

axisTick: {

// 刻度长度与轴线宽度一致,达到分隔的效果

length: 20,

// 增加刻度密度

splitNumber: 100,

lineStyle: {

// 增加刻度宽度

width: 3

}

},

detail: {formatter:'{value}%'},

data: [{value: 50, name: '完成率'}]

}

]

};

经过这样修改的话,确实初步达到了我们要的效果。

bVXBA4?w=293&h=260

但是仔细看的话,会发现一个问题,指针的指向是空白处。原因就是空白的地方是刻度,而有颜色的地方是轴线。

这样的话最终指针指向的数据是不准确的,而且这个方案还有一个问题就是渐变颜色的处理。

[[0.2, '#91c7ae'], [0.8, '#63869e'], [1, '#c23531']]

官方提供的接口是分段颜色,想要做成渐变还不是很好处理。

接下来呢,考虑第二种实现方式

首先,轴线肯定是连续的,那我先把轴线隐藏掉,然后刻度加粗,拉长

option = {

...

series: [

{

name: '业务指标',

type: 'gauge',

splitNumber: 1,

axisLine: {

lineStyle: {

width: 20,

// 透明度设置为0

opacity: 0

}

},

splitLine: {

show: false

},

axisTick: {

length: 20,

splitNumber: 100,

lineStyle: {

width: 3,

// 给点颜色

color: '#555'

}

},

detail: {formatter:'{value}%'},

data: [{value: 50, name: '完成率'}]

}

]

};

bVXBA6?w=305&h=242

可以看到效果有了,而且指针位置正确。

渐变颜色

需求中轴线的颜色是渐变的,但是文档中给定的接口是分段式的颜色,没有办法使用,再者轴线透明度已经被设置为0了。

所以只能从刻度的颜色入手。

官方文档中,刻度的颜色是如下这样的:

// 线性渐变,前四个参数分别是 x0, y0, x2, y2, 范围从 0 - 1,相当于在图形包围盒中的百分比,如果 globalCoord 为 `true`,则该四个值是绝对的像素位置

color: {

type: 'linear',

x: 0,

y: 0,

x2: 0,

y2: 1,

colorStops: [{

offset: 0, color: 'red' // 0% 处的颜色

}, {

offset: 1, color: 'blue' // 100% 处的颜色

}],

globalCoord: false // 缺省为 false

}

// 径向渐变,前三个参数分别是圆心 x, y 和半径,取值同线性渐变

color: {

type: 'radial',

x: 0.5,

y: 0.5,

r: 0.5,

colorStops: [{

offset: 0, color: 'red' // 0% 处的颜色

}, {

offset: 1, color: 'blue' // 100% 处的颜色

}],

globalCoord: false // 缺省为 false

}

// 纹理填充

color: {

image: imageDom, // 支持为 HTMLImageElement, HTMLCanvasElement,不支持路径字符串

repeat: 'repeat' // 是否平铺, 可以是 'repeat-x', 'repeat-y', 'no-repeat'

}

默认支持两种渐变,线性和径向渐变,从效果上看都不符合我们的要求:线性是直线方向的渐变,而径向渐变是由内而外的。即使可以勉强实现,效果肯定不好。

所以可以尝试一下使用图片纹理。

首先用PS画一个和画布一样大小的渐图案

bVXBBb?w=240&h=240

在配置中使用image选项

option = {

...

series:[{

...

axisTick: {

length: 20,

splitNumber: 100,

lineStyle: {

color: {

image: document.getElementById('linear-pic'),

repeat: 'no-repeat'

},

width: 3

}

}

}]

这样项目中的需求就可以完美解决了

bVXBBf?w=202&h=157

颜色分段

颜色渐变完成了,看一下效果的话,会发现有一个明显的问题。需求中指针指向的位置之前的刻度是有渐变颜色的,后面一段则都是灰色。

而我们现在仪表盘无论指向哪里,刻度都是有颜色的。

在解决这个问题的过程中,想了很多方案,使用遮罩、修改渐变图片等等,都不能很好的解决问题。最后突然想起来一个配置项中可以使用多个仪表盘的,

我只要在数据前半段使用带渐变色的仪表盘,后半段全部用灰色的仪表盘补充,这样就可以解决问题。

这里还需要注意以下两点:

由于仪表盘的值是动态的,所以每个仪表盘的开始结束位置、刻度的个数都要根据值来计算

由于有两个仪表盘,最好把内容部分全部都写在一个上,另外一个确保只有轴线部分,避免出现重叠等问题

代码如下:

calculateOption: function (params) {

var offsetAngle = -35;

var totalAngle = 250;

var split = 75;

var series = [];

var asisWidth = 11;

var fontSize = 30;

// Defaults

params = $.extend({

min: 0,

max: 100,

value: 0,

name: 'DOWNLOAD SPEED',

type: 'gauge',

data: [{

value: 0,

name: ''

}]

}, params);

var startAngle = totalAngle + offsetAngle;

var endAngle = startAngle - Math.floor((parseInt(params.value, 10) / (params.max - params.min)) * totalAngle);

series.push({

name: params.name,

type: params.type,

startAngle: startAngle,

endAngle: endAngle,

splitNumber: 1,

// 轴线样式

axisLine: {

show: false,

lineStyle: {

width: asisWidth,

opacity: 0

}

},

// 分段样式

splitLine: { show: false },

// 刻度样式

axisTick: {

length: asisWidth,

splitNumber: Math.floor((params.value / (params.max - params.min)) * split),

lineStyle: {

color: {

image: $('#xx')[0],

repeat: 'no-repeat'

},

width: 2

}

},

axisLabel: { show: false },

pointer: { show: false },

// 指针样式

itemStyle: {},

title: {

fontSize: 8,

offsetCenter: [0, '-35%'],

color: '#999'

},

detail: {

color: '#36444b',

fontSize: fontSize,

offsetCenter: [0, '20%'],

formatter: function (val) {

return val.toFixed(2) + '\n{unit|Mbps}'

},

rich: {

unit: {

fontSize: 10,

color: '#999',

lineHeight: 30

}

}

},

data: [{

value: params.value,

name: params.name

}]

});

series.push({

name: '',

type: params.type,

startAngle: endAngle,

endAngle: offsetAngle,

splitNumber: 1,

axisLine: {

show: false,

lineStyle: {

width: asisWidth,

opacity: 0

}

},

splitLine: { show: false },

axisTick: {

length: asisWidth,

splitNumber: split - Math.floor((params.value / (params.max - params.min)) * 80),

lineStyle: {

color: '#999',

width: 2

}

},

axisLabel: { show: false },

pointer: { show: false },

// 指针样式

itemStyle: {},

title: { show: false },

detail: { show: false }

});

return series;

}

效果如下:

bVXBBi?w=202&h=165

指针类型

最后,我们需要做的就是把指针改为需求中的样子,本来我以为这个应该是最简单的部分,看完官方文档后发现并没有修改指针的接口。

{

color: 'auto',

borderColor: '#000',

borderWidth: 0,

borderType: 'solid',

shadowBlur: ...,

shadowColor: ...,

shadowOffsetX: 0,

shadowOffsetY: 0,

opacity: ...

}

如上,指针配置项应该是没有办法实现类似刻度的样子。

目前还在实验中,考虑使用markline画一条指针,是否可行还有待验证。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值