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/
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 ?