Reputation: 310
I need to display an arrow to show the evolution of some metric, for this I created an algorithm that draws the line and add use a marker to have the shape of an arrow.
I've tried to change the refX so the marker would finish at the end but since the line is thick it displays the rest of the line after the marker. I can reduce change this refX in a way that I don't see the rest of the line but I want to see the whole marker within the limits of the svg.
I could also reduce the length of the line so the line + the marker takes the whole place but then I cannot find the correct amount of pixels I need to remove.
The line is rendered dynamically which means it won't always be in that way. In a svg(x,y) from (0,0) to (100,100) it can go from (100,0) to (100,100).
Current code displays the arrow overflowing the svg, I would like to have everything in it.
<svg class="svg" style="height: 190px; width: 328px; border:1px solid blue;">
<marker class="red_arrow_normal" markerUnits="strokeWidth" viewBox="0 0 10 10" refY="6" orient="auto"
markerHeight="10" markerWidth="10" id="red-3" refX="10">
<path d="M2,2 L10,6 L2,10 L6,6 L2,2" style="fill: red;"></path>
</marker>
<line x1="0" y1="0" x2="328" y2="190" stroke="red" stroke-width="10" marker-end="url(#red-3)"></line>
</svg>
Upvotes: 0
Views: 523
Reputation: 600
There doesn't look to be a clean solution to this problem that doesn't involve some javascript, but you can solve it with some math:
function drawArrow(x1, y1, x2, y2) {
const svg = document.getElementById("my-svg")
let dx = x2 - x1;
let dy = y2 - y1;
const length = Math.sqrt(dx * dx + dy * dy);
if (length > 0)
{
dx /= length;
dy /= length;
}
const SHORTEN = 6
const x3 = x1 + dx * (length - SHORTEN)
const y3 = y1 + dy * (length - SHORTEN)
svg.innerHTML += `<line x1=${x1} y1=${y1} x2=${x3} y2=${y3} stroke="red" stroke-width="5" marker-end="url(#arrow)"></line>`
}
You will first have to make sure your arrow head extends past the end of the line, so that the square end of the line isn't showing. Then you will have to adjust the SHORTEN
variable to offset the extra length of the arrow head.
My fiddle: https://jsfiddle.net/h4pgoaLw/
Upvotes: 1
Reputation: 57
You can edit it online in codepen here. I have modified the width and height.
<svg class="svg" style="height: 190px; width: 328px; border:1px solid blue;">
<marker class="red_arrow_normal" markerUnits="strokeWidth" viewBox="0 0 10 10" refY="6" orient="auto"
markerHeight="10" markerWidth="10" id="red-3" refX="9">
<path d="M2,2 L10,6 L2,10 L6,6 L2,2" style="fill: red;"></path>
</marker>
<line x1="0" y1="0" x2="320" y2="180" stroke="red" stroke-width="10" marker-end="url(#red-3)"></line>
</svg>
Upvotes: 0