Duh Huh
Duh Huh

Reputation: 139

Vue: how to create methods that change things created in mount()?

I want to create a button that recenter the canvas. Clicking the button should call the rec() method, which should recenter the canvas created in mounted().

But that doesn't work. I suspect that the methods can't really refer to things created in mounted().

How to fix this?

<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/[email protected]/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>

Upvotes: 1

Views: 403

Answers (1)

Mohammad Masoudi
Mohammad Masoudi

Reputation: 446

You can use the window to save the current created instance of the fabric class; I created a computed to do this and a state for the current status of the class.

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

And in computed I checked if that value was true don't make another instance and read them from the window object.

And for access a computed inside methods or mounted, you just use this keyword in Vue.

Also, I set an object as an active object, because if no object was selected and click on the recenter button you will get an error.

A note for your method definition: You don't have to write a name for your function.

In the below, I added a working example of 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/[email protected]/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/4.5.0/fabric.js"></script>

Reference: for make center the object I used a function in this pen (pen link)

Upvotes: 1

Related Questions