AngularJS not rendering SVG correctly - javascript

I have a directive that should append a SVG element to the directive element
.directive('aSvg', function ($compile) {
return {
restrict: 'E',
replace: true,
link: function (scope, element, attrs) {
var svgTag = angular.element('<svg viewBox="0 0 4000 2000" version="1.1"><defs><marker id="StartMarker" viewBox="0 0 12 12" refX="12" refY="6" markerWidth="3" markerHeight="3" stroke="green" stroke-width="2" fill="none" orient="auto"><circle cx="6" cy="6" r="5"></circle></marker><marker id="MidMarker" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="strokeWidth" markerWidth="3" markerHeight="3" stroke="lightblue" stroke-width="2" fill="none" orient="auto"><path d="M 0 0 L 10 10 M 0 10 L 10 0"></path></marker><marker id="EndMarker" viewBox="0 0 10 10" refX="5" refY="5" markerUnits="strokeWidth" markerWidth="3" markerHeight="3" stroke="red" stroke-width="2" fill="none"><rect x="0" y="0" width="10" height="10"></rect></marker></defs><path d="M 200 250 L 700 100 L 900 350 L 1200 400 L 1300 200 L 1700 680 L 2200 680 L 2600 400" fill="none" stroke="black" stroke-width="50" marker-start="url(#StartMarker)" marker-mid="url(#MidMarker)" marker-end="url(#EndMarker)"></path><path d="M 1000 750 S 2000 750 2500 1250 S 1200 1000 1300 1400 S 1700 1480 1900 1200" fill="none" stroke="tomato" stroke-width="50" marker-start="url(#StartMarker)" marker-mid="url(#MidMarker)" marker-end="url(#EndMarker)"></path></svg>');
$compile(svgTag)(scope);
angular.element(svtTag).appendTo(element[0]);
}
};
});
And in html I have the directive as an element:
<body>
<div>
<a-svg></a-svg>
</div>
</body>
However the SVG is not rendering correctly, only the 2 lines (black and orange) appear but there are no markers rendered. The SVG used in the example seems to be correct, because it renders correctly if I save it to a file, but for some reason it's not working in AngularJS.
What am I missing here?
Thanks in advance.
Edit 1: I was using AngularJS v1.2.20, I tried with v1.3.0 but still have the same problem.

After more researching I found out that the problem was in Angular routing, more specifically in the <base href='/'> tag that was messing around with the links defined in the SVG markers.
I solved my problem by changing the url in the markers attributes of each path (note the /myroute in the marker-start, marker-mid and marker-end attributes):
<path d="M 200 250 L 700 100 L 900 350 L 1200 400 L 1300 200 L 1700 680 L 2200 680 L 2600 400" fill="none" stroke="black" stroke-width="50" marker-start="url(/myroute#StartMarker)" marker-mid="url(/myroute#MidMarker)" marker-end="url(/myroute#EndMarker)"></path>
For more details, I suggest reading the accepted answer for the question here.

Related

Simplify SVG (Vector Graphics) Path

