How can I loop through path elements in SVG? - javascript

I am getting TypeError: logo[i].getTotalLength is not a function error while trying to mesure the length of each <path> of the <svg> tag!
I got that error using jquery :
jQuery('#logo').each(function(i) {
console.log( i + ' ====' + jQuery(this).get(0).getTotalLength());
});
So I rewrote the same code in javascript but I still get the same error!
javascript code :
const logo= document.querySelectorAll("#logo");
for (let i=0; i < logo.length; i++)
{
console.log(i," ==== ",logo[i].getTotalLength());
}
Note: in this html code there is only 1 <path> , I removed the others because they are very large!
html code :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body style="background-color: black;">
<svg id="logo" width="80" height="90" viewBox="0 0 80 90" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M32.56 3.24001C41.36 3.24001 49.08 4.96001 55.72 8.40001C62.44 11.84 67.6 16.76 71.2 23.16C74.88 29.48 76.72 36.84 76.72 45.24C76.72 53.64 74.88 61 71.2 67.32C67.6 73.56 62.44 78.4 55.72 81.84C49.08 85.28 41.36 87 32.56 87H3.28V3.24001H32.56ZM31.96 72.72C40.76 72.72 47.56 70.32 52.36 65.52C57.16 60.72 59.56 53.96 59.56 45.24C59.56 36.52 57.16 29.72 52.36 24.84C47.56 19.88 40.76 17.4 31.96 17.4H20.08V72.72H31.96Z" stroke="white" stroke-width="6"/>
</svg>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="app.js"></script>
</body>
</html>
When i removed id="logo" from the <svg> tag and add it to the <path> it work perfectly fine!
So the loop doesn't work properly!

