【问题标题】:Vue3, Composition API & HTML Canvas drawing refresh problemVue3, Composition API & HTML Canvas 绘制刷新问题
【发布时间】:2020-12-22 16:47:58
【问题描述】:

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

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

这是我的 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>

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

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

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

我只用了几周的 Vue(任何版本),目前我不确定如何进行调试。

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

任何帮助将不胜感激。

干杯

【问题讨论】:

  • 我的猜测是 vue 重新渲染,由于没有参考 vue 中实际发生的情况,因此不会重新渲染网格
  • 我在画布上看到的大多数带有 Vue 的教程似乎都会在发生变化时重新绘制整个画布等
  • @DerekPollard 我听到你说的话,但想知道为什么它第一次起作用,因为这也是一个外部类在做这项工作。我可能会尝试在板组件本身内部移动绘图方法。

标签: typescript vue.js html5-canvas vuejs3


【解决方案1】:

每当数据发生变化时,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);

但我会通过不在每次渲染上创建新的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();
});

这是一个demo,还有其他一些小的结构改进

【讨论】:

    猜你喜欢
    • 2021-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-11
    • 2022-01-25
    • 2021-06-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多