Reputation: 5387
I'm trying to get an arrow marker to display at the end of a line, but for some reason, this doesn't work in any browser I have or any graphics viewer or editor, except for Inkscape.
Can anyone tell me what I'm doing wrong?
<?xml version="1.0" encoding="UTF-8" ?>
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 500 500" width="500" height="500"
style="stroke: rgb(0, 0, 0); fill: none; stroke-linecap: round; stroke-linejoin: round;">
<defs>
<marker id="arrow" refX="-2.33" refY="0" orient="auto">
<path d="m 0,0 -5,2 q 1.5,-2 0,-4 z"
style="fill: rgb(0, 0, 0); stroke-width: 1;"
transform="scale(0.6667 0.6667)" />
</marker>
</defs>
<g transform="translate(20 20)">
<path d="m 0,0 100,0" style="stroke-width: 3; marker-end: url(#arrow);" />
</g>
</svg>
Update
The right viewBox
(without scaling the path inside the marker) is "-5.5 -2.5 6 5"
. The 4 parameters of the viewBox
are min-x, min-y, width, and height. They have to take into account whatever stroke-width
the marker
's elements may have, hence the extra 0.5 that I needed on either side.
Turns out, markerHeight
and markerWidth
are important to set, because the default value for both is 3
. That's why the arrow was coming out too small in my earlier attempt. For 1-to-1 scaling, they should be the same as the last two numbers in the viewBox
.
All of the viewBox
, markerHeight
, and markerWidth
need to be adjusted accordingly when scaling elements inside the marker.
Here's a complete solution based on the answer and the comments for posterity:
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 30 10" width="300" height="100"
style="stroke: #000000; fill: none; stroke-linecap: round; stroke-linejoin: round;">
<defs>
<marker id="arrow" refX="-1.333" refY="0"
orient="auto" markerUnits="strokeWidth"
viewBox="-3.667 -1.667 4 3.333"
markerWidth="4" markerHeight="3.333"
>
<path d="m 0,0 -5,2 q 1.5,-2 0,-4 z"
style="fill: #000000; stroke-width: 1;"
transform="scale(0.667)"
/>
</marker>
</defs>
<g transform="translate(5 5)">
<path d="m 0,0 10,0" style="stroke-width: 1.5; marker-end: url(#arrow);" />
</g>
<g transform="translate(25 5)">
<path d="m 0,0 -5,2 q 1.5,-2 0,-4 z"
style="fill: rgb(0, 0, 0); stroke-width: 1;" />
</g>
</svg>
Upvotes: 0
Views: 889
Reputation: 123985
The simplest thing is probably to add a viewBox to the marker so the shape is actually drawn in the marker canvas and not outside it.
<svg xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 500 500" width="500" height="500"
style="stroke: rgb(0, 0, 0); fill: none; stroke-linecap: round; stroke-linejoin: round;">
<defs>
<marker id="arrow" refX="-2.33" refY="0" orient="auto" viewBox="-3 -3 5 5">
<path d="m 0,0 -5,2 q 1.5,-2 0,-4 z"
style="fill: rgb(0, 0, 0); stroke-width: 1;"
transform="scale(0.6667 0.6667)" />
</marker>
</defs>
<g transform="translate(20 20)">
<path d="m 0,0 100,0" style="stroke-width: 3; marker-end: url(#arrow);" />
</g>
</svg>
Upvotes: 2