Q:

Fabric.js position elements relative to getZoom() and getWidth()/getHeight()

I am using Fabric.js with React/Redux and i am trying to achieve the following effect on canvas: (note i have 2 rulers on the top and left which shouldn't move around when panning, just horizontally and vertically).
This is a video of the effect I am trying to get: https://vid.me/qs5Q
I have the following code:
var canvas = new fabric.Canvas('c');
var topRuler = new fabric.Text('this is the top ruler', {
  top: 0,
  left: 60,
  selectable: false
});
var leftRuler = new fabric.Text('this is the left ruler', {
  top: 150,
  left: -125,
  selectable: false
});
var circle = new fabric.Circle({
  radius: 20,
  fill: 'green',
  left: 180,
  top: 100
});
var triangle = new fabric.Triangle({
  fill: 'green',
  left: 150,
  top: 170
});
var panning = false;
var panningOn = false;
leftRuler.setAngle(-90).setCoords();
canvas.add(circle, triangle, topRuler, leftRuler);
canvas.renderAll();

canvas.on('mouse:up', function(e) {
 if (panningOn) panning = false;
});

canvas.on('mouse:down', function(e) {
 if (panningOn) panning = true;
});

canvas.on('mouse:move', function(e) {
  if (panning && e && e.e) {
  moveX = e.e.movementX;
  moveY = e.e.movementY;
  topRuler.set({
    top: topRuler.top - moveY,
    left: topRuler.left - moveX
  });

  leftRuler.set({
    top: leftRuler.top - moveY,
    left: leftRuler.left - moveX
  });
   canvas.relativePan(new fabric.Point(moveX, moveY));
  }
});
$('#toggle').click(function() {
  panningOn = !panningOn;
  canvas.selection = !panningOn;
  canvas.defaultCursor = 'default';
  $('#toggle').html('Turn Panning ON');
  if (panningOn) {
   $('#toggle').html('Turn Panning OFF');
   canvas.defaultCursor = 'move';
  }
});

 /* ZOOM FUNCTIONS */
 $('#zoomIn').click(function(){
    canvas.setZoom(canvas.getZoom() * 1.1 ) ;
 });

 $('#zoomOut').click(function(){
    canvas.setZoom(canvas.getZoom() / 1.1 ) ;
 });

This is a working JSFiddle: https://jsfiddle.net/z3p8utmc/19/
The code is not complete since I do not know exactly how to position the rulers, tried to play with viewPort, canvas size, etc. but did not manage to get the same effect.
Thank you for the help.

A:

Here's a screen shot of the results:

Here's the two zoom functions:
/* ZOOM FUNCTIONS */
$('#zoomIn').click(function() {
  rectangle.set({
    width: rectangle.width * 1.1,
    height: rectangle.height * 1.1
  });
  rectangle.setCoords();
  textSample.set({
    top: 60 + (textSample.top - 60) * 1.1,
    left: 60 + (textSample.left - 60) * 1.1,
    scaleX: textSample.scaleX * 1.1,
    scaleY: textSample.scaleY * 1.1
  });
  textSample.setCoords();
  setPins();
  addLeftRuler();
  addTopRuler();
  resizeCanvas();
});
$('#zoomOut').click(function() {
  rectangle.set({
    width: rectangle.width / 1.1,
    height: rectangle.height / 1.1
  });
  rectangle.setCoords();
  textSample.set({
    top: 60 + (textSample.top - 60) / 1.1,
    left: 60 + (textSample.left - 60) / 1.1,
    scaleX: textSample.scaleX / 1.1,
    scaleY: textSample.scaleY / 1.1
  })
  textSample.setCoords();
  setPins();
  addLeftRuler();
  addTopRuler();
  resizeCanvas();
});

Panning is done using a 3rd-Party control, and the traditional way, since that's what the video shows (and you wanted) - top and left rulers are kept in place by updating their positions as scrolling occurs.
Zooming is done by scaling the individual objects based on point (60, 60) - as in the video. Pins are reset, rulers are rescaled, and canvas is resized - as needed.
The trick is calculating and recalculating everything as user actions are taken and events are firing.
Hopefully this gets you the canvas foundation you need to build upon.
Here's a working JSFiddle, https://jsfiddle.net/rekrah/hs6jL8d4/.

