Vue3、Composition API & HTML Canvas 绘图刷新问题

Chr*_*ger 2 html5-canvas typescript vue.js vuejs3

我有一个打字稿代码库,在其中创建了一个工作数独板,只需直接处理 DOM,并使用其 API 在 HTML Canvas 元素上进行专门绘制。

我现在想将我的项目扩展到一个完整的站点,并且我正在尝试将我已有的内容合并到 Vue3 项目中。我正在将 Composition API 与 typescript 结合使用。我已经开始取得进展,但因板刷新问题而停止。

这是我的 Board 组件的启动代码:

<template>
    <button @click="grow">Grow</button>
    <br><br>
    <div class="board">
        <canvas ref='myCanvas' :width="size.w" :height="size.h" tabindex='0' 
style="border:1px solid #000000;"
        ></canvas>
    </div>
</template>

<script lang="ts">

    import { defineComponent, onMounted, ref, reactive } from 'vue'
    import { CanvasManager } from '@/managers/canvasmanager'

    export default defineComponent({
        
        setup() {
                 
            let myCanvas = ref(null)
            let myContext = ref(null)
            let manager = ref(null)

            let size = reactive({
                w: 200,
                h: 200
            })

            function grow() {
                size.w += 10
                size.h += 10
                manager.drawGrid(4, 4, 1, 'black')
            }
            
            onMounted(() => {
                myContext = myCanvas.value.getContext('2d')
                manager = new CanvasManager(myContext, size.w, size.h)
                manager.drawGrid(4, 4, 1, 'black')
            })

            return {
                myCanvas,
                size,
                grow
            }
        }
    })
</script>
Run Code Online (Sandbox Code Playgroud)

这里导入的是我编写的一个实用程序类CanvasManager,它包含各种 Canvas API 绘图助手。

此代码在首次加载时有效。manager.drawGrid(4, 4, 1, 'black')内部调用起作用onMounted并在画布上绘制 4 x 4 网格。

增长方法还增加了画布的大小,并且可以看到边框在增长,但是,对manager.drawGrid(4, 4, 1, 'black')增长方法内部的调用没有效果。边框内的网格消失并且不会重新绘制。

我只使用 Vue(任何版本)几个星期,我不确定目前如何进行调试。

我在控制台中没有收到任何错误。我已将控制台日志记录添加到 CanvasManager 中的 drawGrid 方法中,并且可以看到它肯定被调用。

任何帮助将不胜感激。

干杯

Dan*_*Dan 7

每当数据发生变化时,Vue 都会再次渲染组件,但这并不意味着重新安装,并且您的画布只准备绘制onMounted。所以当组件重新渲染节点时,之前的绘制就会丢失。解决这个问题的一种快速方法是绘制onUpdated

function draw() {
  myContext = myCanvas.value.getContext('2d')
  manager = new CanvasManager(myContext, size.w, size.h)
  manager.drawGrid(4, 4, 1, 'black')
}

onMounted(draw);
onUpdated(draw);
Run Code Online (Sandbox Code Playgroud)

但我会通过不在每次渲染上创建新对象来进一步改进代码CanvasManager,这只需完成一次。

function draw() {
  manager.drawGrid(4, 4, 1, 'black')
}

onMounted(() => {
  myContext = myCanvas.value.getContext('2d')
  manager = new CanvasManager(myContext, size.w, size.h)
  draw();
});
onUpdated(() => {
  draw();
});
Run Code Online (Sandbox Code Playgroud)

这是一个带有其他一些小的结构改进的演示