5

I have a curve generated by this:

    var path = ["M", x1.toFixed(3), y1.toFixed(3), "L", arrow_left_x, arrow_left_y, "L", arrow_right_x, arrow_right_y, "L", x1.toFixed(3), y1.toFixed(3), "C", x2, y2, x3, y3, x4.toFixed(3), y4.toFixed(3)].join(",");

enter image description here

but my arrow is not correctly done.
- it only points to the right, and doesn't point the same direction as the slope of the curve at the end of the bezier. - it is not filled

now, I know I'm not doing the math correctly here, but mainly, I just want to know how to fill the triangle at the end of the line. thanks!

For demo purposes:

        arrow_left_x = (x1 - 8);
        arrow_left_y = (y1 - 8);
        arrow_right_x = (x1 - 8);
        arrow_right_y = (y1 + 8);

that is the code for getting the the coordinates I use.

NullVoxPopuli
  • 61,906
  • 73
  • 206
  • 352
  • 1
    See also _[Arrow triangles on my SVG line](http://stackoverflow.com/questions/11808860/arrow-triangles-on-my-svg-line)_. – Phrogz Aug 04 '12 at 15:51
  • Now Raphael 2.1 has a path attr pair for this, `arrow-start` and `arrow-end`, see https://stackoverflow.com/questions/27372513/raphaeljs-how-to-draw-arrow-heads-at-the-end-of-archs – user56reinstatemonica8 Jun 04 '17 at 10:34

1 Answers1

20

I guess you should use markers for your purpose. See an example here.

Edit:

You need to create a marker in the defs section:

var defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
var marker = document.createElementNS('http://www.w3.org/2000/svg', 'marker');
marker.setAttribute('id', 'Triangle');
marker.setAttribute('viewBox', '0 0 16 16');
marker.setAttribute('refX', '0');
marker.setAttribute('refY', '6');
marker.setAttribute('markerUnits', 'strokeWidth');
marker.setAttribute('markerWidth', '16');
marker.setAttribute('markerHeight', '12');
marker.setAttribute('orient', 'auto');
var path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
marker.appendChild(path); 
path.setAttribute('d', 'M 0 0 L 16 8 L 0 16 z');   
path.setAttribute('stroke', '#000');   
path.setAttribute('stroke-width', '1'); 
path.setAttribute('style', '  marker-start :none;   marker-end :none; ');      

document.getElementById( id_of_svg_placeholder ).getElementsByTagName('svg')[0].appendChild(defs);
defs.appendChild(marker);

and referense it in CSS:

path {marker-start:url("#Triangle")}

or as an attribute:

<path d="..." marker-start="url(#Triangle)" />

Here's the resulting jsfiddle

Spadar Shut
  • 15,111
  • 5
  • 47
  • 54
  • alright, I see how it works now. However, it is not campatible with Raphael, as it uses a tag, rather than an attribute, if you edit your answer somehow, I'll change the down vote to an upvote. OR if you can figure out how to get the markers in here : http://jsfiddle.net/G5mTx/10/ that wolud be awesome – NullVoxPopuli Sep 26 '11 at 14:58
  • 9
    I hope this is what you need http://jsfiddle.net/G5mTx/29/ . Don't be afraid to use native DOM methods. And probably it's Raphael that is not compatible with creating SVG markers, not the other way round. Also, I guess it's not too friendly to downvote someone who offered his help and gave a key to your question. – Spadar Shut Sep 26 '11 at 21:12
  • I can't upvote unless you edit your answer though. =\ that's exactly what I need though! You are awesome! <3 – NullVoxPopuli Sep 26 '11 at 21:16
  • thanks! thas was pretty easy to implement into my new code, too: http://jsfiddle.net/G5mTx/30/ – NullVoxPopuli Sep 26 '11 at 21:32
  • 10
    "it's not too friendly to downvote someone who offered his help" #TrueStory – Necronet Mar 07 '12 at 09:40
  • The order of lines is not good, it should be like this: var path = document.createElementNS('http://www.w3.org/2000/svg', 'path'); THEN multiple lines of path.setAttribute(...); THEN marker.appendChild(path); and THEN defs.appendChild(marker); and LASTLY ....getElementsByTagName('svg')[0].appendChild(defs); – TomoMiha Oct 25 '21 at 09:51