I am working with a svg element which is following
<svg class="layer1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 150">
<rect class="bg" id="bg" width="150" height="150" fill="#e6e6e6"></rect>
<circle class="circ0" id="circ0" cx="75" cy="75" r="72" fill="none" stroke="blue" stroke-linecap="round" stroke-linejoin="round"></circle>
<circle class="circ1" id="circ1" cx="75" cy="75" r="69" fill="none" stroke="green" stroke-linecap="round" stroke-linejoin="round"></circle>
<circle class="circ2" id="circ2" cx="75" cy="75" r="66" fill="none" stroke="red" stroke-linecap="round" stroke-linejoin="round"></circle>
<script href="index.js"></script>
</svg>
I want to reverse the order of these circles with javascript, which I am currently doing by this way
const svg = document.querySelector("svg");
var x = document.querySelectorAll("[class^='circ']");
var bucket = [];
x.forEach((a, i) => {
bucket.push(a)
});
bucket.reverse();
x.forEach(
(a, i) => a.parentNode.removeChild(a)
);
bucket.forEach(
(a, i) => {
a.setAttribute("class", 'circ' + [i]);
a.setAttribute("id", "circ" + [i]);
svg.appendChild(a);
}
)
<svg class="layer1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 150 150">
<rect class="bg" id="bg" width="150" height="150" fill="#e6e6e6"></rect>
<circle class="circ0" id="circ0" cx="75" cy="75" r="72" fill="none" stroke="blue" stroke-linecap="round" stroke-linejoin="round"></circle>
<circle class="circ1" id="circ1" cx="75" cy="75" r="69" fill="none" stroke="green" stroke-linecap="round" stroke-linejoin="round"></circle>
<circle class="circ2" id="circ2" cx="75" cy="75" r="66" fill="none" stroke="red" stroke-linecap="round" stroke-linejoin="round"></circle>
<script href="index.js"></script>
</svg>
Is there a better way of doing this?
append(child) by itself moves DOM Nodes. So your code can be simplified.
But for complexer SVG you probably want to swap DOM positions, because there could be other Elements in between you don't want to affect.
appendappend was not available in Internet Explorer, that is why you see most posts using appendChild.replaceWith after , before etc.<svg viewBox="0 0 10 10" style="height:200px">
<style>
text { font-size: 2px }
[y="3"]{ fill:yellow }
.first { stroke: black; stroke-width: 0.5 }
</style>
<rect class="bg" id="bg" width="10" height="10" fill="grey"></rect>
<circle class="first" id="c0" cx="2" cy="5" r="2" fill="red" />
<text x="0" y="3">R</text>
<circle class="second" id="c1" cx="4" cy="5" r="3" fill="green" />
<text x="1" y="3">G</text>
<circle class="last" id="c2" cx="6" cy="5" r="4" fill="blue" />
<text x="2" y="3">B</text>
<text x="1" y="6">Click Me!</text>
</svg>
<script>
let svg = document.querySelector("svg");
function append() {
[...svg.querySelectorAll("circle")]
.reverse().forEach((c, i) => {
c.parentNode.append(c);
c.setAttribute("class", c.id = 'c' + i);
});
}
function swap() {
function swapElements(e1, e2) {
let {id,previousSibling,className:{baseVal:c2}} = e2;
e1.after(e2); // put e2 after e1
e2.id = e1.id; e2.setAttribute("class", e1.getAttribute("class"));
previousSibling.after(e1); // put e1 after where e2 WAS
e1.id = id; e1.setAttribute("class", c2);
}
let circles = [...svg.querySelectorAll("circle")];
while (circles.length) {
let c1 = circles.shift();
if (circles.length) swapElements(c1, circles.pop())
}
}
svg.onclick = (e) => (e.ctrlKey && append()) || swap();
</script>