Search code examples
angularionic-frameworkchart.jsng2-charts

Can one fill the background of the Axis of a radar Chart?


Can I fill the Background of a Radar Chart like in the picture below?

I'm Using Chart.js version 3.9.

enter image description here

My code for now looks like this:


   this.chart = new Chart(spiderChart as ChartItem, {
      type: 'radar',
      data: this.data,
      options: {
        scales: {
          r: {
            ticks: {
              backdropColor: 'rgba(0,0,0,0.01)',
            },
            angleLines: {
              display: true,
              color: 'rgba(255,255,255,0.1)',
            },
            grid: {
              circular: true,
              color: 'rgba(255,255,255,0.1)',
            },
            suggestedMin: 0,
            suggestedMax: 4,
          },
        },
        responsive: true,
        elements: {
          line: {
            borderWidth: 1,
            borderJoinStyle: 'round',
            borderCapStyle: 'round',
          },
          point: {
            pointStyle: 'circle',
            borderColor: 'rgba(255,255,255,0.1)',
          },
        },
      },
    });

I want to color the backgrounds of the axes (not the axes themselves).


Solution

  • this can be done by applying conic gradient in background-image on the canvas in a way that no gradient affect is seen (which can be done by using same angle values in a group of two).

    for example in linear gradient

    .linear-gradient{
    width: 300px; 
    height: 100px;
    background: linear-gradient(to right, #32ff7a 0%,#32ff7a 33%,#ff0004 33%,#ff0004 66%, #ff32E0 66%, #ff32E0 100%);
    }
    
    
    .conic-gradient{
        width: 400px; 
        height: 400px; 
        background-repeat: no-repeat;
        background-position: center center;
        background-image: conic-gradient(from 25.715deg, 
                            rgba(255, 0, 0, 0.44) 0deg,
                            rgba(255, 0, 0, 0.44) 51.43deg,
                            rgba(255, 255, 0, 0.44) 51.43deg,   
                            rgba(255, 255, 0, 0.44) 102.86deg,
                            rgba(0, 128, 0, 0.44) 102.86deg,
                            rgba(0, 128, 0, 0.44) 154.29deg, 
                            rgba(0, 0, 255, 0.44) 154.29deg,
                            rgba(0, 0, 255, 0.44) 205.72deg, 
                            rgba(165, 42, 42, 0.44) 205.72deg,
                            rgba(165, 42, 42, 0.44) 257.15deg, 
                            rgba(128, 0, 128, 0.44) 257.15deg, 
                            rgba(128, 0, 128, 0.44) 308.58deg, 
                            rgba(128, 128, 128, 0.44) 308.58deg,
                            rgba(128, 128, 128, 0.44) 360.01deg);
       
         clip-path: polygon(
          49% 0,
          90% 20%,
          100% 60%,
          75% 100%,
          25% 100%,
          0% 60%,
          10% 20%
        );
    }
    <div class="linear-gradient"></div>
    
    <div class="conic-gradient"></div>

    like (#32ff7a 33%,#ff0004 33%) and (#ff0004 66%, #FF32E0 66%) in above example, the angle values are same so the gradient effect is not seen

    now use this concept on chartjs and set conix gradient as background to generate this gradient based on the number of sectors we will divide sectors into equal parts with respect to 360 degree -> (360 / no of sectors)

    you need gives the same nukber of colors as your labels in colors[] array and it will generate gradient accordingly (ex: 4 labels then 4 colors then 4 sectors will be generated)

    see the following code

    codepen link here

    const data = {
      labels: [
        "Eating",
        "Drinking",
        "Sleeping",
        "Designing",
        "Coding",
        "Cycling",
        "Running"
      ],
      datasets: [
        {
          label: "My First Dataset",
          data: [65, 59, 90, 81, 56, 55, 40],
          fill: true,
          // backgroundColor: "rgba(255, 99, 132, 0.2)",
          borderColor: "rgb(255, 99, 132)",
          pointBackgroundColor: "rgb(255, 99, 132)",
          pointBorderColor: "#fff",
          pointHoverBackgroundColor: "#fff",
          pointHoverBorderColor: "rgb(255, 99, 132)"
        },
        {
          label: "My Second Dataset",
          data: [28, 48, 40, 19, 96, 27, 100],
          fill: true,
          // backgroundColor: "rgba(54, 162, 235, 0.2)",
          borderColor: "rgb(54, 162, 235)",
          pointBackgroundColor: "rgb(54, 162, 235)",
          pointBorderColor: "#fff",
          pointHoverBackgroundColor: "#fff",
          pointHoverBorderColor: "rgb(54, 162, 235)"
        }
      ]
    };
    
    var ctx = document.getElementById("radarChart");
    
    var myRadarChart = new Chart(ctx, {
      type: "radar",
      data: data,
      options: {
        plugins: {
          legend: {
            display: false
          }
        },
        elements: {
          line: {
            borderWidth: 3
          }
        },
        scales: {
          r: {
            angleLines: {
              display: true
            },
            suggestedMin: 50,
            suggestedMax: 200
          }
        }
      }
    });
    
    // colors you want to use
    var color = [
      "#ff000070",
      "#ffff0070",
      "#00800070",
      "#0000ff70",
      "#a52a2a70",
      "#80008070",
      "#80808070"
    ];
    
    var colorData = [];
    
    //this creates double entries as required in conic gradient in css
    color.map((e, i) => {
      colorData.push(e);
      colorData.push(e);
    });
    
    //equal parts for sector
    const angles = (360 / data.labels.length).toFixed(2) * 1;
    
    var angle = 0;
    var angleValues = [];
    
    // to create successive angles for sectors
    //this create value to insert in conic gradient with color and angle in deg
    colorData.map((e, i) => {
      e = e + ` ${angle}deg`;
      angleValues.push(e);
      if (i % 2 !== 1) {
        angle = angle + angles;
      }
    });
    
    //now convert array to string and put inside css
    var bgConic = `conic-gradient(from ${
      angles / 2
    }deg, ${angleValues.toString()})`;
    
    console.log(bgConic);
    //apply our home-made css
    ctx.style.backgroundImage = bgConic;
    .container {
      width: 600px;
      height: 600px;
      margin: 0 auto;
    }
      #radarChart {
        width: 100%;
        height: 100%;
        background-repeat: no-repeat;
        background-position: center center;
    
    
    /*for hexagon shape*/
        clip-path: polygon(
          49% 0,
          90% 20%,
          100% 60%,
          75% 100%,
          25% 100%,
          0% 60%,
          10% 20%
        );
      }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.0/chart.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    
    <div class="container">
      <canvas id="radarChart"></canvas>
    </div>
    and at last used clip-path css on canvas to make hexagon shape

    also the codepen link here