Fabri cJS: объединение двух изображений для оптимизации памяти - PullRequest
0 голосов
/ 10 января 2020

Мне нужно запустить FabricJS / canvas на довольно оптимальном уровне для работы в моем случае использования в браузере.

У меня есть случаи, когда у меня есть фоновое изображение, и мне нужно нарисовать более 20000 полигонов в теме. Это невозможно, поэтому я в данный момент: 1) Сгенерирую статичное * PNG-изображение на стороне сервера полигонов, затем отправлю его в браузер и наложу его на фоновое изображение. 2) Затем, когда пользовательская мышь перемещается по соответствующие области, я загружаю интерактивные аннотации Fabri c в эти области.

Когда пользователь выбирает интерактивный многоугольник, перемещает его и опускает, мне нужно заново сгенерировать слой изображения stati c polygon с обновленными позициями этого многоугольника. Требуется слишком много памяти для воссоздания полного многоугольного изображения stati c с помощью toDataUrl, браузер падает.

Скажите, что я могу затем создать небольшое изображение stati c, используя дополнительный меньший холст. Затем мне нужно объединить его с большим многогранным изображением stati c. Я видел fabri c .clipTo, но использование его много раз (например, до 20 000 раз), в то время как fabri c сохраняет ссылку на него, наверняка замедлит работу браузера?

Есть ли способ в fabri cjs сделать эквивалент ctx.drawImage (img, sx, sy, swidth, sheight, x, y, width, height); таким образом, чтобы объединить его в изображение на холсте без создания дополнительных объектов?

Вот игровая площадка, которую я построил, чтобы попытаться найти способ объединить изменения в изображение многоугольника stati c ниже :

const SPACING = 15;
const RECTANGLE_SIDE = 40;
const TOTAL_RECT_SPACE = RECTANGLE_SIDE + SPACING;
const CANVAS_WIDTH = 300;
const CANVAS_HEIGHT = 300;

const CANVAS_RECT = document.getElementById('c').getBoundingClientRect();

const app = async () => {

  const canvas = new fabric.Canvas('c');

  const rectangles = generateRectangles();

  await createStaticImage(canvas, rectangles);

  showAnnotationsOnHover(canvas, rectangles);

};

const generateRectangles = () => {

  let rectangles = [];

  for (let i = 0; (i + 1) * TOTAL_RECT_SPACE < CANVAS_WIDTH; i++) {
    for (let j = 0; (j+ 1) * TOTAL_RECT_SPACE < CANVAS_HEIGHT; j++) {
      let rectangle = new fabric.Rect({
        left: i * TOTAL_RECT_SPACE,
        top: j * TOTAL_RECT_SPACE,
        fill: 'rgba(0, 0, 0, 0)',
        stroke: 'red',
        strokeWidth: 1,
        width: RECTANGLE_SIDE,
        height: RECTANGLE_SIDE
      });
      rectangles.push(rectangle);
    }
  };

  return rectangles;

}

const createStaticImage = (canvas, rectangles) => {

  return new Promise(resolve => {

    rectangles.forEach(rect => {
      rect.set({ stroke: 'blue' });
      canvas.add(rect);
    });
    const dataUrl = canvas.toDataURL();
    fabric.Image.fromURL(dataUrl, image => {
      image.set({
        selectable: false
      });
      canvas.add(image);
      resolve();
    });
    rectangles.forEach(rect => {
      rect.set({ stroke: 'red' });
      canvas.remove(rect);
    });

  });

}

const showAnnotationsOnHover = (canvas, rectangles) => {

  let showAnnotations = false;

  canvas.on('mouse:over', () => {
    if (!showAnnotations) {
      showAnnotations = true;
      rectangles.forEach(rect => {
        canvas.add(rect);
      })
    }
  });

  canvas.on('mouse:out', () => {
    if (showAnnotations) {
      showAnnotations = false;
      rectangles.forEach(rect => {
        canvas.remove(rect);
      });
    }
  });

}

app();
<html>
  <body>
    <div style="display: inline-block; height: 300px; width: 300px; background-color: lightblue; padding: 20px; box-sizing: border-box; ; vertical-align: top">
      <p> Hovering on the canvas shows Fabric Annotations. Otherwise it's a static image </p>
      <p> When a rectangle is moved, that change should be flattened down to the static image of the rectangles below. </p>
    </div>
    <div style="display: inline-block; height: 300px; width: 300px; vertical-align: top">
      <canvas id="c" width=300 height=300></canvas>
    </div>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.0/fabric.min.js"></script>
    <script src="index.js"></script>
  </body>
</html>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...