Input is below:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="800pt" height="600pt" viewBox="0 0 800 600">
<g enable-background="new">
<path style="fill:none;stroke-width:0.074;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(50.19989%,50.19989%,50.19989%);stroke-opacity:1;stroke-miterlimit:10;" d="M 110.949219 265.421875 L 109.730469 265.691406 L 108.699219 266.410156 L 108.011719 267.460938 L 107.78125 268.679688 " transform="matrix(1,0,0,-1,0,600)"/>
<path style="fill:none;stroke-width:0.074;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(50.19989%,50.19989%,50.19989%);stroke-opacity:1;stroke-miterlimit:10;" d="M 111.050781 268.679688 L 111.050781 265.421875 " transform="matrix(1,0,0,-1,0,600)"/>
<path style="fill:none;stroke-width:0.074;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(50.19989%,50.19989%,50.19989%);stroke-opacity:1;stroke-miterlimit:10;" d="M 110.949219 268.679688 L 110.949219 265.421875 " transform="matrix(1,0,0,-1,0,600)"/>
</g>
</svg>
Expected Output is below:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="800pt" height="600pt" viewBox="0 0 800 600">
<g enable-background="new">
<path transform="matrix(1,0,0,-1,0,600)" stroke-width="0.074" stroke-linecap="round" stroke-linejoin="round" fill="none" stroke="#929292" d="M 110.95 265.42 L 109.73 265.69 L 108.7 266.41 L 108.01 267.46 L 107.78 268.68 "/>
<path transform="matrix(1,0,0,-1,0,600)" stroke-width="0.074" stroke-linecap="round" stroke-linejoin="round" fill="none" stroke="#929292" d="M 111.05 268.68 L 111.05 265.42 "/>
<path transform="matrix(1,0,0,-1,0,600)" stroke-width="0.074" stroke-linecap="round" stroke-linejoin="round" fill="none" stroke="#929292" d="M 110.95 268.68 L 110.95 265.42 "/>
</g>
</svg>
This is about simplifying and beautifying SVG path. I would like the expected output to have the elements of path transform, stroke-width, stroke-linecap, stroke-linejoin, fill stroke and d (rounded to 2 decimals for simplicity).
I have tried let svg_object_alt=document.querySelector('svg').outerHTML;, to convert svg as a string to be read and I am not sure how to extract all the information from it, to be formatted to the expected output? I would really appreciate any help I can obtain :)
I think that the stroke-colour can just hardcode the code number (#929292) into it instead of using the rgb colour :)
you can use that...
const mySvg_Paths = document.querySelectorAll('#my-svg > g > path');
for ( let attr of mySvg_Paths[2].attributes )
{
console.log(attr.name,'-->\n', attr.value);
}
// or
// console.log( 'outerHTML -->\n', mySvg_Paths[2].outerHTML );
// console.log( 'path.d -->\n', mySvg_Paths[2].getAttribute('d'));
#my-svg {
width : 800pt;
height : 600pt;
background : lightgreen;
}
#my-svg path {
fill : none;
stroke-width : 0.074;
stroke-linecap : round;
stroke-linejoin : round;
stroke : rgb(50.19989%, 50.19989%, 50.19989%);
stroke-opacity : 1;
stroke-miterlimit : 10;
}
<svg id="my-svg" viewBox="0 0 800 600">
<g enable-background="new">
<path
d="M 110.949219 265.421875 L 109.730469 265.691406 L 108.699219 266.410156 L 108.011719 267.460938 L 107.78125 268.679688 "
transform="matrix(1,0,0,-1,0,600)"/>
<path
d="M 111.050781 268.679688 L 111.050781 265.421875 "
transform="matrix(1,0,0,-1,0,600)" />
<path
style="fill:none;stroke-width:0.074;stroke-linecap:round;stroke-linejoin:round;stroke:rgb(50.19989%,50.19989%,50.19989%);stroke-opacity:1;stroke-miterlimit:10;"
d="M 110.949219 268.679688 L 110.949219 265.421875 "
transform="matrix(1,0,0,-1,0,600)"/>
</g>
</svg>
then, you can have a look to -> Use RegEx to parse a string with complicated delimiting
specialy this function:
function parseData(pathData)
{
var pieces = pathData.match(/([a-z]+[-.,\d ]*)/gi), i;
/* now parse each piece into its own array */
for (i=0; i<pieces.length; i++)
pieces[i] = pieces[i].match(/([a-z]+|-?[.\d]*\d)/gi);
return pieces;
}

setAttribute smooth transition

I trying to recreate this smil animation with pure javascript
<svg viewBox="0 0 600 600">
<path id="foo" d="M10 10 C 20 20, 40 20, 50 10" stroke="black" fill="black">
<animate
attributeName="d" to="M500 500 C 20 20, 40 20, 50 10"
dur="5s" repeatCount="indefinite" />
</path>
</svg>
The problem here is when I use setAttribute to recreate the animation on click
the animation is sudden
var path = document.getElementById('foo');
path.addEventListener("click", function(){path.setAttribute('d','M500 500 C 20 20, 40 20, 50 10');});
and I can't figure out how to make it smooth like the smil
Is there a way to make it in pure js ?
You can begin an animation on a click event.
<svg viewBox="0 0 600 600">
<path id="foo" d="M10 10 C 20 20, 40 20, 50 10" stroke="black" fill="black">
<animate
attributeName="d" to="M500 500 C 20 20, 40 20, 50 10"
dur="5s" begin="0s;foo.click" repeatCount="indefinite" />
</path>
</svg>