If you want to loop through all the elements with a particular tag name then there's a function that will get all of them: getElementsByTagName.
You were getting the parent <svg> element and there's only one of them. You could iterate through its children and find the path elements but why bother given there's an easier way to do it.
const logo= document.getElementsByTagName("path");
for (let i=0; i < logo.length; i++)
{
console.log(i," ==== ",logo[i].getTotalLength());
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body style="background-color: black;">
<svg id="logo" width="80" height="90" viewBox="0 0 80 90" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M32.56 3.24001C41.36 3.24001 49.08 4.96001 55.72 8.40001C62.44 11.84 67.6 16.76 71.2 23.16C74.88 29.48 76.72 36.84 76.72 45.24C76.72 53.64 74.88 61 71.2 67.32C67.6 73.56 62.44 78.4 55.72 81.84C49.08 85.28 41.36 87 32.56 87H3.28V3.24001H32.56ZM31.96 72.72C40.76 72.72 47.56 70.32 52.36 65.52C57.16 60.72 59.56 53.96 59.56 45.24C59.56 36.52 57.16 29.72 52.36 24.84C47.56 19.88 40.76 17.4 31.96 17.4H20.08V72.72H31.96Z" stroke="white" stroke-width="6"/>
</svg>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="app.js"></script>
</body>
</html>

Related

Unable to change svg colour using jQuery

I'm having trouble changing the colour of an svg image with jquery or vanila javascript. I've tried a couple of things but nothing seems to work, the original colour is black and i can change it if i open the svg image in my IDE and add/change the fill attribute. But not with JS. What am I doing wrong? Other lines of code work fine so it is not a problem with the files or so.
So far i've tried these lines of codes and put id on the img tag aswell as the svg element it self
html:
<img src="import/splash.svg">
JS:
$('#myId').css({fill:"#f8b9d4"});
$("myId").attr("fill", "yellow");
document.getElementById("myId").setAttribute("fill", "#f8b9d4");
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="100%" viewBox="0 0 588 497" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<title>random title</title>
<g>
<path
d="M259.952694,496.613554 C253.376792,496.613554 250.627732,488.109987 250.038987,483.084288 L246.271494,450.855246 C245.492831,444.196255 243.408484,440.818093 240.070679,440.818093 C236.607054,440.818093 232.400376,443.96598 231.070952,445.174331 L199.957676,473.559913 C195.010319,478.077582 191.435117,480.178547 188.70505,480.178547 C187.190455,480.178547 185.884771,479.528079 185.020645,478.350589 C182.383162,474.756395 184.650306,466.661151 185.407603,464.263439 L192.935467,440.450127 C193.543204,438.531958 194.03699,435.934833 192.949711,434.446352 C191.893294,433.002977 189.478964,432.791694 188.135296,432.791694 C187.140602,432.791694 186.411793,432.903271 186.3382,432.91514 L127.318884,443.085236 C118.696618,444.573716 112.519544,442.940424 109.001317,438.313553 C103.842676,431.523993 106.712808,420.883851 106.838629,420.439918 "
id="myId" fill=""></path>
</g>
UPDATE - created a completley new project but the problem is the same. (The div is for testing and working fine)
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="tmo.js"></script>
</head>
<body>
<img src="splash.svg" alt="">
<div id="h"></div>
</body>
</html>
jquery:
$(document).ready(function () {
$('#myId').css({fill:"blue"});
$("#h").text("heasdadasdsadasdsad");
});
SVG file:
<svg width="100%" viewBox="0 0 588 497" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<title>random title</title>
<g>
<path
d="M259.952694,496.613554 C253.376792,496.613554 250.627732,488.109987 250.038987,483.084288 L246.271494,450.855246 C245.492831,444.196255 243.408484,440.818093 240.070679,440.818093 C236.607054,440.818093 232.400376,443.96598 231.070952,445.174331 L199.957676,473.559913 "
id="myId"></path>
</g>
</svg>
I'd say it's because you're using an <img> tag rather than putting the <svg> directly in the HTML.
If you cannot put the <svg> directly in your HTML, embed it using the <object> tag, e.g. like this:
<object id="img" data="test.svg" type="image/svg+xml">Your browsser doesn't support SVG</object>
Then, you can access elements inside the <object> like this:
document.getElementById("img").contentDocument.getElementById("myId").setAttribute("fill", "#f8b9d4");
Your Jquery css works fine. You don't need to have an empty fill="" attribute on the path.
Note: Scroll down on the code snippet to see result, your viewbox is a bit big :)
$('#myId').css({fill:"blue"});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg width="100%" viewBox="0 0 588 497" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<title>random title</title>
<g>
<path
d="M259.952694,496.613554 C253.376792,496.613554 250.627732,488.109987 250.038987,483.084288 L246.271494,450.855246 C245.492831,444.196255 243.408484,440.818093 240.070679,440.818093 C236.607054,440.818093 232.400376,443.96598 231.070952,445.174331 L199.957676,473.559913 C195.010319,478.077582 191.435117,480.178547 188.70505,480.178547 C187.190455,480.178547 185.884771,479.528079 185.020645,478.350589 C182.383162,474.756395 184.650306,466.661151 185.407603,464.263439 L192.935467,440.450127 C193.543204,438.531958 194.03699,435.934833 192.949711,434.446352 C191.893294,433.002977 189.478964,432.791694 188.135296,432.791694 C187.140602,432.791694 186.411793,432.903271 186.3382,432.91514 L127.318884,443.085236 C118.696618,444.573716 112.519544,442.940424 109.001317,438.313553 C103.842676,431.523993 106.712808,420.883851 106.838629,420.439918 "
id="myId"></path>
</g>
</svg>
Try This-
$('#myId').css({fill:"blue"});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<svg width="100%" viewBox="0 0 588 497" version="1.1"
xmlns="http://www.w3.org/2000/svg">
<title>random title</title>
<g>
<path
d="M259.952694,496.613554 C253.376792,496.613554 250.627732,488.109987 250.038987,483.084288 L246.271494,450.855246 C245.492831,444.196255 243.408484,440.818093 240.070679,440.818093 C236.607054,440.818093 232.400376,443.96598 231.070952,445.174331 L199.957676,473.559913 C195.010319,478.077582 191.435117,480.178547 188.70505,480.178547 C187.190455,480.178547 185.884771,479.528079 185.020645,478.350589 C182.383162,474.756395 184.650306,466.661151 185.407603,464.263439 L192.935467,440.450127 C193.543204,438.531958 194.03699,435.934833 192.949711,434.446352 C191.893294,433.002977 189.478964,432.791694 188.135296,432.791694 C187.140602,432.791694 186.411793,432.903271 186.3382,432.91514 L127.318884,443.085236 C118.696618,444.573716 112.519544,442.940424 109.001317,438.313553 C103.842676,431.523993 106.712808,420.883851 106.838629,420.439918 "
id="myId"></path>
</g>
</svg>

Window.getComputedStyle does not show inline style

