Paankey56
Paankey56

Reputation: 125

How do I remove the old SVG elements and then replace it with a new one?

So I have been working on this code and I have gotten it to work. My problem is that it works perfectly for the first input, but if the user keeps putting in inputs the new picture overlaps the old. I have successfully coded in the ability for the ellipse to be replaced when a new input is given, but I am having trouble with doing the same for all my path and marker elements. My entire code is below (separated into its individual files) what do I need to add in order to replace the old image with the new one?

main.js

function eccentricityChanged(){

  let svg = document.getElementById('diagram');

  let temp = document.getElementById('mytext');
  if (temp) {
    temp.remove();
  }

  let s = 100;
  let omega = 0.5;
  let A = 0.2084558583;
  let B = 0.7915441417;

  let e = document.getElementById('eccentricity').value;
  let formFactor = A * e + B;
  let eccent = Math.sqrt(Math.pow(e, 2)/(1-Math.pow(e,2)));
  let p = (1 + 1/(Math.pow(eccent, 2)))*(1-(1/eccent)*Math.atan(eccent))-(1/3);
  let q = (1/eccent)*(1+3/(Math.pow(eccent, 2)))*Math.atan(eccent)-3/(Math.pow(eccent, 2));
  let omegaStable = Math.sqrt((15/4)*q*(1-(3/5)*formFactor));
  let apperantGravA = Math.pow(1-Math.pow(e,2), -1/6)*(1-(1+p/q)*Math.pow(omegaStable, 2));
  let apperantGravB = Math.pow(1-Math.pow(e,2),1/3)*(1+2*p/q*Math.pow(omegaStable,2));
  let a = Math.pow((1-Math.pow(e,2)),-1/6);
  let b = Math.pow((1-Math.pow(e,2)),1/3);
  let scaleFactor = 150;
  let eqRad = a*scaleFactor;
  let polRad = b*scaleFactor;

  let latitude = [Math.PI/6, Math.PI/4, Math.PI/3];
  let latitudeLength = latitude.length;
  var i;

  for (i of latitude) {
    let rho = (a*Math.cos(i))/Math.sqrt(1-Math.pow(e*Math.sin(i),2));
    let z = -(a*(1-Math.pow(e,2))*Math.sin(i))/Math.sqrt(1-Math.pow(e*Math.sin(i),2));
    let lattGrav = (a* apperantGravA*Math.pow(Math.cos(i),2)+b*apperantGravB*Math.pow(
        Math.sin(i),2))/Math.sqrt(Math.pow(a*Math.cos(i),2)+Math.pow(b*Math.sin(i),2));
    let gravRho =-lattGrav*Math.cos(i)-Math.pow(omegaStable,2)*rho;
    let gravZ = -lattGrav*Math.sin(i);
    let accelCent = Math.pow(omega,2)*rho;
    calculateValues(rho, z, lattGrav, gravRho, gravZ, accelCent, polRad,s);
  }

  makeEllipse(eqRad,polRad);

}

function makeEllipse(eqRad,polRad) {
  let svg = document.getElementById('diagram');

  let temp = document.getElementById('mydiagram');
  if (temp) {
    temp.remove();
  }
  let ellipse = document.createElementNS('http://www.w3.org/2000/svg', 'path');
  ellipse.setAttribute('d', `M 400 100 a ${polRad},${eqRad} 90 1,0 1,0 z`);
  ellipse.style.fill = 'transparent';
  ellipse.style.stroke = 'black';
  ellipse.style.strokeWidth = '5px';
  ellipse.setAttribute('id', 'mydiagram');
  svg.appendChild(ellipse);
}

function calculateValues(rho, z, lattGrav, gravRho, gravZ, accelCent, polRad,s) {
  let rho1 = rho*150 + 400;
  let z1 = z*150 + 100 + polRad;

  let rho2 = rho1 + s*gravRho;
  let z2 = z1- s*gravZ

  let rho3 = rho2 + s*accelCent;
  console.log(rho1, rho2, rho3, z1,z2);

  gravityVector(rho1, z1, rho2, z2, rho3, gravRho, gravZ, s, polRad);
  accelCentVector(rho1, z1, rho2, z2, rho3, gravRho, gravZ, s, polRad);
  apperantGravVector(rho1, z1, rho2, z2, rho3, gravRho, gravZ, s, polRad);
}

Vectors.js

function gravityVector(rho1, z1, rho2, z2, rho3, gravRho, gravZ, s, polRad) {
    let svg = document.getElementById('diagram');

    let marker= document.createElementNS('http://www.w3.org/2000/svg',
        'marker');
    marker.setAttribute('id', 'triangle');
    marker.setAttribute('viewBox', '0 0 10 10');
    marker.setAttribute('refX', '0');
    marker.setAttribute('refY', '5');
    marker.setAttribute('markerUnits', 'strokeWidth');
    marker.setAttribute('markerWidth', '10');
    marker.setAttribute('markerHeight', '8');
    marker.setAttribute('orient', 'auto');

    let path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
    path.setAttribute('d', `M ${rho2} ${z2} l 5 0 l -5 10 l -5 -10 z`);
    path.style.stroke = 'green';
    path.style.strokeWidth = '5px';
    svg.appendChild(path);

    let arrow = document.createElementNS('http://www.w3.org/2000/svg', 'path');
    arrow.setAttribute('d', `M ${rho1},${z1} L ${rho2} ${z2}`);
    arrow.setAttribute('id', 'gravPath')
    arrow.style.stroke = 'black';
    arrow.style.strokeWidth = '2px';
    svg.appendChild(arrow);
    arrow.setAttributeNS('marker-end', 'triangle', 'void');
}

