Стрелка неправильно нарисована на холсте fabricJS

#javascript #html #canvas #position #fabricjs

#javascript #HTML #холст #положение #fabricjs

Вопрос:

Я работаю над проектом, в котором на холсте fabricJS можно нарисовать несколько фигур (прямоугольник, треугольник, эллипс, ..). Теперь я реализую функциональность для рисования стрелки. Эта стрелка состоит из двух фигур: линии и треугольника (головка стрелки). Они добавляются на холст как групповой объект, но проблема в том, что стрелка неправильно нарисована на холсте. (см. Эту картинку ).

Ниже приведен мой код для рисования стрелки:

 drawShape: function(canvas, shape) {

        let selectedShape;
        let pointer, startX, startY, origX, origY;
        let rect, ellipse, line, triangle, arrow;

        let stroke = 'black';
        let fill = 'transparent';

 canvas.on('mouse:down', function(option) {

    if(option.target != null) {
         return;
    } else {

         switch(shape)
         {

           case 'arrow' :

             pointer = canvas.getPointer(option.e);                         
             let arrowLinePoints = [pointer.x, pointer.y, pointer.x, pointer.y];

             startX = pointer.x;
             startY = pointer.y;

             line = new fabric.Line(arrowLinePoints, {
                 top: startY,
                 left: startX,
                 fill: fill,
                 stroke: stroke,
             });

             // reference points for arrowhead
             origX = line.x2;
             origY = line.y2;

             let dx = line.x2 - line.x1,
                 dy = line.y2 - line.y1;

             /* calculate angle of arrow */
             let angle = Math.atan2(dy, dx);
             angle *= 180 / Math.PI;
             angle  = 90;

             arrow = new fabric.Triangle({
                 angle: angle,
                 fill: 'black',
                 top: line.y2,
                 left: line.x2,
                 width: 1,
                 height: 1,
                 originX: 'center',
                 originY: 'center',
                 stroke: stroke
             });


              let grp = new fabric.Group([line, arrow], {
                 top: startY,
                 left: startX,
                 width: 1,
                 height: 1,
                 hasBorders: true,
                 hasControls: true,
              });

              selectedShape = grp;

              break;

      }

      canvas.add(selectedShape);  


      canvas.on("mouse:move", function(option) {

            switch(shape) {

              case 'arrow' :
                   pointer = canvas.getPointer(option.e);     

                   selectedShape.set({
                       width: Math.abs(startX -pointer.x),
                       height: Math.abs(startY - pointer.y)
                   });
                   selectedShape.setCoords();                        

                   line = selectedShape.item(0);
                   line.set({
                        x2: pointer.x, 
                        y2: pointer.y,
                        left: selectedShape.left,
                        top: selectedShape.top
                    });
                    line.setCoords();

                     let dx = line.x2 - line.x1,
                         dy = line.y2 - line.y1;

                      let angle = Math.atan2(dy, dx);
                      angle *= 180 / Math.PI;
                      angle  = 90;

                      arrow = selectedShape.item(1);
                      arrow.set({
                               top: line.y2, 
                               left: line.x2, 
                               angle: angle,
                               width: 15, 
                               height: 15
                       });  
                       arrow.setCoords();

                       canvas.renderAll();

                       break;
               }
  });  

canvas.on('mouse:up', function() {

   canvas.off('mouse:move');                      
});
 

JSFiddle: https://jsfiddle.net/9408k1gb /

Есть ли способ это исправить? Заранее спасибо!

С уважением,

Sven

Комментарии:

1. Попробуйте вызвать setCoords для группы после ее создания.

2. Я пробовал, но проблема остается…

3. Хм, в таком случае не могли бы вы опубликовать jsfiddle или что-то в этом роде?

4. Я добавил jsfiddle

Ответ №1:

Я думаю, что добавление линии и стрелки в группу, а затем их перемещение вызывали некоторые проблемы. Я изменил код так, чтобы стрелка и линия объединялись в группу только после завершения рисования, и это, казалось, устранило проблему. Основы того, что я сделал, это дождаться mouse:up события, а затем позаботиться о группе следующим образом:

 canvas.deactivateAll();
canvas.remove(line);
canvas.remove(arrow);
selectedShape = new fabric.Group([line, arrow], {
    hasBorders: true,
    hasControls: true,
});
canvas.add(selectedShape);
 

https://jsfiddle.net/9408k1gb/1/

Комментарии:

1. Это действительно решение. Большое вам спасибо!

2. Я отредактировал jsfiddle, чтобы вы могли рисовать более одной стрелки: jsfiddle.net/9408k1gb/4