Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
359 views
in Technique[技术] by (71.8m points)

reactjs - Increase Arrow from both sides in React-Konva

I'm drawing a Line with React-Konva. Once the Line is drawn, I would like to display an Arrow (with pointers on both sides) underneath that Line. That Arrow should be longer (both sides) than the Line but should point the same direction.

What I've tried so far is to create an Arrow with the same points as the Line, and then using a scale on that Arrow to make it longer than the Line. This works, but the Arrow is longer than the Line on just one side.

Screenshot

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

Is there a method I can use to accomplish this?

question from:https://stackoverflow.com/questions/65923609/increase-arrow-from-both-sides-in-react-konva

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

In principle your issue is because the arrow shape is drawn from the x & y position - A in your sketch. What you need to do is compute the positions for the drawing point moved by 0.1 times the line length, then apply a 1.2 scale X & Y.

You can do this by

  1. Get the width and height of the line via the line points where the starting pt is {x: points[0], y: points[1]} and the ending pt is the same from points[2] and [3].
  2. Subtract the x's to get length and y's to get the height.
  3. Multiply each by .1 to find the delta X & Y.
  4. Subtract deltaX & Y from the line X & Y to find the new drawing point
  5. Draw you arrow from there using the same points[] array as the line, and scale of 1.2.

Job done. I would not have thought of your cunning solution of manipulating the scale - I would likely have computed the end point in the same manner as the start point and drawn the arrow between them at a scale of 1.

I include a working snippet below - this is vanilla JS rather than react but hopefully it will show you the way.

The black line is the original Konva line, and the arrow position is computed as per my explanation above.

  // 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 & 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>

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...