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.
<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?
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
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>