function accelCentVector(rho, z, rho2, z2, rho3, gravRho, gravZ, s, polRad) {
    let svg = document.getElementById('diagram');

    let marker= document.createElementNS('http://www.w3.org/2000/svg',
        'marker');
    marker.setAttribute('id', 'triangle');
    marker.setAttribute('viewBox', '0 0 10 10');
    marker.setAttribute('refX', '0');
    marker.setAttribute('refY', '5');
    marker.setAttribute('markerUnits', 'strokeWidth');
    marker.setAttribute('markerWidth', '10');
    marker.setAttribute('markerHeight', '8');
    marker.setAttribute('orient', 'auto');

    let path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
    path.setAttribute('d', `M ${rho3} ${z2} l 5 0 l -5 10 l -5 -10 z`);
    path.style.stroke = 'black';
    path.style.strokeWidth = '5px';
    svg.appendChild(path);

    let arrow = document.createElementNS('http://www.w3.org/2000/svg', 'path');
    arrow.setAttribute('d', `M ${rho2},${z2} L ${rho3} ${z2}`);
    arrow.setAttribute('id', 'accelCentPath');
    arrow.style.stroke = 'red';
    arrow.style.strokeWidth = '2px';
    svg.appendChild(arrow);
    arrow.setAttributeNS('marker-end', 'triangle', 'void');
}

function apperantGravVector(rho, z, rho2, z2, rho3, gravRho, gravZ, s, polRad) {
    let svg = document.getElementById('diagram');

    let marker= document.createElementNS('http://www.w3.org/2000/svg',
        'marker');
    marker.setAttribute('id', 'triangle');
    marker.setAttribute('viewBox', '0 0 10 10');
    marker.setAttribute('refX', '0');
    marker.setAttribute('refY', '5');
    marker.setAttribute('markerUnits', 'strokeWidth');
    marker.setAttribute('markerWidth', '10');
    marker.setAttribute('markerHeight', '8');
    marker.setAttribute('orient', 'auto');

    let path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
    path.setAttribute('d', `M ${rho3} ${z2} l 5 0 l -5 10 l -5 -10 z`);
    path.style.stroke = 'black';
    path.style.strokeWidth = '5px';
    svg.appendChild(path);

    let arrow = document.createElementNS('http://www.w3.org/2000/svg', 'path');
    arrow.setAttribute('d', `M ${rho},${z} L ${rho3} ${z2}`);
    arrow.style.stroke = 'blue';
    arrow.style.strokeWidth = '2px';
    svg.appendChild(arrow);
    arrow.setAttributeNS('marker-end', 'triangle', 'void');
}

index.html

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>CS 5890</title>
        <script src="https://d3js.org/d3.v5.min.js"></script>
        <style>
          rect {
            fill: #9f009f;
            stroke-width: 0;
          }
          polyline {
            stroke: #00ff00;
            fill: none;
            stroke-width: 3;
          }
          line {
            stroke: #00ff00;
            fill: none;
            stroke-width: 3;
          }
          path {
            stroke: #0000ff;
            fill: #0000ff;
            stroke-width: 0;
          }
          circle {
            stroke-width: 0;
            fill: #009900;
          }
          text {
            font-size: 18px;
          }
        </style>
    </head>
    <body id="body">
      Eccentricity: <input id="eccentricity" onchange="eccentricityChanged()"></input>
      <p>Enter a value between 0 and 1 for the Eccentricity</p>

      <br>
      <svg width="800" height="800" id="diagram">
      </svg>
      <g id="diagram-elements">
          <path id =''>
      </g>
      <script src="Vectors.js"></script>
      <script src="main.js"></script>
    </body>
</html>

Upvotes: 1

Views: 2256

Answers (2)

tex
tex

Reputation: 2766

I generally use a container element (<g>) (or several) for this kind of operation. Some advantages to using a container are that you can rotate, hide, scale, move and transform the container, and all of its children will rotate, hide, scale, move and transform with it. Additionally, this should be faster than looping through the children, removing each one, individually.

In your routine, you'll want to remove the container element, if it exists, then add it and append all of your children to it. The next time your routine runs, you'll remove and recreate the container element, then append the children to it, etc.

Given your code, I'd add something like the following at about line 9 of eccentricityChanged in main.js:

  temp = document.getElementById("container");
  if (temp) {
    temp.remove();
  }
  let container = document.createElementNS("http://www.w3.org/2000/svg", "g");
  container.setAttribute("id", "container");
  svg.appendChild(container);

Then, in Vectors.js, I'd append each element you create to this container element, rather than to the outer svg document, e.g.:

  let container = document.getElementById("container");

  // ...

  container.appendChild(path);

Here's a full, working example.

Upvotes: 2

Dimitri Lavren&#252;k
Dimitri Lavren&#252;k

Reputation: 4879

You need to remove all child elements of your svg element, this question has already been answered here: Remove all child elements of a DOM node in JavaScript

In your case you should update your eccentricityChanged() function:

function eccentricityChanged(){
  let svg = document.getElementById('diagram');
  // remove all child nodes of the svg element
  while (svg.firstChild !== null) {
    svg.removeChild(svg.firstChild);
  }
  // ...
}

Upvotes: 0

Related Questions