首页 > 解决方案 > Fabric.js 不在 Vue 3 组件内的画布上渲染对象

问题描述

我尝试在 Vue 3 中使用 Fabric.js 在画布上添加一个简单的矩形

我能够在页面内的画布顶部加载矩形,因为它似乎在组件内不起作用。

我尝试在组件中设置 2 秒超时,但它没有渲染任何内容。

有什么解决方法还是我犯了任何错误?

    <template>
        <TransitionRoot as="template" :show="showCanvas">
            <Dialog as="div" class="fixed z-10 inset-0" @close="showCanvas = false">
                <div class="w-full" style="width: 60%!important; height:auto">
                    <TransitionChild as="template" enter="ease-out duration-300" enter-from="opacity-0"
                        enter-to="opacity-100" leave="ease-in duration-200" leave-from="opacity-100" leave-to="opacity-0">
                        <DialogOverlay class="fixed inset-0 bg-gray-500 bg-opacity-75 transition-opacity" />
                    </TransitionChild>

                    <!-- This element is to trick the browser into centering the modal contents. -->
                    <span class="hidden sm:inline-block sm:align-middle sm:h-screen" aria-hidden="true">&#8203;</span>
                    <TransitionChild as="template" enter="ease-out duration-300"
                        enter-from="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95"
                        enter-to="opacity-100 translate-y-0 sm:scale-100" leave="ease-in duration-200"
                        leave-from="opacity-100 translate-y-0 sm:scale-100"
                        leave-to="opacity-0 translate-y-4 sm:translate-y-0 sm:scale-95">
                        <div
                            class="bg-white">
                            <div>
                                
                                <div class="mt-3 text-center sm:mt-5">
                                
                                

                                    <!-- This example requires Tailwind CSS v2.0+ -->
                                    <div class="fixed inset-0 overflow-y-auto z-50 flex justify-center items-center">
                                        <div class=" bg-white m-auto rounded-lg shadow-md" role="dialog" aria-modal="true"
                                            aria-labelledby="modal- headline" style="width: 550px !important;height:auto;">
                                        
                                            <canvas id="canvas"  ></canvas>
                                
                                        
                                        </div>
                                    </div>

                                    <div class="flex w-full mx-auto absolute bottom-56 justify-center z-50">
                                            <button type="button"
                                                class="w-50 mr-2 inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-indigo-600 text-base font-medium text-white hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:col-start-2 sm:text-sm"
                                                >
                                                Save
                                            </button>
                                            <button type="button"
                                                class="mt-3 w-50 ml-2 inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:col-start-1 sm:text-sm"
                                                @click="closePopup" ref="cancelButtonRef">
                                                Cancel
                                            </button>
                                        </div>

                                    
                                

                                </div>
                            </div>
                        
                        </div>
                    </TransitionChild>
                </div>
            </Dialog>
        </TransitionRoot>


    </template>

    <script>

    import { fabric } from 'fabric'
    import { ref, watch, reactive, onMounted } from 'vue';

    import { Dialog, DialogOverlay, DialogTitle, TransitionChild, TransitionRoot } from '@headlessui/vue'


    export default {

        components:
        {
            Dialog,
            DialogOverlay,
            DialogTitle,
            TransitionChild,
            TransitionRoot,
        },

        props: {

            showCanvas: {
                required: true,
                type: Boolean
            },

        
        },

        setup(props, context) {

            reactive(props.showCanvas) // Make the prop reactive so that we can watch for changes

           

            let canvas = undefined

            watch(() => props.showCanvas, (selection, prevSelection) => {
                
                if (selection == true) {

                    bindImage()

                }

            })

            function bindImage()
            {
            

                canvas = new fabric.Canvas('canvas');


                setTimeout(function(){

                

                    var rectangle = new fabric.Rect({
                        width: 300,
                        height: 200,
                        fill: '',
                        stroke: 'green',
                        strokeWidth: 5
                    });
            
                    console.log("Rectangle>>>>", rectangle);
            
                    // Render the Rect in canvas
                    canvas.add(rectangle);


                }, 2000);
            
            }
        
        
            function closePopup()
            {
                context.emit("closeCanvas")
            }

            return {
                
                closePopup,
                
            }
            
        }

    }
    </script>

    <style>

    </style>

标签: vue.jshtml5-canvasfabricjs

解决方案


您应该将它们放入onMounted块中,例如:

<template>
  <canvas width="600" height="600" id="canvas" style="border: 1px solid #ccc;"></canvas>
</template>

<script setup>
import { onMounted } from 'vue'
import { fabric } from 'fabric'

function init() {
  let canvas = new fabric.Canvas('canvas')  // 实例化fabric,并绑定到canvas元素上

  // 圆
  let circle = new fabric.Circle({
    left: 100,
    top: 100,
    radius: 50,
  })

  canvas.add(circle)
}

onMounted(() => {
  init()
})
</script>

推荐阅读