純粋な JS+Vue とキャンバスを使用してダッシュボードを実装する

Canvas を使用すると、値が変更されるため、毎回再レンダリングする必要があり、値は 0 から始まり、ニーズと矛盾します。

1. 純粋な JS+Vue

1. まず基本的なリングの背景を描き、 と を使用してborder-color正方形border-radiusを基本的なリングに変換します。

<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.背景描画が完了し、各スケールが表示されます。

<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個あり、2目盛ごとに線が入り、10番目の線の長さが少し長くなります。実は時計を描くのと同じで、0の位置は座標軸の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. データに応じてポインタを変更する スケールと同様に、点を移動するたびに対応するスケールも変更する必要があります。

<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>

ここに画像の説明を挿入します

2. キャンバス

Canvasで描画したダッシュボードを冷静に実装したところ、データが0から描画されなくなりました。

1. キャンバスから始めましょう。

<canvas id="progress" width="600" height="600"></canvas>

<script>
	// 获取canvas元素和上下文
	var canvas = document.getElementById("progress");
	var ctx = canvas.getContext("2d");
</script>

2. いくつかの基本パラメータを設定します

<canvas id="progress" width="600" height="600"></canvas>

<script>
	// 获取canvas元素和上下文
	var canvas = document.getElementById("progress");
	var ctx = canvas.getContext("2d");

	// 圆环参数
	var x = canvas.width / 2;
	var y = canvas.height / 2;
	var radius = 176;
	var lineWidth = 10;
	var startAngle = (3 * Math.PI) / 4;  //相当于从钟表中的差不多7点开始
	var endAngle = -Math.PI / 4;         //相当于从钟表中的差不多5点结束
</script>

3. リングとプログレスバーを外側に描画します

// 绘制圆环进度条函数
function drawProgress(progress) {
    
    
	// 清除画布
	ctx.clearRect(0, 0, canvas.width, canvas.height);

	// 绘制背景圆环
	ctx.beginPath();
	ctx.arc(x, y, radius, startAngle, Math.PI / 4);
	ctx.lineWidth = lineWidth;
	ctx.strokeStyle = "#008000";
	ctx.stroke();

	// 绘制进度圆环
	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; // 刻度数量
	var tickLength = 8; // 刻度长度
	var tickColor = "#000000"; // 刻度颜色
	var tickWidth = 2; // 刻度宽度

	let startAngle = (3 * Math.PI) / 4;
	let endAngle = -(1.48 * Math.PI) / 2;

	var angleStep = -((endAngle - startAngle) / numTicks); // 每个刻度之间的角度差

	ctx.save(); 

	// 将原点移到圆心处
	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;

		// 计算刻度起点和终点的坐标
		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();

		// 绘制时间文本
		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(); // 恢复之前的绘图状态
}

ここに画像の説明を挿入します

5. ポインタを描画する

この段落からメソッドを抽出し、時間があるときに変更できます。

let kedu = (((2.4) * 2) / 100);  //我的起始角度0的位置旋转角度是从-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. テキストを描画して現在の値を表示します

function drawText(value){
    
    
	ctx.font = "40px Arial";
	ctx.fillStyle = "#000000";
	ctx.fillText((value*100).toFixed(2)+'%', x-60, y+42);
}

ここに画像の説明を挿入します
完了〜

おすすめ

転載: blog.csdn.net/2201_75499330/article/details/131983150