Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

166
Visualizações
JavaScript canvas pie chart warping issue

I am trying to create a custom HTML element that allows me to create pie charts easily. I have been very successful so far except for the fact that I cant seem to get the actual canvas drawing to be proportioned correctly.

class PieChart extends HTMLElement {
    constructor(){
        super();
    }

    connectedCallback(){
        this.classList.add('pie-chart')
        this.innerHTML = `<canvas style="width:100%; height:100%;"></canvas>`
        this.style.display = 'block'
        this.ctx = this.getElementsByTagName('canvas')[0].getContext('2d')

        const results = [
            {mood: "Angry", total: 1599, shade: "#0a9627"},
            {mood: "Happy", total: 478, shade: "#960A2C"},
            {mood: "Melancholic", total:332, shade: "#332E2E"},
            {mood: "Gloomy", total: 195, shade: "#F73809"},
            {mood: "Eh", total: 195, shade: "#000000"}
        ];

            this.chartify(results);
        

    }

    chartify(results){
        var el_width = this.getBoundingClientRect().width;
        var half = (el_width / 2);
        let sum = 0;
        let portion = results.reduce((sum, {total}) => sum + total, 0);
        let currentAngle = 0;
    
        for (let moodValue of results) {
            //calculating the angle the slice (portion) will take in the chart
            let portionAngle = (moodValue.total / portion) * 2 * Math.PI;
            //drawing an arc and a line to the center to differentiate the slice from the rest
            this.ctx.beginPath();
            this.ctx.arc(half, half, half, currentAngle, currentAngle + portionAngle);
            currentAngle += portionAngle;
            this.ctx.lineTo(half, half);
            //filling the slices with the corresponding mood's color
            this.ctx.fillStyle = moodValue.shade;
            this.ctx.fill();
        }
    }
}

window.customElements.define('pie-chart', PieChart);
export{PieChart};

this is the returned result

enter image description here

The custom element is designed to have dynamic size. So to draw the arcs I was dividing the width by 2 in order to get the midpoint. I figured this would also be the radius. then all I need is to calculate the angle which I have no problem with. Why is it that the pie chart is oblong and not taking up the full space? What am I doing wrong in my canvas draw code?.

about 4 years ago · Juan Pablo Isaza
1 Respostas
Responde à pergunta

0

The canvas element has default values for its height and width attributes of 150 and 300, respectively. If you need your canvas to be square, you need to specify these sizes to be the same.

This example tweaks your el_width variable to read the width off the canvas directly, instead of using getBoundingClientRect. I've also tweaked the way the canvas element is created so it has width and height attributes, and its 100% width and height styles are set via CSS:

class PieChart extends HTMLElement {
    constructor(){
        super();
    }

    connectedCallback(){
        this.classList.add('pie-chart')
        this.innerHTML = `<canvas width="300" height="300"></canvas>`
        this.style.display = 'block'
        this.ctx = this.getElementsByTagName('canvas')[0].getContext('2d')

        const results = [
            {mood: "Angry", total: 1599, shade: "#0a9627"},
            {mood: "Happy", total: 478, shade: "#960A2C"},
            {mood: "Melancholic", total:332, shade: "#332E2E"},
            {mood: "Gloomy", total: 195, shade: "#F73809"},
            {mood: "Eh", total: 195, shade: "#000000"}
        ];

            this.chartify(results);
        

    }

    chartify(results){
        var el_width = this.ctx.canvas.width;
        var half = (el_width / 2);
        let sum = 0;
        let portion = results.reduce((sum, {total}) => sum + total, 0);
        let currentAngle = 0;
    
        for (let moodValue of results) {
            //calculating the angle the slice (portion) will take in the chart
            let portionAngle = (moodValue.total / portion) * 2 * Math.PI;
            //drawing an arc and a line to the center to differentiate the slice from the rest
            this.ctx.beginPath();
            this.ctx.arc(half, half, half, currentAngle, currentAngle + portionAngle);
            currentAngle += portionAngle;
            this.ctx.lineTo(half, half);
            //filling the slices with the corresponding mood's color
            this.ctx.fillStyle = moodValue.shade;
            this.ctx.fill();
        }
    }
}

window.customElements.define('pie-chart', PieChart);
pie-chart {
  width: 150px;
  aspect-ratio: 1 / 1;
}

pie-chart canvas {
  width: 100%;
  height: 100%;
}
<pie-chart></pie-chart>

You'll also notice that if you use width and height values that are smaller than the actual size at which the canvas is displayed, it will be noticeably scaled up since it's producing a raster image rather than a vector one.

about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda