#StackBounty: #javascript #html5-canvas #fabricjs Controlling the Zoom out view port in FabricJS

Bounty: 50

I am trying out the examples given here on the pan and zoom in fabric js and got it working. I am using the zoom to point to zoom where the cursor was. However, the problem I face is that if I zoomIn in one place and zoomOut in another, there is an offset created between the border and background. Even though the code works for restricting the pan area to 1000×400 px, while zooming out, the boundaries are not restricted.

How can I restrict the boundaries even while zooming out, such that there is no offset?

Code here:

(function(){
var canvas = new fabric.Canvas('canvas1',{backgroundImage:"https://images.unsplash.com/photo-1520299607509-dcd935f9a839?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1489&q=80"});
 viewportTransform=canvas.viewportTransform;
    canvas.add(new fabric.Rect({ width: 50, height: 50, fill: 'blue', angle: 10 }))
    canvas.add(new fabric.Circle({ radius: 50, fill: 'red', top: 44, left: 80 }))
    canvas.add(new fabric.Ellipse({ rx: 50, ry: 10, fill: 'yellow', top: 80, left: 35 }))
    canvas.add(new fabric.Rect({ width: 50, height: 50, fill: 'purple', angle: -19, top: 70, left: 70 }))
    canvas.add(new fabric.Circle({ radius: 50, fill: 'green', top: 110, left: 30 }))
    canvas.add(new fabric.Ellipse({ rx: 50, ry: 10, fill: 'orange', top: 12, left: 100, angle: 30 }))
    canvas.on('mouse:wheel', (opt) => {
      var delta = opt.e.deltaY;
      var zoom = canvas.getZoom();
      zoom *= 0.999 ** delta;
      if (zoom > 20) zoom = 20;
      if (zoom < 0.01) zoom = 0.01;
      canvas.zoomToPoint(new fabric.Point(opt.e.offsetX, opt.e.offsetY), zoom);
      opt.e.preventDefault();
      opt.e.stopPropagation();
      var vpt = viewportTransform;
      if (zoom < 0.4) {
        vpt[4] = 200 - 1000 * zoom / 2;
        vpt[5] = 200 - 400 * zoom / 2;
      } else {
        if (vpt[4] >= 0) {
          vpt[4] = 0;
        } else if (vpt[4] < canvas.getWidth() - 1000 * zoom) {
          vpt[4] = canvas.getWidth() - 1000 * zoom;
        }
        if (vpt[5] >= 0) {
          vpt[5] = 0;
        } else if (vpt[5] < canvas.getHeight() - 400 * zoom) {
          vpt[5] = canvas.getHeight() - 400 * zoom;
        }
      }
    });
    canvas.on('mouse:down', function (opt) {
      var evt= opt.e;
      if (evt.altKey === true) {
        this.isDragging = true;
        this.selection = false;
        this.lastPosX = evt.clientX;
        this.lastPosY = evt.clientY;
      }
    });
    canvas.on('mouse:move', function (opt) {
      if (this.isDragging) {
        var e = opt.e;
        var zoom = canvas.getZoom();
        var vpt = this.viewportTransform;
        if (zoom < 0.4) {
          vpt[4] = 200 - 1000 * zoom / 2;
          vpt[5] = 200 - 400 * zoom / 2;
        } else {
          vpt[4] += e.clientX - this.lastPosX;
          vpt[5] += e.clientY - this.lastPosY;
          if (vpt[4] >= 0) {
            vpt[4] = 0;
          } else if (vpt[4] < canvas.getWidth() - 1000 * zoom) {
            vpt[4] = canvas.getWidth() - 1000 * zoom;
          }
          if (vpt[5] >= 0) {
            vpt[5] = 0;
          } else if (vpt[5] < canvas.getHeight() - 400 * zoom) {
            vpt[5] = canvas.getHeight() - 400 * zoom;
          }
        }
        this.requestRenderAll();
        this.lastPosX = e.clientX;
        this.lastPosY = e.clientY;
      }
    });
    canvas.on('mouse:up', function (opt) {
      this.setViewportTransform(this.viewportTransform);
      this.isDragging = false;
      this.selection = true;
    });
})()
https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.6/fabric.min.js
  <canvas id="canvas1" height="300" width="400" style="border:1px solid"></canvas>

Issue Screenshot:
enter image description here


Get this bounty!!!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.