2

I am having a hard time understanding why my svg and circle elements that are created dynamically are not appearing on the page. I'd like to ask why it is doing this and how to fix this problem.

EDITED: This is the function that creates the svg and circle elements dynamically:

function createSvgCircle() {
  const svgDiv = document.createElement("svg");
  const circle = document.createElement("circle");
    
  setAttribute(svgDiv, {
    height: "100",
    width: "100"
  });
    
  setAttribute(circle, {
    cx: "50",
    cy: "50",
    r: "40"
  });
    
  svgDiv.appendChild(circle);
  return svgDiv;
}
    
function setAttribute(el, attrs) {
  for (let key in attrs) {
    el.setAttribute(key, attrs[key]);
  }
}

For clarity, here is the basic HTML structure, I am trying to emulate Twitter fleet/Instagram stories:

<div id="fleets">
  <div class="allFleets">
     <div class="story">
        <img src="" />
        <svg height="100" width="100">
            <circle cx="50" cy="50" r="40"></circle>
        </svg>
     </div>
  </div>
  <div class="allFleets">
     <div class="story">
        <img src="" />
        <svg height="100" width="100">
            <circle cx="50" cy="50" r="40"></circle>
        </svg>
     </div>
  </div>
  <div class="allFleets">
     <div class="story">
        <img src="" />
        <svg height="100" width="100">
            <circle cx="50" cy="50" r="40"></circle>
        </svg>
     </div>
  </div>
</div>

Now the img elements appear fine, but when I click on the svg elements in the Inspect window's HTML, they seem to be hidden somewhere and I can't seem to understand why.

For reference, I have also included a red circle on the page, and this one shows up.

I've tried to remove the width and height from their parent elements (.story, allFleets), but the problem still persists.


Complete code

HTML:

<!DOCTYPE html>
<html>
  <head>
    <title>Parcel Sandbox</title>
    <meta charset="UTF-8" />
  </head>

  <body>
    <div id="app">
      <h1>Fleets</h1>
      <div id="fleets"></div>
    </div>

    <script src="src/index.js"></script>
  </body>
</html>

Fleets.json

{
  "fleets": [
    {
      "name": "Lauren",
      "avatar": "https://cdn3.iconfinder.com/data/icons/design-n-code/100/272127c4-8d19-4bd3-bd22-2b75ce94ccb4-512.png"
    },
    {
      "name": "Guy",
      "avatar": "https://cdn3.iconfinder.com/data/icons/design-n-code/100/272127c4-8d19-4bd3-bd22-2b75ce94ccb4-512.png"
    },
    {
      "name": "Nikki",
      "avatar": "https://cdn3.iconfinder.com/data/icons/design-n-code/100/272127c4-8d19-4bd3-bd22-2b75ce94ccb4-512.png"
    },
    {
      "name": "Chikako",
      "avatar": "https://cdn3.iconfinder.com/data/icons/design-n-code/100/272127c4-8d19-4bd3-bd22-2b75ce94ccb4-512.png"
    },
    {
      "name": "Taishi",
      "avatar": "https://cdn3.iconfinder.com/data/icons/design-n-code/100/272127c4-8d19-4bd3-bd22-2b75ce94ccb4-512.png"
    }
  ]
}

JS

import "./styles.css";
/*
create an api with objects
fetch them

display them

when I click on one fleet, it grays out and stays at the same place

*/

async function fleetsWork(node) {
  // need to remember src
  const promise = await fetch("./src/fleets.json");
  const fleetsJson = await promise.json();
  const fleets = fleetsJson.fleets;

  // display fleets
  displayFleets(node, fleets);

  // gray out function
}

const displayFleets = (node, fleets) => {
  // const allFleets = document.createElement("div");
  // allFleets.classList.add("allFleets");

  fleets.forEach((fleet) => {
    const { name, avatar } = fleet;
    const allFleets = document.createElement("div");
    allFleets.classList.add("allFleets");

    // const fleetDiv = document.createElement("div");
    // fleetDiv.classList.add("fleetDiv");
    // console.log(avatar);
    // fleetDiv.style.backgroundImage = `url(${avatar})`;

    const story = document.createElement("div");
    const imgDiv = document.createElement("img");
    const svgCircle = createSvgCircle();
    console.log(svgCircle);

    imgDiv.setAttribute("src", avatar);

    imgDiv.setAttribute("src", avatar);

    story.classList.add("story");
    imgDiv.classList.add("imgDiv");

    story.appendChild(imgDiv);
    story.appendChild(svgCircle);

    // story.appendChild(imgDiv);

    const title = document.createElement("div");
    title.classList.add("title");
    title.innerText = name;

    // fleetContainer.appendChild(story);
    // fleetContainer.appendChild(title);
    allFleets.appendChild(story);
    allFleets.appendChild(title);
    node.append(allFleets);
  });

  // node.appendChild(allFleets);
};