Svg path not closing correctly

I'm trying to create a bridge-like shape with an svg using javascript. With the following html I get the overall shape, but the close path is wrong:
<svg height="897" width="414" xmlns:xlink="http://www.w3.org/1999/xlink" viewbox="0 0 414 897">
<path stroke-width="3" stroke="blue" style="fill:transparent; fill-opacity: 1"
d="M 0 0 V 207 H 30
M 30 207 q 0 -177 177 -177
M 207 30 q 177 0 177 177
H 414 V 0 H 0 z">
</path>
</svg>
This produces the following shape:
It is closing in a strange way which means that it isn't filling correctly. The strange vertical line from the top of the arch to the top left shouldn't be there. How do I get it to close properly and fill properly?
The path will close from your last point to the last declared M. You can fix this by removing all the M calls except the first one. Since you are making a continuous line you don't need to move to a new point every time.
<svg height="897" width="414" xmlns:xlink="http://www.w3.org/1999/xlink" viewbox="0 0 414 897">
<path stroke-width="3" stroke="blue" style="fill:transparent; fill-opacity: 1"
d="M 0 0 V 207 H 30
q 0 -177 177 -177
q 177 0 177 177
H 414 V 0 H 0 z">
</path>
</svg>

SVG Patch is not cleared

Thanks for advance,
i have used the below code with (MoveTo Lineto),
<svg height="200" width="500">
<path fill='none' stroke-width="30" stroke="black" d="M 100 63.125 L 254 63.125 L 254 117.5 L 418 117.5"/>
</svg>
it's shown fine but when i use same with(MoveTo Lineto MoveTo)
<svg height="200" width="500">
<path fill='none' stroke-width="30" stroke="black" d="M 100 63.125 L 254 63.125 L 254 117.5 M 254 117.5 L 418 117.5">
</svg>
.5 pixel is vary check the attached image.
Why that difference? and how to solve?
Sample:
http://jsfiddle.net/3t8rspd1/1/
Please minus the half the stroke width from x position.
you will get the correct path.
eg. if stroke width is 20 mean minus the 10 from second MoveTo.
calculation 254-(storkeWidth/2) = 244. if strokeWidth is 20.
<svg height="200" width="500">
<path fill='none' stroke-width="20" stroke="black" d="M 100 63.125 L 254 63.125 L 254 117.5 M 244 117.5 L 418 117.5"/>
</svg>
Fiddle
stroke-linejoin
<svg height="200" width="500">
<path fill='none' stroke-width="30" stroke-linejoin="round" stroke="black" d="M 100 63.125 L 254 63.125 L 254 117.5 L 418 117.5"/>
</svg>

How to animate changing path lengths (line) with markers in svg

I have this svg path:
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width='500' height='500'>
<defs id="def">
<marker orient="auto" refY="0.0" refX="-3" id="Arrow2Mend" style="overflow:visible;">
<path id="path3900" style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;" d="M -15 -5 L 0 0 L -15 5 z" transform="scale(0.5)"></path>
</marker>
</defs>
<path style="fill:none;stroke:#000000;stroke-width:2.58384609;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;marker-end:url(#Arrow2Mend)" d="m 189,100.09448 200,0" id="arrowline"></path></svg>
I want to be able to increase and decrease the length of the "#arrowline" path, with an animation, keeping the arrowhead also in the correct place while animating. I tried various methods but they were either too complicated for implementing or didn't work. Probably I am missing something. Any help appreciated. Thank you.
I don't know what you mean by "correct" - do you mean the following?
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width='500px' height='500px'>
<defs id="def">
<marker orient="auto" refY="0.0" refX="-3" id="Arrow2Mend" style="overflow:visible;">
<path id="path3900" style="fill-rule:evenodd;stroke-width:0.62500000;stroke-linejoin:round;" d="M -15 -5 L 0 0 L -15 5 z" transform="scale(0.5)"></path>
</marker>
</defs>
<path style="fill:none;stroke:#000000;stroke-width:2.58384609;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;marker-end:url(#Arrow2Mend)" d="m 10 10 l200,0" id="arrowline">
<animate attributeName="d" from="m 10 10 l200,0" to="m 10 10 l400,0" dur="1s" repeatCount="indefinite"/>
</path>
</svg>

Categories

Resources