Tengo un círculo concéntrico en SVG en HTML, pero me gustaría que la mitad inferior se parezca a la mitad superior. La parte inferior tiene los círculos están desalineados.

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>

Soy nuevo en Javascript, modifiqué la configuración pero no pude llegar a la solución.

Gracias de antemano. Perdon por mi inglés.

2
Sergio C 19 oct. 2019 a las 22:28

3 respuestas

La mejor respuesta

El problema es que le das diferentes xstart y xend para tus círculos superior e inferior. El radio también es diferente para el superior y el inferior.

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>
3
Swaroop Deval 19 oct. 2019 a las 20:07

Esto se debe a que está aumentando el ancho de su semicírculo con cada iteración del bucle, independientemente de si está volteando el camino o no. Esto significa que sus círculos verticales siempre serán un paso más anchos que los invertidos, cuando desee que ambos tengan el mismo tamaño. Puede solucionar esto fácilmente manteniendo el mismo ancho para cada conjunto de iteraciones pares / impares:

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>
2
Chris B. 19 oct. 2019 a las 20:06

¿Por qué no solo usas círculos?

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>
2
ksav 19 oct. 2019 a las 20:05