Reputation: 107
I am using fabric.js to generate a canvas with a background. I want to add zoom and followed this guide.
But when using .zoomToPoint()
with the background, it can unaligned and shows a white blank canvas. Try it yourself in my jsfiddle or down below by zooming in first with the mouse in the bottom right corner and then zooming out with the mouse on the top right. This produces the image being only in the top left part of the canvas.
My guess would be to change the 1000
to something associated with image or canvas width and height.
Thanks for your help.
Minimal Code example:
canvas=new fabric.Canvas("mycanvas")
fabric.Image.fromURL("https://images.unsplash.com/photo-1488330890490-c291ecf62571?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80", function(img) {
// add background image
canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas), {
scaleX: canvas.width / img.width,
scaleY: canvas.height / img.height
});
});
canvas.on('mouse:wheel', function(opt) {
var delta = opt.e.deltaY;
var zoom = canvas.getZoom();
zoom = zoom + delta/200;
if (zoom > 20) zoom = 20;
if (zoom < 1) zoom = 1;
canvas.zoomToPoint({ x: opt.e.offsetX, y: opt.e.offsetY }, zoom);
opt.e.preventDefault();
opt.e.stopPropagation();
var vpt = this.viewportTransform;
if (zoom < 400 / 1000) {
this.viewportTransform[4] = 200 - 1000 * zoom / 2;
this.viewportTransform[5] = 200 - 1000 * zoom / 2;
} else {
if (vpt[4] >= 0) {
this.viewportTransform[4] = 0;
} else if (vpt[4] < canvas.getWidth() - 1000 * zoom) {
this.viewportTransform[4] = canvas.getWidth() - 1000 * zoom;
}
if (vpt[5] >= 0) {
this.viewportTransform[5] = 0;
} else if (vpt[5] < canvas.getHeight() - 1000 * zoom) {
this.viewportTransform[5] = canvas.getHeight() - 1000 * zoom;
}
}});
#mycanvas{
border: black solid 1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.1.0/fabric.min.js"></script>
<canvas width="500px" height="300px" id="mycanvas"></canvas>
Upvotes: 0
Views: 1517
Reputation: 14731
The trick is to check when the viewport is going off bounds and fix it.
Change that generic 1000 with the size of the image at the current zoom in order to have it working.
canvas=new fabric.Canvas("mycanvas")
var imgWidth, imgHeight
fabric.Image.fromURL("https://images.unsplash.com/photo-1488330890490-c291ecf62571?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1050&q=80", function(img) {
// add background image
canvas.setBackgroundImage(img, function() {
canvas.requestRenderAll();
imgWidth = img.width * img.scaleX;
imgHeight = img.height * img.scaleY;
}, {
scaleX: canvas.width / img.width,
scaleY: canvas.height / img.height
});
});
canvas.on('mouse:wheel', function(opt) {
var delta = opt.e.deltaY;
var zoom = canvas.getZoom();
zoom = zoom + delta/200;
if (zoom > 20) zoom = 20;
if (zoom < 1) zoom = 1;
canvas.zoomToPoint({ x: opt.e.offsetX, y: opt.e.offsetY }, zoom);
opt.e.preventDefault();
opt.e.stopPropagation();
var vpt = this.viewportTransform;
if (vpt[4] >= 0) {
this.viewportTransform[4] = 0;
} else if (vpt[4] < canvas.getWidth() - imgWidth * zoom) {
this.viewportTransform[4] = canvas.getWidth() - imgWidth * zoom;
}
if (vpt[5] >= 0) {
this.viewportTransform[5] = 0;
} else if (vpt[5] < canvas.getHeight() - imgHeight * zoom) {
this.viewportTransform[5] = canvas.getHeight() - imgHeight * zoom;
}
});
#mycanvas{
border: black solid 1px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.1.0/fabric.min.js"></script>
<canvas width="500px" height="300px" id="mycanvas"></canvas>
Upvotes: 3