Creating methods in Vue that can alter elements created during the mounted lifecycle hook can be achieved by defining functions

I am trying to implement a button that can recenter the canvas. The idea is that when the button is clicked, it will trigger the rec() method which should reposition the canvas that was created in the mounted() function.

However, this setup is not working as expected. I suspect that the methods are having trouble referencing elements created within the mounted() function.

Any suggestions on how to resolve this issue?

<div id="main">
    <canvas id="c" width="400" height="400"></canvas>
</div>
<button v-on:click="recenter">Recenter</button>

<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.5.0/fabric.js"></script>

<script>
    const app = new Vue(
        {
            el: '#main',
            methods: {
                recenter: function rec() {
                    var fabric_canvas = new fabric.Canvas('c')
                    fabric_canvas.setViewportTransform([1,0,0,1,0,0]);
                }
            },
            mounted() {
                var fabric_canvas = new fabric.Canvas('c');
                var group = [];
                var myurl = "https://upload.wikimedia.org/wikipedia/commons/a/a0/Svg_example1.svg";
                fabric.loadSVGFromURL(
                    myurl,
                    function(objects,options) {
                        var loadedObjects = new fabric.Group(group);
                        fabric_canvas.add(loadedObjects);
                        fabric_canvas.renderAll();
                    },
                    function(item, object) {
                        group.push(object);
                    }
                );
            }
        }
    );
</script>

Answer №1

To store the current instance of the fabric class, utilize the window property; I have implemented a computed function for this purpose and a state to determine the status of the class.

If an instance of the fabric class is created, then the value of fabricHaveAnActiveInstance will be set to true.

In the computed function, it checks if the value is true so as not to create another instance and retrieves them from the window object instead.

To access a computed function within methods or when mounted, simply use the this keyword in Vue.

I have also designated an active object, as clicking the recenter button without selecting an object would result in an error.

Note regarding method definition: You are not required to assign a name to your function.

Below is a functional example based on your code:

const app = new Vue(
        {
            el: '#main',
            data: function(){
                return {
                    fabricHaveAnActiveInstance: false
                }
            },
            methods: {
                recenter: function () {
                  // this.fabric_canvas.setViewportTransform([1,0,0,1,0,0]);
                    let object = this.fabric_canvas.getActiveObject()
                    let objWidth = object.getScaledWidth()
                    let objHeight = object.getScaledHeight()
                    let zoom = this.fabric_canvas.getZoom()
                    let panX = 0
                    let panY = 0
                    
                    console.log("object width is: " + object.width)
                    console.log(" object.getScaledWidth.x is: " + object.getScaledWidth())
                    

                    panX = ((this.fabric_canvas.getWidth() / zoom / 2) - (object.aCoords.tl.x) - (objWidth / 2)) * zoom
                    panY = ((this.fabric_canvas.getHeight() / zoom / 2) - (object.aCoords.tl.y) - (objHeight / 2)) * zoom
                                          
                    this.fabric_canvas.setViewportTransform([zoom, 0, 0, zoom, panX, panY])
                      
                }
            },
            mounted() {
                console.log(this.fabric_canvas)
                var fabric_canvas = this.fabric_canvas;
                var group = [];
                var myurl = "https://upload.wikimedia.org/wikipedia/commons/a/a0/Svg_example1.svg";
                fabric.loadSVGFromURL(
                    myurl,
                    function(objects,options) {
                        var loadedObjects = new fabric.Group(group);
                        fabric_canvas.add(loadedObjects);
                        fabric_canvas.renderAll();
                        fabric_canvas.setActiveObject(fabric_canvas.item(0))
                    },
                    function(item, object) {
                        group.push(object);
                    }
                );
                
            },
            computed:{
                fabric_canvas: function(){
                    if(this.fabricHaveAnActiveInstance){
                        return window.fabric_canvas
                    }else{
                        const fabric_instance = new fabric.Canvas('c'); 
                        window.fabric_canvas = fabric_instance;
                        this.fabricHaveAnActiveInstance = true;
                        return fabric_instance;
                    }
                }

            }
        }
    );
<div id="main">
    <canvas id="c" width="400" height="400"></canvas>

    <button v-on:click="recenter">Recenter</button>
</div>

<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4533302005776b736b7471">[email protected]</a>/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.5.0/fabric.js"></script>

Reference: To center the object, I used a function in this pen (pen link)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

A quirky bug with Tumblr's JS/Jquery Infinite Scroll and Masonry feature

As someone new to JS/JQuery and masonry, I seem to be facing a puzzling issue with overlapping posts/divs. Despite my extensive search for answers, I have run out of ideas. The problem arises from the content at this link: Below is the complete theme cod ...

Encountering issues with styling the search bar using CSS and unable to see any changes reflected

