故事發生在幾天前
公司要求做個儀表盤,大致UI是這樣的
這不是爲難我胖虎嘛,於是找遍整個全網也沒找到相似的,只能自己手寫一個。
然而,最開始是準備用極座標寫的
折騰了一上午發現極座標做出的效果兩頭是360度的圓環,這使UI給的標註無法實現,於是我又開始研究儀表盤,官方給的實例倒是挺炫酷
當我感覺快找到希望時,卻無法實現兩端圓角
以及將刻度顯示在數字外,在網上找資料發現也有同學遇到相同的問題,但是沒找到解決方法
然而急中生智卻被我想到了一個方法,將這二者合併一下
先簡單畫個儀表盤
設置一下他的屬性,去掉指針,去掉錶盤顏色,得到只有刻度和數字的錶盤
之後將除了圓環以外的所有屬性配置一下實現這樣的效果
突然有內味了,這時我們加上極座標環狀圖
然而二者最大角度不同,我們需要做一個換算,設計圖中儀表盤的角度相當於極座標的-30度到210度,二者偏移值是240度除360度
也就是極座標得乘以2分之3(240分之360)纔是真實儀表盤的值
經過換算後,實現以下效果
源碼:https://gitee.com/DieHunter/myCode/tree/master/Echart/PolarGauge
同樣需要引入Echarts
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
.PolarGauge {
margin: 100px auto;
background: #000;
width: 400px;
height: 400px;
}
</style>
<script src="./echarts.js"></script>
<script src="./chart.js"></script>
</head>
<body>
<div id="PolarGauge" class="PolarGauge"></div>
</body>
</html>
chart.js
var chart, option, data, timeTickId, timer, max;
window.onload = function init() {
chart = echarts.init(PolarGauge); //初始化chart容器
data = { //顯示的數據
"name": '館藏量',
"num": 1000
}
timer = 1.5 //刷新頻率
max = 1000 //最大館藏量
createPolarGauge() //配置chart
}
function createPolarGauge() {
option = {
angleAxis: {
show: false,
max: max * 3 / 2, //這裏將極座標最大值轉換成儀表盤的最大值,(360度除以240度)
type: 'value',
startAngle: 210, //極座標初始角度,從第一象限算起,大約在7-8點鐘角度之間
splitLine: {
show: false //隱藏座標
}
},
barMaxWidth: 18, //圓環寬度
radiusAxis: { //隱藏座標
show: false,
type: 'category',
},
polar: { //設置圓環位置和大小
center: ['50%', '50%'],
radius: '296'
},
series: [{
type: 'bar',
data: [{ //上層圓環,用於顯示真實數據
value: data.num,
itemStyle: {
color: { //圖形漸變顏色方法,四個數字分別代表,右,下,左,上,offset表示0%到100%
type: 'linear',
x: 0,
y: 0,
x2: 1, //從左到右 0-1
y2: 0,
colorStops: [{
offset: 0,
color: '#CD48AE' // 0% 處的顏色
}, {
offset: 1,
color: '#2CABFC' // 100% 處的顏色
}],
globalCoord: false // 缺省爲 false
},
shadowColor: 'rgba(255, 255, 255, 0.2)', //加白色陰影產生高亮效果
shadowBlur: 10
}
}],
barGap: '-100%', //柱間距離,用來將上下兩層圓環重合
coordinateSystem: 'polar', //類型,極座標
roundCap: true, //頂端圓角
z: 2 //圓環層級,和zindex相似
}, { //下層圓環,用於顯示最大值
type: 'bar',
data: [{
value: max,
itemStyle: {
color: '#265195',
shadowColor: 'rgba(0, 0, 0, 0.2)', //加白色陰影產生高亮效果
shadowBlur: 5,
shadowOffsetY: 2
}
}],
barGap: '-100%', //柱間距離,用來將上下兩層圓環重合
coordinateSystem: 'polar', //類型,極座標
roundCap: true, //頂端圓角
z: 1 //圓環層級,和zindex相似
},
{ //儀表盤
type: 'gauge',
radius: '95%',
startAngle: 210, //起始角度,同極座標
endAngle: -30, //終止角度,同極座標
max: max,
splitNumber: 5, //分割線個數(除原點外)
axisLine: { // 座標軸線
show: false
},
pointer: {
show: false
},
axisLabel: {
// 座標軸數字
textStyle: {
fontSize: 8,
color: "#13B5FC"
},
},
axisTick: { // 座標軸標記
length: 10,
lineStyle: {
color: "#13B5FC"
}
},
splitLine: { // 分隔線
length: 5,
lineStyle: {
width: 1,
}
},
title: { //標題,顯示'館藏量'
textStyle: {
color: '#fff',
shadowColor: '#fff',
fontSize: 30
},
offsetCenter: ["0", '-35%'] //位置偏移
},
detail: { //儀表盤數值
formatter: function (params) {
var name = data.num.toString()
var list = ''
for (var i = 0; i < name.length; i++) {
list += '{value|' + name[i] + '}' //每個數字用border隔開
if (i !== name.length - 1) {
list += '{margin|}' //添加margin值
}
}
return [list]
},
offsetCenter: ["0", '5%'],
rich: { //編輯富文本樣式
value: {
width: 34,
height: 42,
borderColor: '#02A0F0',
borderWidth: 2,
borderRadius: 5,
lineHeight: 1000,
fontSize: 36,
padding: [0, 0, 4, 0],
color: '#fff',
shadowColor: 'rgb(2,157,239)',
shadowBlur: 5
},
margin: {
width: 8,
height: 42,
}
}
},
data: [{
value: data.num,
name: data.name
}]
}
]
}
timeTick()
}
function setOption() { //更新數據
data.num = parseInt(Math.random() * max)
option.series[2].data[0].value = data.num
option.series[0].data[0].value = data.num
chart.setOption(option)
}
function timeTick() { //定時器,最好用延時加遞歸,如果用setInterval,容易造成堵塞
if (timeTickId) {
clearTimeout(timeTickId)
timeTickId = 0
}
setOption()
timeTickId = setTimeout(timeTick, 1000 * timer || 5000)
}
總結:編程即生活,有時候不能死磕到底,換個角度也許會更好