renanvm
renanvm

Reputation: 216

Fit and prevent image position inside canvas

I have a page that lets you insert an image inside the canvas element and works perfectly.

Now, what I need is a way to prevent the positioning of the image inside the canvas, not allowing to be left over whitespace, regardless of the positioning of the image.

The image selection option is active. The repositioning is done using drag and drop. I'm using fabric js to position the image.

Example

I need something like this when image is zoomed, but i need to have a fixed size canvas and the image will be larger than the canvas

Canvas

<canvas id="c" height="300" width="200"></canvas>

Image

<img id="image" src="images/test.jpg">

JS

    var c = new fabric.Canvas('c');

        var imageSrc = "images/test.jpg";

        fabric.Image.fromURL(imageSrc, function(img) {
            img.scaleToWidth(c.getWidth());
            img.scaleToHeight(c.getHeight());
            img.set('selectable', true);
            img.set('hasControls', false);
            c.add(img);
        });

Upvotes: 0

Views: 2216

Answers (1)

Paschoal
Paschoal

Reputation: 175

I was able to modify your second example to behave the way you want.

Here is the modified script.js:

var canvas = window._canvas = new fabric.Canvas('canvas', {
    preserveObjectStacking: true
});

var imageObj = new Image(), path = 'http://i.imgur.com/tEeSJcr.jpg';

imageObj.src = path;

imageObj.onload = function () {
    var image = new fabric.Image(imageObj);

    canvas.setHeight(250);
    canvas.setWidth(250);
    image.set({
        id: 'img',
        left: 0,
        top: 0,
        selectable: true,
        hasBorders: false,
        hasControls: false,
        hasRotatingPoint: false
    });
    canvas.add(image);
};


canvas.on('object:moving', function (e) {
    var obj;
    obj = e.target;
    obj.setCoords();

    var boundingRect = obj.getBoundingRect();
    var zoom = canvas.getZoom();
    var viewportMatrix = canvas.viewportTransform;

    //there is a bug in fabric that causes bounding rects to not be transformed by viewport matrix
    //this code should compensate for the bug for now
    boundingRect.top = (boundingRect.top - viewportMatrix[5]) / zoom;
    boundingRect.left = (boundingRect.left - viewportMatrix[4]) / zoom;
    boundingRect.width /= zoom;
    boundingRect.height /= zoom;

    var canvasHeight = obj.canvas.height / zoom,
        canvasWidth = obj.canvas.width / zoom;

    if(boundingRect.top > 0){
        obj.top = 0;
    }

    if(boundingRect.left > 0){
        obj.left = 0;
    }

    if (boundingRect.top < canvasHeight - boundingRect.height){
        obj.top = canvasHeight - boundingRect.height;
    }

    if (boundingRect.left < canvasWidth - boundingRect.width){
        obj.left = canvasWidth - boundingRect.width;
    }

});

$('#zoomIn').click(function () {
    if (canvas.getZoom() < 3) {
        canvas.setZoom(canvas.getZoom() + 0.1);
    }
});

$('#zoomOut').click(function () {
    if (canvas.getZoom() !== 1) {
        canvas.setZoom(canvas.getZoom() - 0.1);
    }
});

Here is the working example.

Some explanation about the solution: In order to prevent the image borders from being dragged inside the canvas you need to constrain its top and left positions. The top-left position of the canvas starts with (0,0) and increases the value from top to bottom and left to right. To constrain the top of the image you check if its position (obj.top) is greater than 0 and if it is you just change it back to 0. The same is valid to the left side. For the right and bottom it gets a little different, because you don't have left and right properties on the object to check against. To solve that you just need to calculate the maximum negative numbers the top and left values can reach, which is done by subtracting the canvas height from the image height to get the top value and the canvas width from the image width for the left one, if the values decrease more than that you just set it back to the value you calculated. Ex: For a 200x200 canvas and a 250x250 image the top and left values of -50 would prevent the image from being dragged inside.

enter image description here

Upvotes: 3

Related Questions