Как отобразить другой холст без увеличения в fabricjs - PullRequest
0 голосов
/ 30 января 2020

Короче говоря, я разрабатываю проект, в котором есть два холста: холст, поддерживающий масштабирование и рисование, второй холст - дубликат первого холста, который должен отображать общий вид без масштабирования. К сожалению, я не понимаю, как это реализовать, поскольку второй холст также отображает картинку с увеличением. Пожалуйста помоги! Вот небольшой пример того, что у меня есть:

var c1 = document.getElementById("scale");
var c2 = document.getElementById("static");

var canvas = this.__canvas = new fabric.Canvas(c1, {
  isDrawingMode: true
});
var ctx1 = c1.getContext("2d");
var ctx2 = c2.getContext("2d");

function copy() {
    var imgData = ctx1.getImageData(0, 0, 512, 512);
    ctx2.putImageData(imgData, 0, 0);
}

fabric.Image.fromURL(
  "https://cdn-images-1.medium.com/max/1800/1*sg-uLNm73whmdOgKlrQdZA.jpeg",
  img => {
    img.scaleToWidth(canvas.width);
    canvas.setBackgroundImage(img);
    canvas.requestRenderAll();
  },
  {
    crossOrigin: "Annoymous"
  }
);

canvas.on('mouse:wheel', function(opt) {
  var delta = opt.e.deltaY;
  var pointer = canvas.getPointer(opt.e);
  var zoom = canvas.getZoom();
  zoom = zoom + delta/200;
  if (zoom > 20) zoom = 20;
  if (zoom < 0.01) zoom = 0.01;
  canvas.zoomToPoint({ x: opt.e.offsetX, y: opt.e.offsetY }, zoom);
  opt.e.preventDefault();
  opt.e.stopPropagation();
});
    

setInterval(() => {
    copy();
}, 10)
canvas {
  border: 1px solid black;
}
#static {
  position: relative;
  top: -300px;
  left: 500px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.1/fabric.min.js"> </script>

This is interactive canvas
<canvas id="scale" width="300" height="300"></canvas>

<canvas id="static"width="300" height="300"></canvas>

Ответы [ 2 ]

1 голос
/ 02 февраля 2020

Не существует идеального решения, потому что fabri cJS не поддерживает рендеринг для большего количества целей.

Здесь есть метод toCanvasElement, который создает копию на другой холст, но не позволяет Вы указываете холст, на котором хотите рисовать.

Итак, в какой-то момент я делаю вот что:

  • Сброс масштабирования до 1
  • . новый холст
  • верните масштаб на прежнее значение
  • скопируйте этот холст на стати c холст

Существует дополнительная копия, которая быстро на современном оборудовании, до такой степени, что вас это не волнует, но было бы лучше добавить аргумент canvas к этому методу toCanvasElement, чтобы рисование происходило на указанном холсте немедленно

Тогда кроме этого есть вопрос при стрельбе этой копии. 'after: render' не очень хорошая идея, она будет l oop навсегда, и она также будет перерисовываться при изменении масштаба, это не то, что вам нужно.

Пока я использую объект: добавлен, вы можете добавьте также объект: измененный, и, возможно, что-то еще, но в идеале вы будете вызывать копию вручную, когда это необходимо, при запуске некоторого кода, который изменит некоторые свойства чертежа.

var c1 = document.getElementById("scale");
var c2 = document.getElementById("static");

var canvas = this.__canvas = new fabric.Canvas(c1, {
  isDrawingMode: true
});
var ctx2 = c2.getContext("2d");

function copy(copiedCanvas) {
   ctx2.drawImage(copiedCanvas,0,0);
}

fabric.Image.fromURL(
  "https://cdn-images-1.medium.com/max/1800/1*sg-uLNm73whmdOgKlrQdZA.jpeg",
  img => {
    img.scaleToWidth(canvas.width);
    canvas.setBackgroundImage(img);
    canvas.requestRenderAll();
  },
  {
    crossOrigin: "Annoymous"
  }
);

canvas.on('mouse:wheel', function(opt) {
  var delta = opt.e.deltaY;
  var pointer = canvas.getPointer(opt.e);
  var zoom = canvas.getZoom();
  zoom = zoom + delta/200;
  if (zoom > 20) zoom = 20;
  if (zoom < 0.01) zoom = 0.01;
  canvas.zoomToPoint({ x: opt.e.offsetX, y: opt.e.offsetY }, zoom);
  opt.e.preventDefault();
  opt.e.stopPropagation();
});

function afterRender() {
  var originalVP = canvas.viewportTransform;
  canvas.viewportTransform = [1, 0, 0, 1, 0, 0];
  copy(canvas.toCanvasElement());
  canvas.viewportTransform = originalVP;
}

canvas.on('object:added', afterRender);
canvas.on('object:modified', afterRender);
canvas {
  border: 1px solid black;
}
#static {
  position: relative;
  top: -300px;
  left: 500px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.1/fabric.min.js"> </script>

This is interactive canvas
<canvas id="scale" width="300" height="300"></canvas>

<canvas id="static"width="300" height="300"></canvas>
1 голос
/ 30 января 2020

Ваша проблема в том, что вы получаете "ImageData" из контекста
, но вы должны использовать объект fabric.Canvas ...

Контекст дает вам только то, что вы видите, поэтому те два полотна будут зеркальным отображением, вы должны получить данные из fabric.Canvas, который имеет «большую картинку» со всеми изменениями.

В моем прототипе я использую canvas.toJSON чтобы получить данные, а затем нарисовать эти данные, я использую loadFromJSON, но я заметил, что какое-то мерцание при загрузке нового изображения загружается, поэтому я решил использовать изображение вместо stati c canvas, таким образом, переход будет плавным

см. Мой простой прототип ниже:

var c1 = document.getElementById("scale");
var static = document.getElementById("img");
var canvas = new fabric.Canvas(c1, {isDrawingMode: true});

function copy() {
  var data = canvas.toObject();
  var c = new fabric.Canvas();
  c.loadFromJSON(data,  function() {
    static.src = c.toDataURL({ format: 'png' });
  });  
}

fabric.Image.fromURL(
  "https://cdn-images-1.medium.com/max/1800/1*sg-uLNm73whmdOgKlrQdZA.jpeg",
  img => {
    img.scaleToWidth(canvas.width);
    canvas.setBackgroundImage(img);
    canvas.requestRenderAll();
  }, { crossOrigin: "anonymous" }
);

canvas.on('mouse:wheel', function(opt) {
  var pointer = canvas.getPointer(opt.e);
  var zoom = canvas.getZoom() + opt.e.deltaY / 200;
  if (zoom > 20) zoom = 20;
  if (zoom < 0.01) zoom = 0.01;
  canvas.zoomToPoint({
    x: opt.e.offsetX,
    y: opt.e.offsetY
  }, zoom);
  opt.e.preventDefault();
  opt.e.stopPropagation();
});

setInterval(copy, 200)
canvas {
  border: 2px solid black;
}
img {
  border: 2px solid red;
  position: absolute;
  top: 5px; right: 5px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.1/fabric.min.js">
</script>

<canvas id="scale" width="300" height="150"></canvas>
<br><img id="img"   width="300" height="150">

Если у нас не возникнет проблема совместимости браузера (я только проверял chrome), результат должен выглядеть следующим образом:

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...