canvas 畫進度條

amoslb發表於2020-12-01

template>

<div class="circle-wrapper">

<canvas id="canvas"></canvas>

</div>

</template>

<script>

export default {

mounted() {

this.percent = this.options.percent;

this.radius = this.options.radius;

this.width = this.options.width;

this.height = this.options.height;

this.externalHeight = parseInt(this.width / 9) || 0;

this.initCircle();

},

data() {

return {

pointColor: "rgba(255,144,55,1)", // 中心紅點

percent: 0,

radius: 0,

width: 0,

height: 0,

externalHeight: 0,

};

},

props: {

options: {

type: Object,

default: {

percent: 0,

radius: 0,

width: 0,

height: 0,

},

},

startGradient: {

type: Boolean,

default: false,

}, // 開啟漸變進度條

hasProgress: {

type: Boolean,

default: true,

}, // 開啟進度條

traceColor: {

type: String,

default: "rgba(255,255,255,0.1)",

}, // 外部整個無軌道的顏色

coverColor1: {

type: String,

default: "rgba(255,255,255,0.5)",

}, //軌道漸變的顏色1

coverColor2: {

type: String,

default: "rgba(255,255,255,0.5)",

},

coverColor3: {

type: String,

default: "rgba(255,255,255,1)",

},

stopBgCircle: {

type: String,

default: "rgba(255,255,255)",

},

hasProgress: {

type: Boolean,

default: true,

}, // 開啟進度條

hasPoint: {

type: Boolean,

default: true,

}, // 是否有中心小紅點

hasCircle: {

type: Boolean,

default: true,

},

hasOutCircle: {

type: Boolean,

default: true,

}, //是否有外部圓

hasGradientCircle: {

type: Boolean,

default: true,

}, //是否有軌道漸變圓

runtime: "", //軌跡運動總時間

},

methods: {

draw(percent, sR0) {

if (this.percent < 0 || this.percent > 100) {

return;

}

if (sR0 < Math.PI / 2 || sR0 >= (3 / 2) * Math.PI) {

return;

}

let canvas = document.getElementById("canvas");

let cxt = canvas.getContext("2d");

canvas.style.width = this.width + "px";

//解決canvas 鋸齒問題

let dpr = window.devicePixelRatio || window.webkitDevicePixelRatio || window.mozDevicePixelRatio || 1;

// 漸變進度條顏色

canvas.width = this.width * dpr;

canvas.height = (this.height + this.externalHeight) * dpr;

//

cxt.scale(dpr, dpr);

let gradient = cxt.createLinearGradient(0, 0, 170, 0);

gradient.addColorStop(0, this.coverColor1);

gradient.addColorStop(0.3, this.coverColor2);

gradient.addColorStop(1, this.coverColor3);

let cW = this.width,

cH = this.height * 2,

PI = Math.PI,

sR = sR0 || (1 / 2) * PI;

let finalRadian = sR + ((PI + (PI - sR) * 2) * this.percent) / 100;

let stepBase = 50;

if (this.percent < 10) {

stepBase = 1000;

} else if (this.percent >= 10 && this.percent < 20) {

stepBase = 500;

}

let step = (PI + (PI - sR) * 2) / stepBase; // 走的步驟

let text = 0;

let that = this;

let birthday = new Date();

let timer = setInterval(function () {

cxt.clearRect(0, 0, cW, cH);

let endRadian = sR + text * step;

// 軌道trace

that.drawCanvas(cW / 2, cH / 2, that.radius, sR, sR + (PI + (PI - sR) * 2), that.traceColor, 9);

if (that.percent) {

// 進度條 progess

if (that.hasProgress) {

that.drawCanvas(cW / 2, cH / 2, that.radius, sR, endRadian, gradient, 9);

}

let angle = 2 * PI - endRadian,

xPos = Math.cos(angle) * that.radius + cW / 2,

yPos = -Math.sin(angle) * that.radius + cH / 2;

 

if (that.hasCircle) {

// 外部小白圓

that.drawCanvas(xPos, yPos, 3, 0, 2 * PI, that.stopBgCircle, 0);

}

if (that.hasPoint) {

// 中心紅點

that.drawCanvas(xPos, yPos, 1, 0, 2 * PI, that.pointColor, 1, "fill");

}

if (that.hasOutCircle) {

// 最外部圓

that.drawCanvas(xPos, yPos, 9, 0, 2 * PI, that.coverColor2, 9);

}

// 圓形漸變

if (that.hasGradientCircle) {

let radialGrad = cxt.createRadialGradient(300, 300, 0, 300, 300, 500);

radialGrad.addColorStop(0, "rgba(255,255,255,0.3)");

radialGrad.addColorStop(0.3, "rgba(255,227,72,0.2)");

radialGrad.addColorStop(1, "rgba(255,227,72,0.1)");

// 最外部黃色

that.drawCanvas(xPos, yPos, 14, 0, 2 * PI, radialGrad, 13);

}

} else {

clearInterval(timer);

}

if (endRadian.toFixed(2) >= finalRadian.toFixed(2)) {

clearInterval(timer);

}

text = text + 1;

}, 20);

},

drawCanvas(x, y, r, sRadian, eRadian, color, lineWidth, circleType) {

let cxt = canvas.getContext("2d");

cxt.beginPath();

if (circleType == "fill") {

cxt.fillStyle = color;

cxt.arc(x, y, r, sRadian, eRadian);

cxt.fill();

} else {

cxt.lineCap = "round";

cxt.strokeStyle = color;

cxt.lineWidth = lineWidth;

cxt.arc(x, y, r, sRadian, eRadian);

cxt.stroke();

}

},

initCircle() {

this.draw(this.percent, Math.PI); // 半圓PI 全圓 (1 / 2) * PI

},

},

};

</script>

<style lang="scss">

.circle-wrapper {

width: 100%;

canvas {

position: absolute;

left: 50%;

top: 0;

transform: translate(-50%, 0);

}

}

</style>

 

相關文章