Fabric.js: Canvas zoom/position bug [$5]

Created on 27 May 2016  Â·  25Comments  Â·  Source: fabricjs/fabric.js

Version

1.6.2

Test Case

https://jsfiddle.net/qkj8o6eh/1/

Expected Behavior

When I initially set the zoom of my canvas (along with the canvas size and background image size) to 1, i add a rectangle. This rectangle acts as a marker for the center of our canvas. When we scale the canvas (and also the background image and canvas size respectfully) I would expect the center of the canvas to remain the same, regardless of the zoom level. This expected result would be the two rectangles centered on the canvas.

Actual Behavior

Instead, what we see is the position of the second rectangle differs when we zoom the canvas to something other than the initial value "1".

NOTES:

Keep in mind, this might also effect other align functions, (i.e. centerObjectH, etc.) other than object.center().

https://api.bountysource.com/badge/issue?issue_id=34629617

bounty bug

All 25 comments

i think there is aduplicate for this i will check and in case close.
But yes we should clarify on top of function of what center we are talking about e respect it.

@asturur Would the center function need to be the center at all times regardless of the zoom? Why even have a center function that only centers when the canvas is at only an initial point?

Because this is a free project. The whole zoom function has been a bounty supported feature. The user that did it did not change the centering functions, or maybe in the old discussion about this something has been said. Maybe someone already pointed out this problem with centering, maybe in the wrong moment when no one had time to listen (not that i have now, but i decided to support fabricjs). There are no so many "BECAUSE" to return to many "WHY". There is what you see now and it can done better probably if the right amount of energy, skill, time and love are mixed in (and sometimes money speed things up).

@asturur Sorry, didn't mean it in that tone. I thought it was a core feature of the canvas (to zoom). I will be glad to help or even throw some money out there to get these issues fixed.

Your tone was fine. I was not complaining, just explaning what is the situation clearly.

@asturur I submitted a small bounty for my most two recent issues. Ill try to add more later if this doesn't help a tiny bit.

I was thinking that now fabricjs has clearly a "canvas" and a "viewport". So instead of guessing where we should center what, we should just be able to ask canvas.center(obj) and canvas.viewportCenter(obj);
I think as a long term solution is better than having just one or having something like canvas.center(obj, boolean_to_consider_viewport)

A bit of research shows that it's a combination of the zoom and setting the canvas dimensions - each works fine when used alone. It appears to be due to how the getCenter function works, I think it might need to take into account the viewport transforms. However, that doesn't make much sense.

It looks like this is more of a fundamental issue with coordinates that I'm not prepared to solve. I'm going to stop working on this, at least for now.

Ok, thank you for taking a look at this.

On Tuesday, May 31, 2016, PlasmaPower [email protected] wrote:

It looks like this is more of a fundamental issue with coordinates that
I'm not prepared to solve. I'm going to stop working on this, at least for
now.

—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
https://github.com/kangax/fabric.js/issues/3015#issuecomment-222866026,
or mute the thread
https://github.com/notifications/unsubscribe/AGlOWI3UsmbAhJpK__l92vqibs9uKWSkks5qHNuygaJpZM4IoaGv
.

There is a PR that will add the methods for this. They will be separate methods. I wrote just one for now, check #3017.

@asturur Will this fix an issue with the coords in general? Take this for instance:

function AlignVertical() {
    var object = editor.getActiveObject() || editor.getActiveGroup();
    if(object) {
        object.setTop((editor.getHeight() / 2) - (object.getHeight() / 2));
    }
}

zoom the canvas and then try to use this simple calculation to center the object. The coords are the same, but it does not center correctly?

@asturur To be sure I am correct, here is a fiddle of exatly what I am talking about (i.e. coords).

http://jsfiddle.net/y551Lkdx/

Because you cannot set it like this. To center and object we use setPositionByOrigin where we switch the position to center,center, we place where we want and then we go back to the positioning top,left.
No other way to do this.

