Увеличить стрелку с обеих сторон в React-Konva

#reactjs #konvajs #react-konva #konva

#reactjs #конвайс #react-konva #konva

Вопрос:

Я рисую линию с помощью React-Konva. Как только линия будет нарисована, я хотел бы отобразить стрелку (с указателями с обеих сторон) под этой линией. Эта стрелка должна быть длиннее (с обеих сторон), чем линия, но должна указывать в том же направлении.

До сих пор я пытался создать стрелку с теми же точками, что и линия, а затем использовать масштаб на этой стрелке, чтобы сделать ее длиннее линии. Это работает, но стрелка длиннее линии только с одной стороны.

Скриншот

 <Arrow
 pointerAtBeginning={true}
 scaleX={1.4}
 scaleY={1.4}
 stroke="rgb(0, 61, 55)"
 x={startPoint[0]}
 y={startPoint[1]}
 points={[0, 0, ...endPoint]}
/>
 

Есть ли метод, который я могу использовать для достижения этой цели?

Ответ №1:

В принципе, ваша проблема заключается в том, что форма стрелки нарисована из позиции x amp; y — A в вашем эскизе. Что вам нужно сделать, это вычислить позиции для точки рисования, перемещенной в 0,1 раза больше длины линии, затем применить масштаб 1,2 X amp; Y.

Вы можете сделать это с помощью

  1. Получите ширину и высоту линии через точки линии, где начальная точка pt равна {x: точки [0], y: точки [1]}, а конечная точка pt одинакова из точек [2] и [3].
  2. Вычтите x, чтобы получить длину, и y, чтобы получить высоту.
  3. Умножьте каждый на .1, чтобы найти дельту X amp; Y.
  4. Вычтите deltaX amp; Y из линии X amp; Y, чтобы найти новую точку рисования
  5. Нарисуйте стрелку оттуда, используя тот же массив точек [], что и линия, и масштаб 1.2.

Работа выполнена. Я бы не подумал о вашем хитром решении манипулировать масштабом — я бы, вероятно, вычислил конечную точку таким же образом, как и начальную точку, и нарисовал стрелку между ними в масштабе 1.

Я включаю рабочий фрагмент ниже — это ванильный JS, а не react, но, надеюсь, он укажет вам путь.

Черная линия — это исходная линия Konva, а положение стрелки вычисляется в соответствии с моим объяснением выше.

   // Set up a stage
let     
    // Konva housekeeping
    stage = new Konva.Stage({
      container: 'container',
      width: window.innerWidth,
      height: window.innerHeight
    }), 

    // add a layer to draw on
    layer = new Konva.Layer(),

    points = [0, 0, 250, -50],
    drawX = 50,
    drawY = 100
    line = new Konva.Line({
      x: drawX,
      y: drawY,
      points: points,
      stroke: 'black',
      strokeWidth: 3
    });
    
// Add the layer to the stage and shape to layer
stage.add(layer);


// Make a couple of points to give start and end of line for ease
let ptStart = {x: points[0], y: points[1]},
    ptEnd =  {x: points[2], y: points[3]};

// Compute the width and height of the line
let sz = {
  width: Math.abs(ptEnd.x - ptStart.x),
  height: Math.abs(ptEnd.y - ptStart.y),
}

// Compute x amp; y size of 10% increase
let adj = {
  width: sz.width * 0.1,
  height: sz.height * 0.1
}

// Compute new position of arrow.
drawX = drawX - adj.width;
drawY = drawY   adj.height

// add the arrow at the new position and scaled x 1.2
let arrow = new Konva.Arrow({
      x: drawX,
      y: drawY,
      points: points,
      stroke: 'magenta',
      strokeWidth: 6,
      opacity: 0.2,
      pointerAtBeginning: true,
      scaleX: 1.2,
      scaleY: 1.2
    });

// Job done
layer.add(line, arrow)
stage.draw(); 
 * {
  box-sizing: border-box;
}

body {
  margin: 10;
  padding: 10;
  overflow: hidden;
  background-color: #f0f0f0;
}

#container {
  border: 1px solid silver;
} 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://unpkg.com/konva@^3/konva.min.js"></script>
  <div id="container"></div>