今天分享给大家的是玉珏(jue)图,本周做技术预言,看到设计里有个好看又奇怪的图,然后echart、heightChart找了一遍,并没有找到demo,百度查了一圈,还是没找到一样demo,所以决定自己写个demo。
首先看下设计图
首先看到的是四分之三圆。然后在四分之三圆中有个类似进度条的圆弧。只能用canvas画了,连查带写,花费了多半天的时间终于写出来了,今天把它记录下来,给自己记录的同时希望也能帮助到需要的人,下面直接上代码,因为是在vue中写的,所以把按着vue的风格来展示代码:
circle.vue文件
<template>
<div class="canvas-wrapper">
<canvas class="canvas" :id="id" :width="width" :height="height" style="width:100%;height:100%;"></canvas>
</div>
</template>
<script>
export default {
name: 'canvasCircle',
data () {
return {}
},
/*
params对象
@id: 画布id
@width: 画布宽
@height: 画布高
@percente: 圆环百分比, 范围[0, 100]
@radius: 半径
@lineWidth: 环宽
@innerColor: 内圈范围值颜色
@outerColor: 外圈范围值颜色
@text: 显示文字
@textColor: 文字颜色
*/
props: {
params: {
type: Object,
required: true
},
id: {
type: String,
required: true
},
width: {
type: Number,
default: 200
},
height: {
type: Number,
default: 200
}
},
mounted () {
this.initDraw()
},
methods: {
// 初始化数据
initDraw () {
this.canvas = document.getElementById(this.params.id)
this.context = this.canvas.getContext('2d')
this.centerX = this.canvas.width / 4
this.centerY = this.canvas.width / 2
this.percente = this.params.percente
this.innerColor = this.params.innerColor
this.outerColor = this.params.outerColor
this.width = this.params.width
this.height = this.params.height
this.radius = this.params.radius
this.lineWidth = this.params.lineWidth
this.text = this.params.text
this.textColor = this.params.textColor
this.speed = 0
window.requestAnimationFrame(this.drawMain)
},
// 开始绘制
drawMain () {
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height)
this.backgroundCircle()
this.drawPoint()
this.drawText()
this.foregroundCircle(this.speed)
if (this.speed < this.percente) {
this.speed += 1
window.requestAnimationFrame(this.drawMain)
}
},
// 绘制背景圆圈
backgroundCircle () {
this.context.save() // save和restore可以保证样式属性只运用于该段canvas元素
this.context.beginPath()
this.context.lineWidth = this.lineWidth // 设置线宽
this.context.lineCap = 'round' // 圆环末端类型 [可填] 默认:butt (平滑);round (圆形线帽)
this.context.strokeStyle = this.outerColor
this.context.arc(this.centerX, this.centerY, this.radius, 1.5 * Math.PI, 0 * Math.PI, true)
// 用于绘制圆弧this.context.arc(x坐标,y坐标,半径,起始角度,终止角度,顺时针/逆时针)
this.context.stroke()
this.context.closePath()
this.context.restore()
},
// 绘制进度圆环
foregroundCircle (n) {
this.context.save()
this.context.strokeStyle = this.innerColor
this.context.lineWidth = this.lineWidth
this.context.lineCap = 'round'
this.context.beginPath()
this.context.arc(this.centerX, this.centerY, this.radius, 1.5 * Math.PI, Math.PI * (1.5 - n * 1.5 / 100), true)
this.context.stroke()
this.context.closePath()
this.context.restore()
},
// 绘制文字前的点
drawPoint () {
this.context.save()
this.context.beginPath()
this.context.arc(this.centerX + 10, this.centerY - this.radius - this.lineWidth / 2 + this.lineWidth / 2, this.lineWidth / 2, Math.PI * 2, 0, false)
this.context.fillStyle = this.innerColor
this.context.fill()
this.context.closePath()
this.context.restore()
},
// 绘制文字
drawText () {
this.context.save()
this.context.fillStyle = this.textColor
let fontSize = 16
this.context.font = fontSize + 'px Helvetica'
// let textWidth = this.context.measureText(n + '%').width
this.context.fillText(this.text, this.centerX + 25, this.centerY - this.radius - this.lineWidth / 2 + fontSize / 2)
this.context.restore()
}
}
}
</script>
<style scoped>
.canvas-wrapper{
width: 100%;
height: 100%;
}
</style>
helloCanvas.vue
<template>
<div class="hello">
<div class="aaa">
<canvas-circle
:params="circle1"
:width="circle1.width"
:height="circle1.height"
:id="circle1.id"
></canvas-circle>
</div>
<div class="aaa">
<canvas-circle
:params="circle2"
:width="circle2.width"
:height="circle2.height"
:id="circle2.id"
></canvas-circle>
</div>
<div class="aaa">
<canvas-circle
:params="circle3"
:width="circle3.width"
:height="circle3.height"
:id="circle3.id"
></canvas-circle>
</div>
</div>
</template>
<script>
import canvasCircle from '../components/circle.vue'
export default {
name: 'Hello',
data () {
return {
circle1: {
id: 'circle1',
width: 400,
height: 400,
percente: 90,
radius: 30,
lineWidth: 5,
text: '山 西 业 务',
outerColor: 'rgba(32,68,95,1)',
innerColor: 'rgba(242,167,34,1)',
textColor: 'rgba(126,164,173,1)'
},
circle2: {
id: 'circle2',
width: 400,
height: 400,
percente: 60,
radius: 60,
lineWidth: 5,
text: '陕 西 业 务',
outerColor: 'rgba(32,68,95,1)',
innerColor: 'rgba(18,231,118,1)',
textColor: 'rgba(126,164,173,1)'
},
circle3: {
id: 'circle3',
width: 400,
height: 400,
percente: 80,
radius: 90,
lineWidth: 5,
text: '内 蒙 业 务',
outerColor: 'rgba(32,68,95,1)',
innerColor: 'rgba(0,232,250,1)',
textColor: 'rgba(126,164,173,1)'
}
}
},
components: {
canvasCircle
}
}
</script>
<style scoped>
.hello{
position: relative;
}
.aaa{
position: absolute;
top: 0;
left: 0;
width: 400px;
height: 400px;
}
</style>