@asturur Then how would I create a function to position something in the center of the cavas (even when it's zoomed?) I am trying to create Left Align, Right Align, and so on..., but without me being able to calculate the points is there any way I could do this?

Even the function below has the same issues:

function AlignHorizontal() {
    var object = editor.getActiveObject() || editor.getActiveGroup();
    if(object) {
        //object.setLeft((editor.getWidth() / 2) - (object.getWidth() / 2));
        object.setPositionByOrigin(new fabric.Point(editor.getWidth() / 2, object.top), "center", object.originY);
    }
}

did you try the functions i posted in the PR? they are supposed to do that. I did not have time to test them yet. tests are failing, i hope they weren't...

@asturur they didn't work. I tried modifying them slightly as well and I got the same issue. I think it is something with the coordinate system that is broken.

yes i noticed they are broken .i think i fixed them.

Ok, let me see if it works on my end. Also, why doesn't dividing the width of the canvas by 2 and calculating a point work directly? I don't understand the internals for that (one reason i am scared to help contribute - i might break something).

@asturur I found a way around it! I can calculate the viewportHeight and width like so:

var viewportHeight = canvas.getHeight() / canvas.getZoom();

From there I can literally just set the coords and it centers!

is what the functions are doing. You do not take in account the panning in this way. if the canvas is panned down, you are not in right point.

@asturur Ah, for what i am doing I pan the entire canvas in a div. I dont use fabric's pan. So, the width and the height of my canvas expand with the zoom of the canvas. Might just be good for my situation.

Hello everyone. We have worked on the mentioned problem and here is the solution.

Below are the updated changes for the Fabric.js to make the center for canvas.

Changes in Fabric js:

zoomToPoint: function (point, value) {
// TODO: just change the scale, preserve other transformations
var before = point;
point = fabric.util.transformPoint(point, fabric.util.invertTransform(this.viewportTransform));
this.viewportTransform[0] = value;
this.viewportTransform[3] = value;
var after = fabric.util.transformPoint(point, this.viewportTransform);
this.viewportTransform[4] = before.x;
this.viewportTransform[5] = before.y;
this.renderAll();
for (var i = 0, len = this._objects.length; i < len; i++) {
this._objects[i].setCoords();
}
return this;
},

setZoom: function (value, pt) { //Added a new parameter (pt)
this.zoomToPoint(new fabric.Point(pt.x, pt.y), value);
return this;
},

And for point (pt) calculation for the above setZoom() function, below is the code:

function zoom(scale) {
var current_zoom =scale;
var windowWidth, windowHeight;
var docposX = (windowWidth - (Number(bgWidth * current_zoom)))/2;
var docposY = (windowHeight - (Number(bgHeight * current_zoom)))/2;
if(current_zoom != tempZoom){
var pt = {};
var arr = canvas.viewportTransform;
pt.x = docposX;
pt.y = docposY
canvas.setZoom(current_zoom,pt);
}
}

Please check the above and let us know how it goes.


http://www.i95dev.com

Nice addition, like that you removed the renderAll as well : )
This will be useful for us.

this is finally done.

The new methods are:

canvas.viewportCenter(object)
canvas.viewportCenterH(object)
canvas.viewportCenterV(object)
object.viewportCenter()
object.viewportCenterH()
object.viewportCenterV()

i could add the booleans to the old ones, but i think this is more clear also for documentation.
I mean, it would be same, but there are more chances an user will notice the method before opening an issue asking if there is a way to center in the viewport and not in the canvas.

@FeaRCODE i accidentally rebuilded the distribution folder, so fabric.js in the repository is updated. Could you give it a test?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

semiadam picture semiadam  Â·  3Comments

bevacqua picture bevacqua  Â·  4Comments

mlev picture mlev  Â·  3Comments

semiadam picture semiadam  Â·  3Comments

zhangzhzh picture zhangzhzh  Â·  4Comments