function createSvgCircle() {
  const svgDiv = document.createElement("svg");
  const circle = document.createElement("circle");

  setAttribute(svgDiv, {
    height: "100",
    width: "100"
  });

  setAttribute(circle, {
    cx: "50",
    cy: "50",
    r: "40"
  });

  svgDiv.appendChild(circle);
  return svgDiv;
}

function setAttribute(el, attrs) {
  for (let key in attrs) {
    el.setAttribute(key, attrs[key]);
  }
}

const fleets = document.querySelector("#fleets");
fleetsWork(fleets);

CSS:

body {
  font-family: sans-serif;
}

#fleets {
  display: flex;
}

.allFleets {
  display: flex;
  width: 100%;
  /* height: 300px; */
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.title {
  position: relative;
  /* bottom: -120%; */
  text-align: center;
}

.story {
  /* position: relative;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 100px;
  height: 100px;
  overflow: hidden;
  margin-left: 20px; */
  position: relative;
  width: 100px;
  height: 100px;
  border-radius: 50%;
  margin-left: 20px;
}

.story img {
  border-radius: 50%;
  width: 70px;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  /* border: 1px solid #8a3ab8; */
  /* animation: loading 4500ms ease-in-out infinite alternate; */
}

svg {
  fill: none;
  stroke: #8a3ab8;
  stroke-width: 3px;
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
  stroke-linecap: round;
  /*   alternate is to go backward after
  going forward */
  /* animation: loading 4500ms ease-in-out infinite alternate; */
}

@keyframes loading {
  /*   when animation is 100% complete */
  100% {
    stroke: #cd476b;
    stroke-dasharray: 10;
    transform: rotate(200deg);
  }
}

/* .story .imgDiv {
  width: 70px;
  border-radius: 50%;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.story svg {
  fill: none;
  stroke: #8a3ab8;
  stroke-width: 3px;
  stroke-dasharray: 1;
  stroke-dashoffset: 0;
  stroke-linecap: round;
  animation: loading 4500ms ease-in-out infinite alternate;
}

@keyframes loading {
  100% {
    stroke: #cd476b;
    stroke-dasharray: 10;
    transform: rotate(200deg);
  }
} */

/* .fleetDiv {
  animation: loading 4500ms ease-in-out infinite alternate;
  border: 1px solid #8a3ab8;
  border-radius: 50%;
  width: 100%;
  height: 100%;
}

@keyframes loading {
  100% {
    stroke: #cd476b;
    stroke-dasharray: 10;
    transform: rotate(200deg);
  }
} */
  • 3
    I clicked on your sandvox link, and i can see the red circle. – Adriano Feb 07 '21 at 22:44
  • Yes that is there as a reference. I just took it away. What I meant is the circles that are created dynamically in Javascript with the `createSvgCircle()` function – Heymanyoulookkindacool Feb 07 '21 at 22:53
  • 1
    You can't use `document.createElement` to create elements that reside inside an svg image. Look into `document.createElementNS` – enhzflep Feb 07 '21 at 22:56
  • Here's an example of use for the version of `createElement` that accepts a namespace as a parameter, which you need to do with svgs. https://stackoverflow.com/questions/3492322/javascript-createelementns-and-svg – enhzflep Feb 07 '21 at 23:01
  • Thank you. Why does `createElement` not work? I guess it confuses me when I inspect and see the tag is on the page. Furthermore, do I only need to do `document.createElementNS` with both the `svg` and `circle` tag, or is it just for `svg`? – Heymanyoulookkindacool Feb 07 '21 at 23:13
  • You need to do it with all the elements that belong to the svg namespace, i.e. for all SVGElements (not only SVGSVGElement). This is because createElement forces the HTML namespace in HTMLDocuments and a `null` namespace in non HTML documents. – Kaiido Feb 08 '21 at 01:59

0 Answers0