Radar Chart with Optional Animation

by teknohippy

HTML

<link
      href="https://fonts.googleapis.com/css2?family=Roboto:wght@600&display=swap"
      rel="stylesheet"
    />

    <div id="chart1-container" class="chart-container">
      <svg id="radar-chart-1" width="600" height="500"></svg>
    </div>

    <div id="chart2-container" class="chart-container">
      <svg id="radar-chart-2" width="600" height="500"></svg>
    </div>

    <div id="chart3-container" class="chart-container">
      <svg id="radar-chart-3" width="600" height="500"></svg>
    </div>

CSS

body {
        position: relative;
      }

      .chart-container {
        position: relative;
        width: 600px;
        height: 500px;
      }

      .label {
        position: absolute;
        padding: 7px 12px;
        background-color: #f2f6fd;
        color: #354c91;
        border-radius: 12px;
        font-family: "Roboto", sans-serif;
        font-size: 13px;
        font-weight: 500;
        text-align: center;
        white-space: nowrap;
        transform: translate(-50%, -50%);
      }

JavaScript

const width = 600
      const height = 500
      const centerX = width / 2
      const centerY = height / 2
      const maxRadius = 332 /2
      const innerRadius = 40
      const stepInRadius = 35
      const minScore = 0
      const maxScore = 10
      const numLevels = 5
      
      const rotationOffset = -Math.PI / 2
      const labelOffset = 15

      const labels = [
        "Label 1",
        "Label 2",
        "Label 3",
        "Label 4",
        "Label 5",
        "Label 6",
      ]

      const numAxes = labels.length
      const angleStep = (2 * Math.PI) / numAxes

      function calculatePoint(angle, radius) {
        return {
          x: centerX + radius * Math.cos(angle),
          y: centerY + radius * Math.sin(angle),
        }
      }

      function mapScoreToRadius(score) {
        return (
          innerRadius +
          ((score - minScore) * (maxRadius - innerRadius)) /
            (maxScore - minScore)
        )
      }

      function drawRadarChart(
        containerId,
        svgId,
        dataSets,
        duration = 400,
        delay = 500,
      ) {
        const container = document.getElementById(containerId)
        const svg = document.getElementById(svgId)
        svg.innerHTML = "" // Clear previous chart if any

        // Draw background levels
        for (let level = numLevels; level >= 0; level--) {
          const levelRadius =
            innerRadius + (level / (numLevels)) * (maxRadius - innerRadius)
          let levelPathData = ""

          for (let i = 0; i < numAxes; i++) {
            const angle = i * angleStep + rotationOffset
            const point = calculatePoint(angle, levelRadius)
            levelPathData += `${i === 0 ? "M" : "L"} ${point.x} ${point.y} `
          }
          levelPathData += "Z"

          const levelPath = document.createElementNS(
            "http://www.w3.org/2000/svg",
            "path",
          )
       ...