Визуализация линии, которая следует за мышью, в конечном итоге замедляется с помощью нескольких строк на холсте с использованием Fabricjs - PullRequest
1 голос
/ 24 марта 2019

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

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

enter image description here

Код mouse:move практически идентичен в обоих случаях, поэтому я не могу понять, почему мой трюк настолько мучительно медленный после добавления около 50 объектов.

Красная линия, заметьте, как реагирует новая строка, когда мышь движется .: https://codepen.io/morrowsend/pen/YgBxvj?editors=0010

Моя тонкая скрипка, обратите внимание, что самая новая строка задерживается в реакции на движения мыши. Это связано с мышью: перемещайте, имея в нем canvas.renderAll (). Чем больше строк на холсте, тем менее он реактивен: https://codepen.io/morrowsend/pen/EMeWpM

Теперь вы можете сказать "Просто используйте анимацию", я попробовал это. Я еще не совсем понял, но я попробовал это, используя анимацию Fabric, которая мне не очень понравилась. Самый быстрый способ - 1 мс, но на самом деле он не очень реактивный, и он дает мне артефакты после прорисовки нескольких линий, иногда новая линия смещается от мыши. Кроме того, он помещает анимацию предыдущей строки так, что она перемещает конечную точку на самую новую строку. Это поведение легче увидеть. На изображении ниже у меня уже есть много строк в коде анимации, и вы можете видеть, что он ведет себя плохо. Когда я обновляю и начинаю с чистого холста, сначала все работает нормально, но чем больше строк я получаю, тем более неправильным становится результат: enter image description here

Вот мой код animate, использующий встроенную в Fabric анимацию. https://codepen.io/morrowsend/pen/YgBxvj?editors=0010

Я нашел пример использования animate с canvas, но я бы хотел, чтобы мои линии редактировались пользователем после того, как они были нарисованы (пока еще не реализованы). Это выглядит гладко, однако на холсте пока нет объектов-человечков, поэтому он может затормозить так же, как мой, если добавить еще: html холст линия, следующая за мышью релевантная скрипка: http://jsfiddle.net/dFjodorov/XQpzU/5171/

Как можно плавно анимировать рисование линии, даже если на экране несколько сотен объектов? Я чувствую, что перепробовал много вещей безрезультатно.

1 Ответ

1 голос
/ 28 марта 2019

Установите значение x2 и y2 строки в обработчике перемещения мыши, нет необходимости использовать анимацию.И удалите указатели мыши в режиме редактирования и добавьте в режиме рисования.

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

var isDown;

var point1;
var line = null;
var drawMode = true;

function addListener() {
  canvas.on('mouse:down', onMouseDown);
  canvas.on('mouse:dblclick', onDblClick);
  canvas.on('mouse:move', onMouseMove)
}

function removeListener() {
  canvas.off('mouse:down', onMouseDown);
  canvas.off('mouse:dblclick', onDblClick);
  canvas.off('mouse:move', onMouseMove)
}

function setSelectable(value) {
  canvas.forEachObject(function(object) {
    object.selectable = value;
    object.setCoords()
  })
  canvas.selection = value;
}

function onMouseDown(options) {
  isDown = true;
  var pointer = canvas.getPointer(options.e);
  var points = [pointer.x, pointer.y, pointer.x, pointer.y];
  line = new fabric.Line(points, {
    stroke: 'black',
    hasControls: false,
    hasBorders: false,
    lockMovementX: false,
    lockMovementY: false,
    hoverCursor: 'default',
    selectable: false
  });
  canvas.add(line);
};

function onDblClick() {
  //alert('dblclick')
  line.setCoords()
  isDown = false;
  line = null;
};

function onMouseMove(o) {
  if (!isDown) return;
  var pointer = canvas.getPointer(o.e);
  line.set({
    x2: pointer.x,
    y2: pointer.y
  });
  canvas.requestRenderAll();
}; //end mouse:move

document.addEventListener("keydown", function(event) {
  var keyPressed = event.keyCode;
  if (keyPressed === 27) { //escape key code
    edit();
  } //end if delete  
}); //end keydown


function draw() {
  drawMode = true
  addListener()
  setSelectable(false);
  // console.log(drawMode)
}


function edit() {
  // bool = false
  if (drawMode) {
    var canvas_objects = canvas._objects;
    var sel = canvas_objects[canvas_objects.length - 1]; //Get last object 
    canvas.remove(sel);
    drawMode = false;
  }
  removeListener();
  setSelectable(true);
}
var enableDraw = document.getElementById("drawEnabled");
enableDraw.addEventListener("click", draw);
var enableEdit = document.getElementById("editEnabled");
enableEdit.addEventListener("click", edit);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.4.6/fabric.min.js"></script>
        
<button id="drawEnabled">Draw Mode</button>
<button id="editEnabled">Edit Mode</button>
<canvas id="c" width="500" height="500" style="border:1px solid #aaa"></canvas>
...