純JS+Vue和canvas實(shí)現(xiàn)一個(gè)儀表盤方式
在使用canvas的時(shí)候發(fā)現(xiàn)數(shù)值變化,每次都要重新渲染,值都從0開始,這和我的需求沖突。
一、 純JS+Vue
1. 先繪制基本的圓環(huán)背景
利用border-color和border-radius將正方形變成基本的圓環(huán)。
<div class="circle">
<div class="Inner"></div>
</div>.circle {
position: relative;
border-radius: 50%;
border: 12px solid;
border-color: green green transparent green;
width: 480px;
height: 484px;
top: 4%;
left: 12%;
}
利用border-radius,就可將正方形變成圓形

2. 背景繪制完成,下面就是每個(gè)刻度
<div class="circle">
<div class="Inner"></div>
<div class="center"></div>
<div class="pointer"></div>
</div>.center{
width: 20px;
height: 20px;
background-color: grey;
border-radius: 50%;
position: absolute;
z-index: 35;
top: calc(50% - 5px);
left: calc(50% - 5px);
}
.pointer{
width: 190px;
height:10px;
background-color: red;
border-radius: 50%;
position: absolute;
z-index: 34;
top: calc(50% - -2px);
left: calc(50% - 6px);
transform-origin:5% 35%;
}
.number {
color: #fff;
display: block;
padding-top: 16px;
position: absolute;
left: -6px;
}一共100個(gè)值,每?jī)蓚€(gè)刻度就要有線,到10線的長(zhǎng)度會(huì)更長(zhǎng)一點(diǎn)。其實(shí)和畫鐘表一樣,0的位置是坐標(biāo)軸的225°,到100的位置,總共是180°+45°
mounted() {
let circle = document.getElementsByClassName('Inner')[0];
circle.style.setProperty('--width', Math.floor(227) + 'px');
for (let i = 0; i <= 50; i++) {
const ul = document.createElement('ul');
const li = document.createElement('li');
li.style.transform = `rotate(${225 + i * 2 * 2.7}deg)`;
if (i % 5 === 0) {
li.style.height = '15px';
li.innerHTML = `<span class = 'number'>${i*2}</span>`
}
circle?.appendChild(ul);
ul.appendChild(li);
}
}
3. 讓指針根據(jù)數(shù)據(jù)變動(dòng),和刻度一樣,每移動(dòng)一個(gè)點(diǎn)要更改相應(yīng)的刻度
<div class="circle">
<div class="Inner"></div>
<div class="center"></div>
<div class="pointer"></div>
<div class="num">{{dataValue}}%</div>
</div>
<script>
export default {
data() {
return {
dataValue: 50,
}
},
watch: {
dataValue: {
handler(newValue, oldVal) {
this.dataValue = newValue;
this.runGuage()
},
},
},
methods: {
runGuage() {
let pointer = document.getElementsByClassName("pointer")[0];
pointer.style.transform = `rotate(${137 + this.dataValue * 2.66}deg)`;
},
},
mounted() {
this.runGuage();
}
}
</script>
<style scoped>
.num{
position: absolute;
color: #fff;
font-size: 70px;
z-index: 32;
top: 54%;
left: 30%;
}
</style>
二、 Canvas
靜下心實(shí)現(xiàn)了canvas描繪的儀表盤,并且數(shù)據(jù)不會(huì)從0開始渲染。
1. 先來canvas的老三樣
<canvas id="progress" width="600" height="600"></canvas>
<script>
// 獲取canvas元素和上下文
var canvas = document.getElementById("progress");
var ctx = canvas.getContext("2d");
</script>2. 設(shè)置一些基本參數(shù)
<canvas id="progress" width="600" height="600"></canvas>
<script>
// 獲取canvas元素和上下文
var canvas = document.getElementById("progress");
var ctx = canvas.getContext("2d");
// 圓環(huán)參數(shù)
var x = canvas.width / 2;
var y = canvas.height / 2;
var radius = 176;
var lineWidth = 10;
var startAngle = (3 * Math.PI) / 4; //相當(dāng)于從鐘表中的差不多7點(diǎn)開始
var endAngle = -Math.PI / 4; //相當(dāng)于從鐘表中的差不多5點(diǎn)結(jié)束
</script>3. 繪制圓環(huán)及外面的進(jìn)度條
// 繪制圓環(huán)進(jìn)度條函數(shù)
function drawProgress(progress) {
// 清除畫布
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 繪制背景圓環(huán)
ctx.beginPath();
ctx.arc(x, y, radius, startAngle, Math.PI / 4);
ctx.lineWidth = lineWidth;
ctx.strokeStyle = "#008000";
ctx.stroke();
// 繪制進(jìn)度圓環(huán)
endAngle = startAngle + ((3 * Math.PI / 2) * progress);
ctx.beginPath();
ctx.arc(x, y, radius, startAngle, endAngle);
ctx.lineWidth = lineWidth;
ctx.strokeStyle = "#ff0000";
ctx.stroke();
}
drawProgress(0.2)
4. 繪制里面的刻度條
function drawTicks() {
var numTicks = 50; // 刻度數(shù)量
var tickLength = 8; // 刻度長(zhǎng)度
var tickColor = "#000000"; // 刻度顏色
var tickWidth = 2; // 刻度寬度
let startAngle = (3 * Math.PI) / 4;
let endAngle = -(1.48 * Math.PI) / 2;
var angleStep = -((endAngle - startAngle) / numTicks); // 每個(gè)刻度之間的角度差
ctx.save();
// 將原點(diǎn)移到圓心處
ctx.translate(x, y);
// 繪制刻度
for (var i = 0; i <= numTicks; i++) {
var angle = startAngle + (i * angleStep) + 0.01;
if (i % 5 == 0) {
tickWidth = 5;
} else {
tickWidth = 2;
}
ctx.beginPath();
ctx.lineWidth = tickWidth;
ctx.strokeStyle = tickColor;
// 計(jì)算刻度起點(diǎn)和終點(diǎn)的坐標(biāo)
var startX = (radius - tickLength - 4) * Math.cos(angle);
var startY = (radius - tickLength - 4) * Math.sin(angle);
var endX = (radius - 4) * Math.cos(angle);
var endY = (radius - 4) * Math.sin(angle);
// 繪制刻度線段
ctx.moveTo(startX, startY);
ctx.lineTo(endX, endY);
ctx.stroke();
// 繪制時(shí)間文本
var text = i % 5 == 0 ? (i * 2).toString() : '';
var textX = (radius - tickLength - 20) * Math.cos(angle);
var textY = (radius - tickLength - 20) * Math.sin(angle);
ctx.font = "16px Arial";
ctx.fillStyle = "#000000";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(text, textX, textY);
}
ctx.restore(); // 恢復(fù)之前的繪圖狀態(tài)
}
5. 繪制指針
這一段可以抽離出來一個(gè)方法,等有時(shí)間再改一下
let kedu = (((2.4) * 2) / 100); //我的起始角度0的位置旋轉(zhuǎn)角度是從-2.4到2.4
let rotate1 = (2.4 - (kedu * progress * 100));
if (progress < 0.5) {
rotate1 = -rotate1;
} else {
rotate1 = -rotate1;
}
ctx.save();
ctx.translate(x, y);
ctx.rotate(rotate1);
ctx.beginPath();
ctx.moveTo(x - (2 * radius) + 50, y - (2 * radius) + 60);
ctx.lineTo(x - (2 * radius) + 40, y - (2 * radius) + 46);
ctx.lineTo(x - (2 * radius) + 50, y - (2 * radius) - 70);
ctx.lineTo(x - (2 * radius) + 60, y - (2 * radius) + 46);
ctx.fillStyle = "#ff0000";
ctx.fill();
ctx.restore();
6. 繪制文本顯示當(dāng)前的值
function drawText(value){
ctx.font = "40px Arial";
ctx.fillStyle = "#000000";
ctx.fillText((value*100).toFixed(2)+'%', x-60, y+42);
}
完成~
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue如何通過router-link或者button跳轉(zhuǎn)到一個(gè)新的頁面
這篇文章主要介紹了vue如何通過router-link或者button跳轉(zhuǎn)到一個(gè)新的頁面,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10
Vue3中使用i18n,this.$t報(bào)錯(cuò)問題及解決
這篇文章主要介紹了Vue3中使用i18n,this.$t報(bào)錯(cuò)問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04
vue單個(gè)元素綁定多個(gè)事件問題(例如點(diǎn)擊綁定多個(gè)事件方法)
這篇文章主要介紹了vue單個(gè)元素綁定多個(gè)事件問題(例如點(diǎn)擊綁定多個(gè)事件方法),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04
Vue獲取子組件實(shí)例對(duì)象ref屬性的方法推薦
在Vue中我們可以使用ref屬性來獲取子組件的實(shí)例對(duì)象,這個(gè)功能非常方便,這篇文章主要給大家介紹了關(guān)于Vue獲取子組件實(shí)例對(duì)象ref屬性的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-06-06
vue實(shí)現(xiàn)用v-bind給src和href賦值
這篇文章主要介紹了vue實(shí)現(xiàn)用v-bind給src和href賦值,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04
vue如何使用element-ui 實(shí)現(xiàn)自定義分頁
這篇文章主要介紹了vue如何使用element-ui 實(shí)現(xiàn)自定義分頁,可以通過插槽實(shí)現(xiàn)自定義的分頁,本文通過實(shí)例圖文相結(jié)合給大家介紹的非常詳細(xì),感興趣的朋友一起看看吧2024-07-07
element-plus/element-ui走馬燈配置圖片及圖片自適應(yīng)的最簡(jiǎn)便方法
走馬燈功能在展示圖片時(shí)經(jīng)常用到,下面這篇文章主要給大家介紹了關(guān)于element-plus/element-ui走馬燈配置圖片及圖片自適應(yīng)的最簡(jiǎn)便方法,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2023-03-03
關(guān)于Vue不能監(jiān)聽(watch)數(shù)組變化的解決方法
本文主要介紹了Vue不能監(jiān)聽(watch)數(shù)組變化的解決方法,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09

