項目過程當中遇到一個這樣的需求: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
畫一條指針,是否可行還有待驗證。