I am currently working on creating a searchBar and customizing its CSS, but unfortunately, most of the styling properties seem to not be taking effect. So far, only changing colors seems to work as expected. .mainBar{ background-color: blue; width: ...

Combine items with similar structure, yet distinct characteristics

Currently working on a program that checks the frequency of certain occurrences in a document based on specified rules. Using regular expressions to process fields, I am able to count the instances of a particular field or perform a more detailed analysis ...

Rotating the camera around the origin in Three.js

Hey, I'm having some trouble with what I thought would be a simple task. I have a group of objects at the origin, and I'm trying to rotate a camera around them while always facing the origin. According to the documentation, this code should work: ...

Guide on sharing Photo Blogs on Tumblr using the "tumblr.js" NodeJS module

I've been using the tumblr.js node module to interact with the Tumblr API, but I'm having trouble understanding what exactly should be included in the "options" when posting on my blog. So far, I've only used this module to retrieve my follo ...

Tips for transitioning the li class from active to none

Struggling with changing the li class (of Home) from 'active' to none (or another class) when clicking on the profile tab, and then changing the li class (of Profile) from none to 'active' when the profile is activated. Snippet of my c ...

Remove Request (MongoDB, express, handlebars)

Struggling with implementing a delete request in my application. I have a database filled with reviews that I manipulate through my app. Currently, I'm attempting to create a function that will remove a document from the database and then redirect th ...

Updating the model of a Vuejs single file component (.vue) within the <script> tag

Discovering the world of vuejs, I set out to create a basic single file component for testing purposes. This component's main task is to showcase a boolean and a button that toggles the boolean value. It also listens for a "customEvent" which trigger ...

Is there a way to detect in the browser when headphones have been unplugged?

Is there an event to pause the video when the audio device changes, like if headphones get unplugged? I've looked into other questions, but they don't seem to be for browser. Detecting headphone status in C# Detecting when headphones are plugg ...

Issue with child routes not functioning properly within single spa React application

{ "name": "@my-react-app/demo", "scripts": { "start": "webpack serve", "start:standalone": "webpack serve --env standalone", "build": "concurrently npm:build:*", "build:webpack": "webpack --mode=production", "analyze": "webpack --mo ...

Trigger an Ajax function using a button within a Bootstrap modal

I need to trigger an ajax function after selecting an option from a bootstrap confirmation modal. The modal will appear by calling the remove(parameter) function. Any assistance would be greatly appreciated function remove(parameter){ // $("#remove-mod ...

What is the best way to implement an 'onKeyPress' event listener for a <canvas> element in a React application?

I've been working with React for a while now and I understand how its event system functions. However, I've run into an issue where the onKeyPress event doesn't seem to be triggering on a <canvas> element. Surprisingly, it's not w ...

Generate pre-set components using fundamental building blocks

Can I predefine some props for components? In my Vuetify example, let's say I want to customize the v-btn component with specific props. This custom implementation would act as a child component while still providing all the functionalities of the par ...

Dealing with intricate query parameters in Express.Js

Currently, I am working on developing REST APIs using Express.js. One particular express route that I have set up is as follows: /api/customer I have incorporated multiple query parameters into this route, such as: /api/customer?name=jake /api/customer?c ...

What is the proper way to invoke a variable-function in Node.js?

I have a function called `findPeopleByName` that queries the database for a specific username, but I'm not sure how to call it in my Node.js code. Here's what I have so far: // Retrieve user_name from POST request. app.post("/api/exercise/new-u ...

Tips for updating the color of table data when the value exceeds 0

I'm currently working on developing a transaction table that is intended to display debit values in red and credit values in green. However, I would like these colors to only be applied if the value in the table data is greater than 0 via JavaScript. ...

Encountering an error with an undefined callback argument within an asynchronous function

I encountered an issue while working with the viewCart function. I have implemented it in the base controller and am calling it from the home controller. However, I am facing an error where the callback argument in home.js is showing up as 'undefined& ...

Is there a way to automatically compress Express JS assets?

Is there a way to dynamically minify the frontend JavaScript/CSS of my Express JS application? Are there any potential drawbacks to this approach? ...

Having trouble with refreshing the div content when using jQuery's $.ajax() function

My goal is to refresh a div that has the id #todos after saving data in the database. I attempted to use .load() within $.ajax() $('.todo--checkbox').change(function () { let value = $(this).data('value'); $.ajax({ url: ...

What is the best way to convert an array of data into a dataset format in React Native?

Within my specific use case, I am seeking to reform the array structure prior to loading it into a line chart. In this context, the props received are as follows: const data = [26.727, 26.952, 12.132, 25.933, 12.151, 28.492, 12.134, 26.191] The objective ...