there's already a tutorial about it in FabricJS webpage, it works with mousewheel, but you can adapt it: http://fabricjs.com/fabric-intro-part-5
I did it with the some buttons.
First of all I have to tell you that zoom and panning affects canvas viewportTransform property, which is a matrix, similar to css transform property works (or I believe so...).
These are some outputs I got in console while I was working:
originalViewporTransform (6) [1, 0, 0, 1, 0, 0]
zoom
Affects index 0 & 3
zoomViewporTransform (6) [1.2, 0, 0, 1.2, 0, 0]
zoomViewporTransform (6) [1.44, 0, 0, 1.44, 0, 0]
panning
Right:
Affects index 4
panningViewporTransform (6) [1.44, 0, 0, 1.44, -82, 0]
panningViewporTransform (6) [1.44, 0, 0, 1.44, -83, 0]
Left:
Affects index 4
panningViewporTransform (6) [1.728, 0, 0, 1.728, 259, 0]
panningViewporTransform (6) [1.728, 0, 0, 1.728, 260, 0]
Bottom:
Affects index 5
panningViewporTransform (6) [1.728, 0, 0, 1.728, 0, -241]
panningViewporTransform (6) [1.728, 0, 0, 1.728, 0, -242]
Top:
Affects index 5
panningViewporTransform (6) [1.728, 0, 0, 1.728, 0, 305]
panningViewporTransform (6) [1.728, 0, 0, 1.728, 0, 306]
And here's my function to control panning with buttons, in four directions. To limit top and left panning you just have to set the respective viewport to 0 whenever is bigger. When is about right and bottom panning, you have to put the number size of the boundaries you are considering. I was considering the size of my canvas, but you can use which ever size you want.
...
else if (this.actualCanvasViewportTransform[4] < this.canvas.getWidth() - (this.canvas.getWidth() * this.actualCanvasZoom))
...
at those lines you would have to change (this.canvas.getWidth() * this.actualCanvasZoom) with the size you want, like so
(pxLimitRight * this.actualCanvasZoom)
hope it helps
whileMouseDown(caseType){
if (this.actualCanvasZoom <= this.originalCanvasZoom) return;
const units = 1;
let delta;
switch (caseType) {
case 'right':
delta = new fabric.Point(-units,0);
break;
case 'left':
delta = new fabric.Point(units,0);
break;
case 'bottom':
delta = new fabric.Point(0,-units);
break;
case 'top':
delta = new fabric.Point(0,units);
break;
}
this.canvas.relativePan(delta);
// console.log('panningViewporTransform', this.canvas.viewportTransform, this.actualCanvasZoom);
this.actualCanvasViewportTransform = this.canvas.viewportTransform;
/*
WE ARE PANNING LEFT AND RIGHT
*/
if (this.actualCanvasViewportTransform[4] >= 0) {
// WE ARE GOING LEFT
this.actualCanvasViewportTransform[4] = 0;
} else if (this.actualCanvasViewportTransform[4] < this.canvas.getWidth() - (this.canvas.getWidth() * this.actualCanvasZoom))
{
// WE ARE GOING RIGHT
this.actualCanvasViewportTransform[4] = this.canvas.getWidth() - (this.canvas.getWidth() * this.actualCanvasZoom);
}
/*
WE ARE PANNING DOWN AND UP
*/
if (this.actualCanvasViewportTransform[5] >= 0) {
// WE ARE GOING UP
this.actualCanvasViewportTransform[5] = 0;
} else if (this.actualCanvasViewportTransform[5] < this.canvas.getHeight() - (this.canvas.getHeight() * this.actualCanvasZoom)) {
// WE ARE GOING DOWN
this.actualCanvasViewportTransform[5] = this.canvas.getHeight() - (this.canvas.getHeight() * this.actualCanvasZoom);
}
}