Gráficos Dinâmicos com Eventos – Chart.js


Há algum tempo trouxemos para vocês um artigo mostrando o básico do Chart.js, caso não tenha lido ainda clique aqui.

Hoje nos aprofundaremos mais um pouco nas funcionalidades dessa ferramenta, mostrando uma forma de trabalhar com múltiplos datasets e com dados dinâmicos e também como criar eventos com este gráfico

O resultado final será este:

Preparando tudo

Iniciaremos em nosso arquivo HTML, criando algumas divs, nosso canvas que será usado pelo Chart.js e também uma tabela que será utilizada para demonstrar o evento que criaremos.

<div class="row">
    <div class="col-40">
        <canvas id="myChart"></canvas>
    </div>
    <div class="col-60">
        <table id="myTable">
            <thead>
                <tr>
                    <th>Pokémon</th>
                    <th>Attack</th>
                    <th>Defense</th>
                    <th>Speed</th>
                </tr>
            </thead>
            <tbody id="poketable">
            </tbody>
        </table>
    </div>
</div>

Crie um arquivo css, faça a chamada em seu HTML e crie um estilo para sua tabela ou copie o código abaixo:

* {
    margin: 0;
    box-sizing: border-box;
    font-family: Arial, Helvetica, sans-serif;
}
table {
    width: 100%;
    border-collapse: collapse;
}
th,td {
    text-align: left;
    padding: 8px 15px;
}
th {
    border-bottom: 1px solid #f2f2f2;
    font-size: 16px;
    text-transform: uppercase;
    font-style: italic;
}
tr:nth-child(even) {
    background-color: #f2f2f2;
}
.row {
    display: flex;
    align-items: start;
}
.col-60,.col-40 {
    display: inline-block;
    padding: 15px;
    min-height: 5px;
}
.col-40 {
    width: 40%;
}
.col-60 {
    width: 60%;
}

Voltando ao arquivo HTML faça a sua chamada do Chart.js, caso tenha dúvidas de como fazer isso clique aqui, depois crie um arquivo JavaScript e faça a chamada em seu arquivo HTML abaixo da chamada que fez para o Chart.js

Iniciando a requisição e inserindo resultado na tabela

Para este exemplo, usaremos a mesma api utilizada no artigo onde mostramos um pouco sobre a Fetch API, caso não tenha lido ainda clique aqui.

Dito isso, para início de conversa, criaremos uma requisição Fetch utilizando a API de Pokémon

window.onload = function() {
    fetch("https://pokeapi.co/api/v1/pokemon?limit=10&offset=1")
        .then(response => response.json())
        .catch(error => console.error("Erro:" + error))
        .then(response => {
            console.log(response)
        });
}

Este deverá ser o retorno da requisição:

O passo 2, será criar uma função responsável por preencher a nossa tabela com os dados que queremos.

Abra a função, e passe alguns parâmetros.

function pokeTable(name, attack, defense, speed) {

Feito isso agora iremos pegar o elemento do corpo da tabela e criar um outro elemento que será a linha a ser adicionada, iremos inserir um template com os nossos dados no elemento criado e depois faremos um append no corpo da nossa tabela e com isso é só fechar a função.

function pokeTable(name, attack, defense, speed) {
    let pTable = document.getElementById('poketable');
    let tRow = document.createElement('tr');
    tRow.innerHTML = `
        <td>${name}</td>
        <td>${attack}</td>
        <td>${defense}</td>
        <td>${speed}</td>
    `;
    pTable.appendChild(tRow);
}

Voltando para a nossa requisição faremos um forEach para adicionar os dados na nossa tabela.

fetch("https://pokeapi.co/api/v1/pokemon?limit=10&offset=1")
    .then(response => response.json())
    .catch(error => console.error("Erro:" + error))
    .then(response => {
        response.objects.forEach(pokemon => {
            pokeTable(pokemon.name,
                pokemon.attack,
                pokemon.defense,
                pokemon.speed);
        });
    });

Este deverá ser o resultado:


Criando o gráfico

No topo do arquivo JS iremos criar duas variáveis, canvas e context.

let canvas = document.getElementById('myChart');
let ctx = canvas.getContext('2d');

Logo abaixo crie uma variável que será seu gráfico e instancie Chart passando os parâmetros necessários, deixe labels e datasets como arrays vazios.

let pokechart = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: [],
        datasets: []
    },
    options: {
        tooltips: {
            mode: 'index',
            intersect: false,
            titleMarginBottom: 10
        },
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero: true
                }
            }]
        }
    }
});

