Canvas Fabricjs reset after scaling

I have fabricjs canvas, which I need to zoom in and out, and also change the image / object several times.

To do this, I set the canvas for the first time the page loads as follows:

fabric.Object.prototype.hasBorders = false; fabric.Object.prototype.hasControls = false; canvas = new fabric.Canvas('my_canvas', {renderOnAddRemove: false, stateful: false}); canvas.defaultCursor = "pointer"; canvas.backgroundImageStretch = false; canvas.selection = false; canvas.clear(); var image = document.getElementById('my_image'); if (image != null) { imageSrc = image.src; if(imageSrc.length > 0){ fabric.Image.fromURL(imageSrc, function(img) { img = scaleImage(canvas, img); //shrinks the image to fit the canvas img.selectable = false; canvas.centerObject(img); canvas.setActiveObject(img); canvas.add(img); }); } } canvas.deactivateAll().renderAll(); 

Then, when I need to change the image / object in the canvas or when the page reloads, I try to reset the canvas as follows:

 canvas.clear(); canvas.remove(canvas.getActiveObject()); var image = document.getElementById('my_image'); if (image != null) { imageSrc = image.src; if(imageSrc.length > 0){ fabric.Image.fromURL(imageSrc, function(img) { img = scaleImage(canvas, img); //shrinks the image to fit the canvas img.selectable = false; canvas.centerObject(img); canvas.setActiveObject(img); canvas.add(img); }); } } 

Not sure, it matters, but the way to change the image is to change the source in "my_image" and resell the canvas using the above method.

This works well until I use canvas.zoomToPoint , according to this thread, after that the image / object starts to change, when I reset the scale or click on the canvas with the mouse while it is enlarged, it seems that it jumps with every change in the top left corner eventually disappears from view.

Reset Scale:

 canvas.setZoom(1); resetCanvas(); //(above method) 

How to restore the position of the image / object?

I tried to do the initial setup instead of reset and take a photo to work visually, but actually added a new layer of the top canvas with each new setup, so this is not good.

Is there a way to reset the canvas to its original state without causing this behavior and still be able to scale / delete correctly?

+7
javascript fabricjs
source share
2 answers

I eventually fixed the problems that I had.

To reset zoom, instead of just setting the zoom to 1 using canvas.setZoom(1) , I applied the canvas.zoomToPoint method to the same point, but with a magnification of 1, to force the initial scaling, but relative to the same point that was used to increase.

Regarding the problem of restoring the position of the image in the canvas (for example, after panning), it is as simple as deleting the image, centering it in the canvas and re-adding it to the canvas, as was done when adding the first time:

  var img = canvas.getActiveObject(); canvas.remove(img); canvas.centerObject(img); canvas.setActiveObject(img); canvas.add(img); canvas.renderAll(); 
0
source share

See the fragment fragment below - here I am doing the same thing - scaling together, but degrading objects in case someone clicks on it.

The problem with obtaining the initial properties of the object can be solved, ungrouping the group and creating its copies and re-linking is a bit annoying, but the only solution I found.

 <script id="main"> // canvas and office background var mainGroup; var canvas = this.__canvas = new fabric.Canvas('c'); fabric.Object.prototype.transparentCorners = false; fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center'; createOnjects(canvas); // events - zoom $(canvas.wrapperEl).on('mousewheel', function(e) { var target = canvas.findTarget(e); var delta = e.originalEvent.wheelDelta / 5000; if (target) { target.scaleX += delta; target.scaleY += delta; // constrain if (target.scaleX < 0.1) { target.scaleX = 0.1; target.scaleY = 0.1; } // constrain if (target.scaleX > 10) { target.scaleX = 10; target.scaleY = 10; } target.setCoords(); canvas.renderAll(); return false; } }); // mouse down canvas.on('mouse:up', function(options) { if (options.target) { var thisTarget = options.target; var mousePos = canvas.getPointer(options.e); if (thisTarget.isType('group')) { // unGroup console.log(mousePos); var clone = thisTarget._objects.slice(0); thisTarget._restoreObjectsState(); for (var i = 0; i < thisTarget._objects.length; i++) { var o = thisTarget._objects[i]; if (o._element.alt == "officeFloor") continue; else { if (mousePos.x >= o.originalLeft - o.currentWidth / 2 && mousePos.x <= o.originalLeft + o.currentWidth / 2 && mousePos.y >= o.originalTop - o.currentHeight / 2 && mousePos.y <= o.originalTop + o.currentHeight / 2) console.log(o._element.alt); } } // remove all objects and re-render canvas.remove(thisTarget); canvas.clear().renderAll(); var group = new fabric.Group(); for (var i = 0; i < clone.length; i++) { group.addWithUpdate(clone[i]); } canvas.add(group); canvas.renderAll(); } } }); // functions function createOnjects(canvas) { // ToDo: jQuery.parseJSON() for config file (or web service) fabric.Image.fromURL('pics/OfficeFloor.jpg', function(img) { var back = img.set({ left: 100, top: 100 }); back._element.alt = "officeFloor"; back.hasControls = false; fabric.Image.fromURL('pics/me.png', function(img) { var me = img.set({ left: -420, top: 275 }); me._element.alt = "me"; console.log(me); var group = new fabric.Group([ back, me], { left: 700, top: 400, hasControls: false }); canvas.clear().renderAll(); canvas.add(group); // remove all objects and re-render }); }); } </script> 
-one
source share

All Articles