手写造轮子day01--vue3自定义渲染-实现canvas

 
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="app">
  </div>

  <script type="text/x-template" id="chart">
    <bar-chart :data="chartData"></bar-chart>
  </script>

  <script src="../dist/vue.global.js"></script>
  <script>

    const { createRenderer } = Vue

    const renderer = createRenderer(
      // 创建element
      {
      createElement(tag) {
        return { tag }
      },
      // 更新属性
      patchProp(el, key, prevValue, nextValue) {
        // el就是上面对象,key是data,nextValue就是数据数组
        el[key] = nextValue
      },
      // 插入操作
      insert(child, parent) {
        // 判断为元素就执行画画操作
        if (parent.nodeType === 1) {
          // parent是canvas
          draw(child)
        }
      }
    })

    // 画画的逻辑
    let canvas, ctx
    const draw = (el, noClear) => {
      // 清空画布
      if (!noClear) {
        ctx.clearRect(0, 0, canvas.width, canvas.height)
      }
      // 判断tag
      if (el.tag == 'bar-chart') {
        const { data } = el;
        const barWidth = canvas.width / 10,
          gap = 20,
          paddingLeft = (data.length * barWidth + (data.length - 1) * gap) / 2,
          paddingBottom = 10;
        // x轴
        // 柱状图
        data.forEach(({ title, count, color }, index) => {
          const x = paddingLeft + index * (barWidth + gap)
          const y = canvas.height - paddingBottom - count
          ctx.fillStyle = color
          ctx.fillRect(x, y, barWidth, count)
          // ctx.fillRect(barWidth, count*2, x, y)
          // text
        });
      }
      // 递归绘制⼦节点
      el.childs && el.childs.forEach(child => draw(child, true));
    }

    // 声明高阶函数
    function createCanvasApp(App) {
      const app = renderer.createApp(App)
      const mount = app.mount

      app.mount = function (sel) {
        canvas = document.createElement('canvas')
        canvas.width = window.innerWidth
        canvas.height = window.innerHeight
        document.querySelector(sel).appendChild(canvas)
        ctx = canvas.getContext('2d')
        mount(canvas)
      }

      return app
    }

    createCanvasApp({
      template: '#chart',
      data() {
        return {
          chartData: [
            { title: "黑铁", count: 260, color: "yellow" },
            { title: "⻘铜", count: 200, color: "brown" },
            { title: "钻石", count: 300, color: "pink" },
            { title: "星耀", count: 100, color: "purple" },
            { title: "王者", count: 50, color: "gold" }
          ]
        }
      },
    })
      .mount('#app')

  </script>
</body>

</html>
原文地址:https://www.cnblogs.com/soonK/p/14590869.html