Нормализовать рисование в FabricJS?

Короче говоря, я делаю приложение, где люди могут сотрудничать и рисовать изображения.

Сейчас у меня есть подтверждение концепции, но я заметил, что рисунки отображаются с неверным масштабом в браузере другого человека, если два человека, которые сотрудничают, используют окна разных размеров.


Решение состоит в том, чтобы нормализовать входные данные для рисования таким образом, чтобы точки выражались в процентах от холста, который они охватывают, вместо абсолютных значений пикселей. Тем не менее, я не знаю, как это сделать в FabricJS. Наконец, я должен быть уверен, что решение работает и при увеличении.

Любой совет для нормализации ввода чертежа будет принят! Для справки, вот мой код.

Имейте в виду: я никогда не использовал FabricJS раньше, поэтому этот пример кода представляет собой смесь нескольких постов в блоге и SO ответов. Это не очень хороший код, и он будет полностью переработан, если FabricJS - библиотека, с которой я решил пойти

Важные строки были прокомментированы

document.addEventListener('DOMContentLoaded', () => {
  const room = window.location.href.split('/').pop();
  const socket = io.connect();

  socket.on('connect', () => {
    socket.emit('room', room);
  });

  var canvas = new fabric.Canvas('map', {
    isDrawingMode: true
  });

  let size = Math.min(window.innerWidth, window.innerHeight);
  canvas.setHeight(size);
  canvas.setWidth(size);

  var img = new Image();
  img.onload = function () {
    canvas.setBackgroundImage(img.src, canvas.renderAll.bind(canvas), {
      width: canvas.width,
      height: canvas.height,
    });
  };
  img.src="/images/map.jpg";

  canvas.wrapperEl.addEventListener('wheel', (e) => {
    if (e.deltaY <= 0) {
      canvas.zoomToPoint({
        x: e.offsetX,
        y: e.offsetY
      }, canvas.getZoom() * 1.1);
    } else {
      canvas.zoomToPoint({
        x: e.offsetX,
        y: e.offsetY
      }, canvas.getZoom() * 0.9);
    }
  });

  canvas.on('path:created', function (e) {
    // This is where I need to normalize the path data
    canvas.remove(fabric.Path.fromObject(JSON.stringify(e.path)));
    socket.emit('draw_line', {
      line: e.path.toJSON(),
      room: room
    });
  });

  socket.on('draw_line', function (path) {
    // This is where I need to convert the path data from percentages to real size
    fabric.util.enlivenObjects([path], function (objects) {
      objects.forEach(function (o) {
        canvas.add(o);
      });
    });
  });

  var panning = false;
  canvas.on('mouse:up', function (e) {
    panning = false;
  });
  canvas.on('mouse:out', function (e) {
    panning = false;
  });
  canvas.on('mouse:down', function (e) {
    panning = true;
  });
  canvas.on('mouse:move', function (e) {
    //allowing pan only if the image is zoomed.
    if (panning && e && e.e && e.e.shiftKey) {
      var delta = new fabric.Point(e.e.movementX, e.e.movementY);
      canvas.relativePan(delta);
    }
  });
});

1 ответ

Общее рабочее решение заключается в том, что вы даете чертежной доске виртуальный фиксированный размер:

15.000 x 15.000 например.

Затем в каждом клиентском приложении вы делаете холст настолько большого размера, сколько захотите, например 1000 х 1000, а другой получит 800 х 800.

Установка масштабирования холста для каждого из них позволит увидеть чертеж настолько большим, насколько это необходимо, с теми же значениями точек в 15 000 пространственных координат.

Толщина рисунка, вероятно, изменится в зависимости от уровня масштабирования.

canvas.setZoom(1000/15000) а также canvas.setZoom(800/15000) должно быть достаточно.

Если это не работает, где-то есть ошибка, которую следует исправить.

Другие вопросы по тегам