Como queremos que cada um dos atributos dos nossos Pokémon tenha um dataset próprio, por exemplo, ataque terá um dataset próprio, que poderá ter os próprios estilos, o mesmo para defesa e velocidade, então faremos uma função que será responsável pela criação de um dataset, essa função deverá ter um atributo dataset, que poderá ser acessado de fora dela.

function Dataset() {
    this.dataset = {
        label: '',
        data: [],
        backgroundColor: '',
        borderColor: '',
        borderWidth: 1
    }
}

Com isso pronto, voltamos para a nossa requisição e criamos 3 variáveis, antes do forEach e já podemos atribuir a eles o label e os estilos que desejamos colocar, neste exemplo usaremos apenas backgroundColor e borderColor.

fetch("https://pokeapi.co/api/v1/pokemon?limit=10&offset=1")
.then(response => response.json())
.catch(error => console.error("Erro:" + error))
.then(response => {
    let dataAttack = new Dataset;
    dataAttack.dataset.label = 'Attack';
    dataAttack.dataset.backgroundColor = 'rgba(255, 35, 35, 0.2)';
    dataAttack.dataset.borderColor = 'rgba(255, 35, 35, 1)';

    let dataDefense = new Dataset;
    dataDefense.dataset.label = 'Defense';
    dataDefense.dataset.backgroundColor = 'rgba(54, 162, 235, 0.2)';
    dataDefense.dataset.borderColor = 'rgba(54, 162, 235, 1)';

    let dataSpeed = new Dataset;
    dataSpeed.dataset.label = 'Speed';
    dataSpeed.dataset.backgroundColor = 'rgba(255, 206, 86, 0.2)';
    dataSpeed.dataset.borderColor = 'rgba(255, 206, 86, 1)';

Dentro do forEach faremos push das informações no data de cada dataset que criamos e também faremos push dos nomes dos no labels

response.objects.forEach(pokemon => {
    pokeTable(pokemon.name, pokemon.attack, pokemon.defense, pokemon.speed);

    dataAttack.dataset.data.push(pokemon.attack);

    dataDefense.dataset.data.push(pokemon.defense);

    dataSpeed.dataset.data.push(pokemon.speed);
    
    pokechart.data.labels.push(pokemon.name);
});

Abaixo do forEach faremos push dos 3 datasets para dentro do nosso gráfico. Depois faremos update no gráfico e então fecharemos o nosso fetch

pokechart.data.datasets.push(
    dataAttack.dataset, 
    dataDefense.dataset, 
    dataSpeed.dataset);

pokechart.update();
});

Criando eventos

Vamos começar abrindo a função onclick no nosso canvas recebendo um evento como parâmetro.

canvas.onclick = evt => {

Agora vamos chamar a função getElementsAtEvent na nossa instancia do Chart.js passando o evento como parâmetro e atribuir isso a uma variável de nome que desejar

let pokeEvent = pokechart.getElementsAtEvent(evt);
let pTable = document.getElementById('poketable');
pTable.innerHTML = `
    <tr>
        <td>${pokechart.data.labels[pokeEvent[0]._index]}</td>
        <td>${pokechart.data.datasets[0].data[pokeEvent[0]._index]}</td>
        <td>${pokechart.data.datasets[1].data[pokeEvent[0]._index]}</td>
        <td>${pokechart.data.datasets[2].data[pokeEvent[0]._index]}</td>
    </tr>`;
};

O resultado final será este:

Quando alguma barra for clicada:

Baixe o código usado neste exemplo no botão abaixo:

[download id=”1084″]

Fonte:

Documentação Chat.js: http://www.chartjs.org/docs/latest/

Uma resposta para “Gráficos Dinâmicos com Eventos – Chart.js”

  1. Bom dia, muito bom o seu artigo,
    Como faria para mostrar as informações no final de cada barra do gráfico ?
    E desabilitar a opção do usuário ter que passar o mouse encima para poder ver o valor ?

Deixe um comentário