Sergio C
Sergio C

Reputation: 113

javascript - SVG circle style untidy

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

Answers (3)

Swaroop Deval
Swaroop Deval

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

Chris B.
Chris B.

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

ksav
ksav

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

Related Questions