2

I want to achieve semantic zooming using fabricjs.

I've got a plot of dense points on the canvas. However, when we zoom in or zoom out, points size should remain as it is but the distance between them should increase or decrease respectively.

Take a look at these 2 examples

Canvas Geometric Zooming https://bl.ocks.org/mbostock/3680958

Canvas Semantic Zooming https://bl.ocks.org/mbostock/3681006

I want to achieve zooming similar to Semantic zooming using fabricjs.

I've attempted the solution using fabricjs and so far seems to be working fine. I want to know or validate if there is any better way of achieving the same using fabricjs.

We also want to preserve the point position relative to the image (floor plan), which is not happening. Please check the updated fiddle.

My solution fiddle link https://jsfiddle.net/bharatpatil/v7658dn9/43/

HTML

<button id="zoomIn">Zoom In</button>
<button id="zoomOut">Zoom Out</button>
<br>
<canvas id="c"></canvas>

Javascript

var i, dot,
  getRandomInt = fabric.util.getRandomInt,
  rainbow = ["#ffcc66", "#ccff66", "#66ccff", "#ff6fcf", "#ff6666"],
  rainbowEnd = rainbow.length - 1;

var circle1Radius = 20;

// create canvas instance
var canvas2 = new fabric.Canvas('c', {
  backgroundColor: "#fff",
  renderOnAddRemove: false
});


fabric.Image.fromURL('https://upload.wikimedia.org/wikipedia/commons/9/9a/Sample_Floorplan.jpg', function(img) {

  img.scaleX = canvas2.width / img.width;
  img.scaleY = canvas2.height / img.height;
  img.set('selectable', false);
  img.opacity = 0.3;
  canvas2.add(img);

  createDots();
});


function createDots() {
  // draw random dots
  for (i = 100; i >= 0; i--) {
    dot = new fabric.Circle({
      left: getRandomInt(0, 400),
      top: getRandomInt(0, 350),
      radius: circle1Radius,
      selectable: false,
      lockScalingX: true,
      lockScalingY: true,
      lockRotation: true,
      hasControls: false,
      hasBorders: true,
      hasRotatingPoint: false,
      objectType: 'AppCircle'
    });
    dot.setGradient('fill', {
      type: 'radial',
      r1: 0,
      r2: circle1Radius,
      x1: circle1Radius,
      y1: circle1Radius,
      x2: circle1Radius,
      y2: circle1Radius,
      colorStops: {
        0: 'rgb(85, 196, 255, 1)',
        0.1: 'rgb(85, 196, 255, 0.5)',
        0.2: 'rgb(85, 196, 255, 0.4)',
        0.3: 'rgb(85, 196, 255, 0.3)',
        0.4: 'rgb(85, 196, 255, 0.2)',
        1: 'rgba(85, 196, 255, 0.1)',
      }
    });
    canvas2.add(dot);
  }
  canvas2.renderAll(); // Note, calling renderAll() is important in this case
}

function zoom(isZoomingIn) {
  var SCALE_FACTOR = 1.1;
  var objects = canvas2.getObjects();
  var dd = 1;
  if (isZoomingIn) dd = SCALE_FACTOR;
  if (!isZoomingIn) dd = 1 / SCALE_FACTOR;
  for (var i in objects) {
    if (objects[i].objectType !== 'AppCircle') {
      console.log(objects[i]);
      objects[i].scaleX = objects[i].scaleX * dd;
      objects[i].scaleY = objects[i].scaleY * dd;
    }
    objects[i].left = objects[i].left * dd;
    objects[i].top = objects[i].top * dd;
    objects[i].setCoords();
  }
  canvas2.setHeight(canvas2.height * dd);
  canvas2.setWidth(canvas2.width * dd);
  canvas2.renderAll();
  canvas2.calcOffset();
}

document.getElementById('zoomIn').addEventListener('click', () => {
  zoom(true);
});
document.getElementById('zoomOut').addEventListener('click', () => {
  zoom(false);
});

Update

We also want to preserve the point position relative to the image (floor plan), which is not happening. Please check the updated fiddle.

https://jsfiddle.net/bharatpatil/v7658dn9/43/

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.