Reputation: 113
I have a concentric circle in SVG in HTML but I would like the bottom half to look like the top half. The bottom has the circles are misaligned.
const svgNs = "http://www.w3.org/2000/svg";
let svg = document.querySelector("svg");
function drawHalfCircle(x, y, r, sweepFlag, width) {
let path = document.createElementNS(svgNs, "path");
let xStart = x - r;
let xEnd = x + r;
let command = `M ${xStart} ${y} A ${r} ${r} 0 0 ${sweepFlag} ${xEnd} ${y}`;
path.setAttribute("d", command);
path.setAttribute("stroke", "#627ca9");
path.setAttribute("fill", "none");
path.setAttribute("stroke-width", width.toString());
svg.appendChild(path);
}
let width = 10;
let nrOfCircles = 1000 / width / 2 - 2;
for(let i = 0; i < nrOfCircles; i++) {
let r = width + i * width;
let sweepFlag = i % 2;
drawHalfCircle(500, 500, r, sweepFlag, width);
}
html, body {
height: 100%;
margin: 0;
}
svg {
position: absolute;
width: 100%;
height: 100%;
}
<svg viewBox="0 0 1000 1000" >
</svg>
I'm new to Javascript, I tweaked the settings but couldn't get to the solution.
Thank you in advance. Sorry my english.
Upvotes: 2
Views: 192
Reputation: 906
Issue is that you give different xstart and xend for your top and bottom circles. Radius is also different for top and bottom one.
const svgNs = "http://www.w3.org/2000/svg";
let svg = document.querySelector("svg");
function drawHalfCircle(x, y, r, sweepFlag, width) {
let path = document.createElementNS(svgNs, "path");
let xStart = x - r;
let xEnd = x + r;
let command = `M ${xStart} ${y} A ${r} ${r} 0 0 ${sweepFlag} ${xEnd} ${y}`;
path.setAttribute("d", command);
path.setAttribute("stroke", "#627ca9");
path.setAttribute("fill", "none");
path.setAttribute("stroke-width", width.toString());
svg.appendChild(path);
}
let width = 10;
let nrOfCircles = 1000 / width / 2 - 2;
for(let i = 0; i < nrOfCircles; i = i+2) { //changes here
let r = width + i * width;
drawHalfCircle(500, 500, r, 0, width); //changes here
drawHalfCircle(500, 500, r, 1, width); //changes here
}
html, body {
height: 100%;
margin: 0;
}
svg {
position: absolute;
width: 100%;
height: 100%;
}
<svg viewBox="0 0 1000 1000" >
</svg>
Upvotes: 3
Reputation: 5763
This is because you're increasing the width of your semi-circle with each iteration of the loop, regardless of whether or not you're flipping the path. This means that your upright circles will always be one step wider than your inverted ones, when you want both to be the same size. You can fix this easily by maintaining the same width for each set of even/odd iterations:
const svgNs = "http://www.w3.org/2000/svg";
let svg = document.querySelector("svg");
function drawHalfCircle(x, y, r, sweepFlag, width) {
let path = document.createElementNS(svgNs, "path");
let xStart = x - r;
let xEnd = x + r;
let command = `M ${xStart} ${y} A ${r} ${r} 0 0 ${sweepFlag} ${xEnd} ${y}`;
path.setAttribute("d", command);
path.setAttribute("stroke", "#627ca9");
path.setAttribute("fill", "none");
path.setAttribute("stroke-width", width.toString());
svg.appendChild(path);
}
let width = 10;
let nrOfCircles = 1000 / width / 2 - 2;
for(let i = 0; i < nrOfCircles; i++) {
let sweepFlag = i % 2;
let r = width + (sweepFlag === 0 ? i : (i-1) ) * width; // Subtract one from iterator used to increment width on odd iterations
drawHalfCircle(500, 500, r, sweepFlag, width);
}
html, body {
height: 100%;
margin: 0;
}
svg {
position: absolute;
width: 100%;
height: 100%;
}
<svg viewBox="0 0 1000 1000" >
</svg>
Upvotes: 2
Reputation: 20840
Why don't you just use circles?
const svgNs = "http://www.w3.org/2000/svg";
let svg = document.querySelector("svg");
function drawFullCircle(x, y, r, width) {
let circle = document.createElementNS(svgNs, "circle");
circle.setAttribute("r", r);
circle.setAttribute("cy", y);
circle.setAttribute("cx", x);
circle.setAttribute("stroke", "#627ca9");
circle.setAttribute("fill", "none");
circle.setAttribute("stroke-width", width.toString());
svg.appendChild(circle);
}
let width = 10;
let nrOfCircles = 50;
for (let i = 0; i < nrOfCircles; i++) {
let r = width + i * width;
drawFullCircle(500, 500, r, 2);
}
html,
body {
height: 100%;
margin: 0;
}
svg {
position: absolute;
width: 100%;
height: 100%;
}
<svg viewBox="0 0 1000 1000">
</svg>
Upvotes: 2