项目过程当中遇到一个这样的需求:javascript
这明显是一个仪表盘类型的图表,打开echarts的官方文档,能够看到有一个默认的实现,以下:java
使用了默认的参数echarts
option = { tooltip : { formatter: "{a} <br/>{b} : {c}%" }, toolbox: { feature: { restore: {}, saveAsImage: {} } }, series: [ { name: '业务指标', type: 'gauge', detail: {formatter:'{value}%'}, data: [{value: 50, name: '完成率'}] } ] };
分析需求后,咱们从如下几个方面入手spa
从第一张图咱们能够看出,需求中的轴线不是连续的,而是被分割成了一个个的长条形状。3d
从官方示例来看,轴线被白色的刻度分红了不少小段,若是刻度的宽度变大,刻度变密集的话是能够达到咱们想要的效果的指针
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: '完成率'}] } ] };
通过这样修改的话,确实初步达到了咱们要的效果。rest
可是仔细看的话,会发现一个问题,指针的指向是空白处。缘由就是空白的地方是刻度,而有颜色的地方是轴线。
这样的话最终指针指向的数据是不许确的,并且这个方案还有一个问题就是渐变颜色的处理。code
[[0.2, '#91c7ae'], [0.8, '#63869e'], [1, '#c23531']]
官方提供的接口是分段颜色,想要作成渐变还不是很好处理。orm
接下来呢,考虑第二种实现方式blog
首先,轴线确定是连续的,那我先把轴线隐藏掉,而后刻度加粗,拉长
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: '完成率'}] } ] };
能够看到效果有了,并且指针位置正确。
需求中轴线的颜色是渐变的,可是文档中给定的接口是分段式的颜色,没有办法使用,再者轴线透明度已经被设置为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画一个和画布同样大小的渐图案
在配置中使用image选项
option = { ... series:[{ ... axisTick: { length: 20, splitNumber: 100, lineStyle: { color: { image: document.getElementById('linear-pic'), repeat: 'no-repeat' }, width: 3 } } }]
这样项目中的需求就能够完美解决了
颜色渐变完成了,看一下效果的话,会发现有一个明显的问题。需求中指针指向的位置以前的刻度是有渐变颜色的,后面一段则都是灰色。
而咱们如今仪表盘不管指向哪里,刻度都是有颜色的。
在解决这个问题的过程当中,想了不少方案,使用遮罩、修改渐变图片等等,都不能很好的解决问题。最后忽然想起来一个配置项中可使用多个仪表盘的,
我只要在数据前半段使用带渐变色的仪表盘,后半段所有用灰色的仪表盘补充,这样就能够解决问题。
这里还须要注意如下两点:
代码以下:
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; }
效果以下:
最后,咱们须要作的就是把指针改成需求中的样子,原本我觉得这个应该是最简单的部分,看完官方文档后发现并无修改指针的接口。
{ color: 'auto', borderColor: '#000', borderWidth: 0, borderType: 'solid', shadowBlur: ..., shadowColor: ..., shadowOffsetX: 0, shadowOffsetY: 0, opacity: ... }
如上,指针配置项应该是没有办法实现相似刻度的样子。
目前还在实验中,考虑使用markline
画一条指针,是否可行还有待验证。