javascript - SVG circle style untidy

Viewed 156

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.

3 Answers

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>

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>

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>

Related