canvas美化仪表盘

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

}


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。