I have simple html like this:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<svg id="svg" viewBox="0 0 594 600" preserveAspectRatio="xMinYMin meet">
<rect id="rect" fill="#98df8a" style="width: 100px; height: 100px;">
</rect>
</svg>
</body>
</html>
When i use: window.getComputedStyle(document.getElementById('rect')), I get the value of both width and height to be auto and not 100px like what I expected.
Is this how it should be? If so, how can i make it to return 100px ?
I need this function to turn all my styles defined in the external css into inline style attribute for svg elements so that I can export it later.
You could just use document.getElementById('rect').style.height and document.getElementById('rect').style.width and if you want to handle an arbitrary list of styles something like this:
var exportStyleKeys = ['width', 'height'];
var rect = document.getElementById('rect');
var exportStyles = exportStyleKeys.reduce((styles, styleKey) => {
styles[styleKey] = rect.style[styleKey];
return styles;
}, {});
JSFiddle
window.document.getElementById('rect').style.width will return you the inline css width attribute.
Try the blow code
var rect = window.document.getElementById('rect');
console.log(rect.style.width);
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<svg id="svg" viewBox="0 0 594 600" preserveAspectRatio="xMinYMin meet">
<rect id="rect" fill="#98df8a" style="width: 100px; height: 100px;">
</rect>
</svg>
</body>
</html>

SVG translate transform in javascript not working in IE 11

The following code doesn't work in IE 11 (Chrome works fine)
<html>
<head>
<script>
window.onload = function() {document.getElementById("abc").style.transform = "translate(100px,100px)";};
</script>
</head>
<body>
<div>
<svg width="200" height="200">
<g id="abc">
<polygon points="14,7 0,14 0,0"></polygon>
</g>
</svg>
</div>
</body>
For IE you need to set transform as an attribute rather than as a CSS style.
Note that for an attribute, units are not allowed.
<html>
<head>
<script>
window.onload = function() {document.getElementById("abc").setAttribute("transform", "translate(100, 100)")};
</script>
</head>
<body>
<div>
<svg width="200" height="200">
<g id="abc">
<polygon points="14,7 0,14 0,0"></polygon>
</g>
</svg>
</div>
</body>

Avoid stretching slented borders on responsive SVG

Is there a way, possibly without JS, do generate a responsive SVG where the slanted border does not stretch with the width? Please do not reply with "use CSS" because I need to create a complex mask that is simply not possible with CSS alone.
body {padding: 20px}
<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
<svg preserveAspectRatio="none" width="100%" height="60" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350.47 32.42">
<defs><style>.cls-1{fill:#fff;stroke:#231f20;stroke-miterlimit:10;}</style></defs>
<title>test</title>
<polygon class="cls-1" points="0.93 31.91 21.34 0.5 333.39 0.5 349.62 31.91 0.93 31.91"/>
</svg>
</body>
</html>
change preserveAspectRatio to "xMaxYMax" to avoid stretching and height to "100%" let the rectangle grow if needed for large screen
body {padding: 20px}
<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
<svg preserveAspectRatio="xMaxYMax" width="100%" height="100%" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 350.47 32.42">
<defs><style>.cls-1{fill:#fff;stroke:#231f20;stroke-miterlimit:10;}</style></defs>
<title>test</title>
<polygon class="cls-1" points="0.93 31.91 21.34 0.5 333.39 0.5 349.62 31.91 0.93 31.91"/>
</svg>
</body>
</html>

Unable to getElementById within external SVG File

Make sure the svg is an external file for object tag to reference. For some reason I am not able to get the "Layer_1" by id. I can get the svgElem and svgDoc , but not "Layer_1" by its id within the svg file.
(function($) {
$(window).load(function() {
var svgElem = document.getElementById("test-svg"); //returns value
alert("svgElem=" + svgElem); //returns value
var svgDoc = svgElem.contentDocument;
alert("svgDoc = " + svgDoc); //returns value when svg external file
var layer1 = svgDoc.getElementById("Layer_1");
alert("layer1 = " + layer1); //returns null* This is my problem.
});
})(jQuery);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title of the document</title>
</head>
<body>
<div id="container">
<div id="container2">
<object id="test-svg" type="image/svg+xml" data="svg-layer-test.svg">
<!-- PLEASE MAKE THIS SVG AN EXTERNAL DOCUMENT and name file 'svg-layer-test.svg'-->
<!--<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 91.333 70.667" enable-background="new 0 0 91.333 70.667" xml:space="preserve">
<g id="Layer_1">
<text transform="matrix(1 0 0 1 -4.333 68.6665)" font-family="'TimesNewRomanPS-BoldMT'" font-size="100" id="first_date">13</text>
</g>
<g id="Layer_2">
<text transform="matrix(1 0 0 1 -4.333 68.6665)" font-family="'TimesNewRomanPS-BoldMT'" font-size="100">15</text>
</g>
</svg>-->
</object>
</div>
</div>
</body>
</html>

Categories