function shapeFn1(ctx, x, y, radius, diff, start, end, color, type) {
ctx.beginPath()
ctx.moveTo(x + radius * Math.cos((start * Math.PI) / 180), y + radius * Math.sin((start * Math.PI) / 180))
for (let i = start; end >= i; i += 1) {
ctx.lineTo(x + radius * Math.cos((i * Math.PI) / 180), y + radius * Math.sin((i * Math.PI) / 180))
}
if ('end' === type || 'all' === type) {
const x1 = x + (radius - diff / 2) * Math.cos((end * Math.PI) / 180)
const y1 = y + (radius - diff / 2) * Math.sin((end * Math.PI) / 180)
for (let i = end; end + 180 >= i; i += 1) {
ctx.lineTo(x1 + (diff / 2) * Math.cos((i * Math.PI) / 180), y1 + (diff / 2) * Math.sin((i * Math.PI) / 180))
}
} else {
ctx.lineTo(x + (radius - diff) * Math.cos((end * Math.PI) / 180), y + (radius - diff) * Math.sin((end * Math.PI) / 180))
}
for (let i = end; start <= i; i -= 1) {
ctx.lineTo(x + (radius - diff) * Math.cos((i * Math.PI) / 180), y + (radius - diff) * Math.sin((i * Math.PI) / 180))
}
if ('start' === type || 'all' === type) {
const x1 = x + (radius - diff / 2) * Math.cos((start * Math.PI) / 180)
const y1 = y + (radius - diff / 2) * Math.sin((start * Math.PI) / 180)
for (let i = start; start - 180 <= i; i -= 1) {
ctx.lineTo(x1 + (diff / 2) * Math.cos((i * Math.PI) / 180), y1 + (diff / 2) * Math.sin((i * Math.PI) / 180))
}
} else {
ctx.lineTo(x + radius * Math.cos((start * Math.PI) / 180), y + radius * Math.sin((start * Math.PI) / 180))
}
ctx.fillStyle = color
ctx.fill()
}
function shapeFn2(ctx, x, y, radius, value, rate, currentColor) {
const x1 = x + (radius - 10 * rate) * Math.cos(((135 + value * 2.7) * Math.PI) / 180)
const y1 = y + (radius - 10 * rate) * Math.sin(((135 + value * 2.7) * Math.PI) / 180)
ctx.beginPath()
ctx.arc(x1, y1, 10 * rate, 0, 360)
ctx.fillStyle = currentColor
ctx.strokeStyle = '#fff'
ctx.lineWidth = 4 * rate
ctx.fill()
ctx.stroke()
}
function shapeFn3(ctx, x, y, radius, start, end, color) {
ctx.beginPath()
ctx.moveTo(x + radius * Math.cos((start * Math.PI) / 180), y + radius * Math.sin((start * Math.PI) / 180))
for (let i = start; end >= i; i += 1) {
ctx.lineTo(x + radius * Math.cos((i * Math.PI) / 180), y + radius * Math.sin((i * Math.PI) / 180))
}
ctx.strokeStyle = color
ctx.lineWidth = 2
ctx.stroke()
let j = 0
for (let i = start; end >= i; i += (end - start) / 50) {
const line = 0 === j % 5 ? 20 : 10
ctx.beginPath()
ctx.moveTo(x + radius * Math.cos((i * Math.PI) / 180), y + radius * Math.sin((i * Math.PI) / 180))
ctx.lineTo(x + (radius - line) * Math.cos((i * Math.PI) / 180), y + (radius - line) * Math.sin((i * Math.PI) / 180))
ctx.strokeStyle = color
ctx.lineWidth = 2
ctx.stroke()
j += 1
}
}
function shapeText(ctx, x, y, value, radius, rate, currentColor) {
ctx.fillStyle = currentColor
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
ctx.font = `${32 * rate}px 微软雅黑`
ctx.fillText(`${value} %`, x, y)
ctx.fillStyle = '#fff'
ctx.textAlign = 'center'
ctx.textBaseline = 'middle'
ctx.font = `${18 * rate}px 微软雅黑`
ctx.fillText('内存使用率', x, y + radius * 0.6)
}
class DashBoard {
constructor(container) {
this.container = container
this.width = this.container.offsetWidth
this.height = this.container.offsetHeight
this.canvas = document.createElement('canvas')
this.canvas.setAttribute('width', this.width)
this.canvas.setAttribute('height', this.height)
this.container.appendChild(this.canvas)
}
setOption(value) {
this.value = value
if (!this.container || !this.canvas) return
this.draw()
}
resize() {
if (!this.container || !this.canvas) return
this.width = this.container.offsetWidth
this.height = this.container.offsetHeight
this.canvas.setAttribute('width', this.width)
this.canvas.setAttribute('height', this.height)
this.draw()
}
draw() {
const ctx = this.canvas.getContext('2d')
const x = this.width / 2
const y = this.height / 2
ctx.clearRect(0, 0, this.width, this.height)
const radius = x > y ? y : x
const colors = [
{
value: 0.6,
color: 'rgba(4, 255, 206, 0.2)',
activeColor: '#04FFCE',
},
{
value: 0.8,
color: 'rgba(252, 189, 106, 0.2)',
activeColor: '#FCBD6A',
},
{
value: 1,
color: 'rgba(227, 22, 86, 0.2)',
activeColor: '#E31656',
},
]
let currentColor = null
const rate = radius / 150
let start = 135
colors.forEach((item, index) => {
let type = ''
if (0 === index) {
type = 'start'
} else if (colors.length - 1 === index) {
type = 'end'
}
shapeFn1(ctx, x, y, radius - 15 * rate, 20 * rate, start, 135 + item.value * 270, item.color, type)
start = 135 + item.value * 270
if (!currentColor && this.value / 100 < item.value) {
currentColor = item.activeColor
}
})
shapeFn1(ctx, x, y, radius - 15 * rate, 20 * rate, 135, 135 + this.value * 2.7, currentColor, 'all')
shapeFn1(ctx, x, y, radius, 8 * rate, 135, 135 + this.value * 2.7, currentColor, 'all')
shapeFn2(ctx, x, y, radius - 15 * rate, this.value, rate, currentColor)
shapeFn3(ctx, x, y, radius - 40 * rate, 135, 405, '#999')
shapeText(ctx, x, y, this.value, radius, rate, currentColor)
}
}
const a = new DashBoard(document.querySelector('#tutorial'))
a.setOption(36)
setInterval(() => {
a.setOption(Number((Math.random() * 100).toFixed(2)))
}, 1000)
window.onresize = function () {
a.resize()
}