Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

svg marker does not work in IE9-10

Working first time on svg. I have following svg definition for an 'arrow-like' path

<defs>
    <marker id="start" refX="1" refY="5" markerUnits="userSpaceOnUse" markerWidth="17" markerHeight="11" orient="auto">
        <path id="conditional"   d="M 0 6 L 8 1 L 15 5 L 8 9 L 1 5" fill="white" stroke="black" stroke-width="1" />
        <path id="default" d="M 5 0 L 11 10" fill="white" stroke="black" stroke-width="1" />
    </marker>
    <marker id="end" refX="15" refY="6" markerUnits="userSpaceOnUse" markerWidth="15" markerHeight="12" orient="auto">
        <path id="arrowhead" d="M 0 1 L 15 6 L 0 11z" fill="black" stroke="black" stroke-linejoin="round" stroke-width="2" />
    </marker>
</defs>
<g id="edge">
    <path id="bg_frame" d="M10 50 L210 50" stroke="black" fill="none" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" marker-start="url(#start)" marker-end="url(#end)" />
    <text id="text_name" x="0" y="0" oryx:edgePosition="startTop"/>
</g>

But it does not show arrow at the end of path in IE 9 or IE 10

Does 'triangle' not supported in IE or Problem in the code?

An example here, http://www.w3.org/TR/SVG11/images/painting/marker.svg too does not work in IE.

Help Please, it is the only point my workflow editor has stuck.

Link result

enter image description here

My code's result in FF is:

enter image description here

And code result in IE is(there is no arrow, no square at the end of arrow):

enter image description here

like image 723
Shanta Avatar asked Jul 15 '13 12:07

Shanta


3 Answers

The problem is already reported to Microsoft as xdhmoore wrote in his answer: https://connect.microsoft.com/IE/feedback/details/801938/dynamically-updated-svg-path-with-a-marker-end-does-not-update

There is a fiddle where the problem is shown: http://jsfiddle.net/EEYZZ/

   //if (isIE10 || isIE11) {
       var parent = p1.parentNode;
       parent.removeChild(p1);
       parent.appendChild(p1);
   //}

My workaround is to manuelly remove the node from DOM and add it again, this will update the node as wanted... Don't speak about performance and stuff, but I think currently there is no better way to do it. (http://jsfiddle.net/kaljak/5zTv9/3/)

like image 192
kaljak Avatar answered Sep 22 '22 06:09

kaljak


One problem in IE seems to be that marker inherits the stroke, stroke-width and fill properties (contrary to the standards).

However, this can be worked around by setting the stroke properties explicitly.

Consider the problem with

http://www.w3.org/TR/SVG11/images/painting/marker.svg

By setting the marker stroke="none" and fill="black" the rendering seems fine:

https://codepen.io/anon/pen/qmYzGE

Note: I have tested this only in IE11. My guess is that it will work at least in IE10 as well. Any information on this very welcome.

like image 3
Daniel Avatar answered Sep 24 '22 06:09

Daniel


I was facing the same Problem and it was causing me quite some headache - I really can't understand why Microsoft doesn't fix that. I decided to replace the markers with custom paths which has the nice side-effect that you can e.g. change the fill or the color at runtime using JavaScript.

I create my svg using d3, the edge has class 'edge-path' and the tip has class 'edge-tip'. Both paths are children of an svg:g. The edge itself is a spline, so for rotating the tip I take the slope of the last 10 pixels. This is pretty much the code which is used to update the arrow, works in IE9-11:

edge.select('path.edge-tip')
     // the shape of the tip  
     .attr('d', 'M0,0L10,5L0,10Z')
     // move the tip to the end of the edge and rotate.
     .attr('transform', function(d) {
         var parent = d3.select(this).node().parentNode,
             path = d3.select(parent).select('path.edge-path').node(),
             pathLength = path.getTotalLength(),
             point1 = path.getPointAtLength(Math.max(0, pathLength - 10)),
             point2 = path.getPointAtLength(pathLength),
             vect = { x: point2.x - point1.x, y: point2.y - point1.y }
             l1 = vect.x * vect.x + vect.y * vect.y;
         l1 = Math.sqrt(l1);
         var angle = Math.acos(vect.x / l1);
         angle = 360 * (angle / (2*Math.PI));
         if (vect.y < 0) {
             angle = 360 - angle;
         }
         return 'translate(' + point1.x + ',' + (point1.y - 5) + ') rotate (' + angle +' 0 5)';
    });

Maybe it helps someone :)

like image 2
frow Avatar answered Sep 22 '22 06:09

frow