移动端,cavans和svg绘制进度图
先看效果:
起初是用cavans绘制的 结果会模糊,倍数绘制再缩小也是模糊,最后换成了svg绘制:
cavans:
global.progressChart = {
template: `
<div class="process-chart-box">
<canvas id="progressChart">当前浏览器不支持canvas</canvas>
<img src="xxx/progress_icon.png" class="progress-icon" v-if="per>0" />
</div>
`,
data() {
return {
isDark: false
}
},
props: ['per'],
methods: {
handleCanvas() {
const isDark = this.isDark
const percent = Math.round(this.per) / 100
let rem =
(document.body.offsetWidth / 750) * 100 < 60
? (document.body.offsetWidth / 750) * 100
: 60
let labelW = Math.round(0.32 * rem)
const box = document.querySelector('.process-chart-box')
if (!box) return
const w = box.offsetWidth
const ctx = document.getElementById('progressChart').getContext('2d')
ctx.canvas.width = w + 1
ctx.canvas.height = w + 1
//外圆环
ctx.beginPath()
ctx.arc(w / 2, w / 2, w / 2, 0, 2 * Math.PI)
//strokeStyle边框 fillStyle填充
ctx.strokeStyle = isDark ? '#262626' : '#fff'
ctx.fillStyle = isDark ? '#283851' : '#d6e6ff'
ctx.fill()
ctx.stroke()
//内圆环
ctx.beginPath()
ctx.arc(w / 2, w / 2, w / 2 - labelW, 0, 2 * Math.PI)
ctx.strokeStyle = isDark ? '#262626' : '#fff'
ctx.fillStyle = isDark ? '#262626' : '#fff'
ctx.fill()
ctx.stroke()
//环形图的进度条
if (percent > 0) {
ctx.beginPath()
ctx.arc(
w / 2,
w / 2,
(w - labelW) / 2,
-Math.PI / 2,
-Math.PI / 2 + percent * (Math.PI * 2),
false
)
ctx.lineWidth = labelW
ctx.lineCap = 'round'
ctx.strokeStyle = isDark ? '#2f71de' : '#3480ff'
ctx.stroke()
}
}
},
mounted() {
this.$nextTick(() => {
this.getDisplayMode()
.then(res => {
this.isDark = !!res
this.handleCanvas()
})
.catch(() => {
this.handleCanvas()
})
window.addEventListener(
'resize',
() => {
this.handleCanvas()
},
false
)
})
},
watch: {
per() {
this.handleCanvas()
}
}
}
svg:
global.progressChart = {
template: `
<div class="process-chart-box">
<svg :width="w" :height="w" version="1.1" xmlns="http://www.w3.org/2000/svg">
<circle class="progress-bg" :cx="w/2" :cy="w/2" :r="r" :stroke="isDark ? '#283851' : '#d6e6ff'" :stroke-width="progressW" fill="none"/>
<circle :style="+per>0?'':'display:none'" class="progress" :transform="rotate" :cx="w/2" :cy="w/2" :r="r" :stroke="isDark ? '#2f71de' : '#3480ff'" :stroke-width="progressW" fill="none" stroke-linecap="round" />
</svg>
<img src="xxx/progress_icon.png" class="progress-icon" v-if="per>0" />
</div>
`,
data() {
return {
isDark: false
}
},
props: ['per'],
computed: {
remToPx() {
let rem =
(document.body.offsetWidth / 750) * 100 < 60 ?
(document.body.offsetWidth / 750) * 100 :
60
console.log('remToPx', rem);
return rem
},
// 容器宽度
w() {
return 2.2 * this.remToPx
},
// 进度宽度
progressW() {
return 0.28 * this.remToPx
},
// 绘制半径
r() {
return (this.w - this.progressW) / 2
},
// 进度旋转
rotate() {
return `rotate(-90,${this.w/2},${this.w/2})`
}
},
methods: {
handleSvg() {
//换成svg绘制
var progressDom = document.querySelector(".progress");
if (!progressDom) {
return
}
let persent = this.per
if (persent > 0) {
var circleLength = Math.floor(2 * Math.PI * parseFloat(progressDom.getAttribute("r")));
var value = persent * circleLength / 100;
progressDom.setAttribute("stroke-dasharray", value + ",10000");
}
},
},
mounted() {
this.$nextTick(() => {
this.getDisplayMode()
.then(res => {
this.isDark = !!res
this.handleSvg()
})
.catch(() => {
this.handleSvg()
})
})
},
watch: {
per() {
this.handleSvg()
}
}
}