Redimensionar tela Chart.js

86

Em ( erro de tela do Android WebView HTML5 ), postei uma pergunta sobre plotagem de gráficos usando a biblioteca Graph.js. O problema que tenho agora é que, se eu chamar a função para plotar o gráfico várias vezes, a tela será redimensionada todas as vezes. Cada vez que o gráfico é redesenhado na mesma tela, seu tamanho também muda. Também tentei definir o tamanho da tela, mas sem sucesso.

Qual seria a razão? Por que a tela sempre redimensiona?

Jaka
fonte
Agora sua página é dedicada ao site oficial do Chart.js, aqui: chartjs.org/docs/latest/general/responsive.html Teste a solução e ela funciona bem.
Amine 27 de

Respostas:

175

Tive muitos problemas com isso, porque depois de tudo isso meu gráfico de linha parecia terrível quando o mouse pairava e descobri uma maneira mais simples de fazer isso, espero que ajude :)

Use estas opções do Chart.js:

// Boolean - whether or not the chart should be responsive and resize when the browser does.

responsive: true,

// Boolean - whether to maintain the starting aspect ratio or not when responsive, if set to false, will take up entire container

maintainAspectRatio: false,
NoFlag
fonte
Obrigado @NoFlag pela resposta. Para mim, os atributos de altura e largura não estavam sendo aplicados à tela, caso alguém acabe aqui procurando uma solução para tentar redimensionar a tela, tente definir responsivo como verdadeiro. * Chart.defaults.global.responsive = false *
sghosh968
13
Não se esqueça que para este método funcionar corretamente, você precisa colocar a tela em um <div>e definir a altura e / ou largura no dito em <div>vez da tela.
totymedli
2
Esses sinalizadores agora estão configurados por padrão como true, então você não precisa tocá-los: chartjs.org/docs/latest/general/responsive.html
João Pimentel Ferreira
Junto com isso, defina a largura e a altura da tela também. Então funciona bem. Obrigado
Mazhar MIK
63

O que está acontecendo é que Chart.js multiplica o tamanho da tela quando é chamado, em seguida, tenta redimensioná-la usando CSS, com o objetivo de fornecer gráficos de resolução mais alta para dispositivos de alto dpi.

O problema é que ele não percebe que já fez isso, então quando chamado de vezes sucessivas, ele multiplica o tamanho já (dobrado ou qualquer outra coisa) DE NOVO até que as coisas comecem a quebrar. (O que realmente está acontecendo é verificar se deve adicionar mais pixels à tela, alterando o atributo DOM para largura e altura, se necessário, multiplicando por algum fator, geralmente 2, em seguida, alterando isso e, em seguida, alterando o estilo css atributo para manter o mesmo tamanho na página.)

Por exemplo, quando você o executa uma vez e a largura e altura da tela são definidas como 300, ele as define como 600 e, em seguida, altera o atributo de estilo para 300 ... mas se você executá-lo novamente, ele vê que a largura e a altura do DOM são 600 (verifique a outra resposta a esta pergunta para ver o porquê) e, em seguida, defina como 1200 e a largura e altura do css como 600.

Não é a solução mais elegante, mas resolvi esse problema mantendo a resolução aprimorada para dispositivos retina simplesmente definindo a largura e a altura da tela manualmente antes de cada chamada sucessiva para Chart.js

var ctx = document.getElementById("canvas").getContext("2d");
ctx.canvas.width = 300;
ctx.canvas.height = 300;
var myDoughnut = new Chart(ctx).Doughnut(doughnutData);
jcmiller11
fonte
Encontrei este erro: Uncaught ReferenceError: breadnutData is not defined
Dulith De Costa
11
Errar. sim, isso é apenas uma variável de espaço reservado, pois simplesmente não sei quais dados você estava tentando representar graficamente.
jcmiller11
26

Isso funciona para mim:

<body>
    <form>
        [...]
        <div style="position:absolute; top:60px; left:10px; width:500px; height:500px;">
            <canvas id="cv_values"></canvas>

            <script type="text/javascript">
                var indicatedValueData = {
                    labels: ["1", "2", "3"],
                    datasets: [
                        {
                            [...]
                        };

                var cv_values = document.getElementById("cv_values").getContext("2d");
                var myChart = new Chart(cv_values, { type: "line", data: indicatedValueData });
            </script>
        </div>
    </form>
</body>

O fato essencial é que temos que definir o tamanho da tela na div-tag.

Patrick Pirzer
fonte
aceita! apenas coloque a tela dentro de um div e certifique-se de que a opção para 'responsivo' NÃO seja falsa (é verdadeira por padrão). Em seguida, basta aplicar a regra de dimensionamento ao div.
NoelB
20

No IOS e no Android, o navegador oculta a barra de ferramentas quando você está fazendo a rolagem, alterando assim o tamanho da janela que abre o gráfico principal para redimensionar o gráfico. A solução é manter a proporção do aspecto.

var options = { 
    responsive: true,
    maintainAspectRatio: true
}

Isso deve resolver seu problema.

Pradeep Rajashekar
fonte
6

Conforme sugerido por jcmiller11, definir a largura e a altura ajuda. Uma solução um pouco melhor é recuperar a largura e a altura da tela antes de desenhar o gráfico. Em seguida, use esses números para definir o gráfico em cada redesenho subsequente do gráfico. Isso garante que não haja constantes no código javascript.

ctx.canvas.originalwidth = ctx.canvas.width;
ctx.canvas.originalheight = ctx.canvas.height;

function drawchart() {
    ctx.canvas.width = ctx.canvas.originalwidth;
    ctx.canvas.height = ctx.canvas.originalheight;

    var chartctx = new Chart(ctx);
    myNewBarChart = chartctx.Bar(data, chartSettings); 
}
Anon
fonte
Desculpe, você poderia explicar como isso funciona? Por exemplo, eu abro uma página e a tela tem um tamanho, mas se eu redimensionar a janela e a tela terá um tamanho diferente (e presumivelmente não preciso do tamanho original porque era para o tamanho anterior da janela)?
Kiradotee de
6

Tive de usar uma combinação de várias respostas aqui com alguns pequenos ajustes.

Primeiro, é necessário envolver o elemento canvas em um contêiner de nível de bloco. Eu digo a você, não deixe o elemento tela ter irmãos; que seja uma criança solitária, pois é teimosa e estragada . (A embalagem pode não precisar de nenhuma restrição de tamanho colocada sobre ela, mas por segurança, pode ser bom ter uma altura máxima aplicada a ela.)

Depois de garantir que as condições anteriores sejam atendidas, ao iniciar o gráfico, certifique-se de que as seguintes opções sejam usadas:

var options = { 
    "responsive": true,
    "maintainAspectRatio": false
}

Se você deseja ajustar a altura do gráfico, faça-o no nível do elemento da tela.

<canvas height="500"></canvas>

Não tente lidar com a criança de nenhuma outra maneira. Isso deve resultar em um gráfico satisfatório e adequadamente organizado, que permaneça em seu berço pacificamente.

fusão verdadeira
fonte
3

Tive um problema semelhante e encontrei a sua resposta. Acabei por chegar a uma solução.

Parece que a fonte de Chart.js tem o seguinte (presumivelmente porque não deve renderizar novamente um gráfico totalmente diferente na mesma tela):

    //High pixel density displays - multiply the size of the canvas height/width by the device pixel ratio, then scale.
if (window.devicePixelRatio) {
    context.canvas.style.width = width + "px";
    context.canvas.style.height = height + "px";
    context.canvas.height = height * window.devicePixelRatio;
    context.canvas.width = width * window.devicePixelRatio;
    context.scale(window.devicePixelRatio, window.devicePixelRatio);
}

Isso é bom se for chamado uma vez, mas quando você redesenhar várias vezes, você acaba alterando o tamanho do elemento DOM da tela várias vezes, causando o redimensionamento.

Espero que ajude!

yahfree
fonte
1

Se alguém está tendo problemas, encontrei uma solução que não envolve sacrificar a capacidade de resposta etc.

Basta envolver sua tela em um contêiner div (sem estilo) e redefinir o conteúdo da div para uma tela vazia com ID antes de chamar o construtor de gráfico.

Exemplo:

HTML:

<div id="chartContainer">
    <canvas id="myChart"></canvas>
</div>

JS:

$("#chartContainer").html('<canvas id="myChart"></canvas>');
//call new Chart() as usual
fpscolin
fonte
1

Tentei redimensionar canvas usando jQuery, mas não funcionou bem. Eu acho que CSS3 é a melhor opção que você pode experimentar, se você quiser fazer zoom instantâneo em um determinado nível.

Seguindo a opção de foco de outro link codepan:

.style_prevu_kit:hover{
    z-index: 2;
    -webkit-transition: all 200ms ease-in;
    -webkit-transform: scale(1.5);
    -ms-transition: all 200ms ease-in;
    -ms-transform: scale(1.5);   
    -moz-transition: all 200ms ease-in;
    -moz-transform: scale(1.5);
    transition: all 200ms ease-in;
    transform: scale(1.5);
}

Siga o meu link codepan:

https://codepen.io/hitman0775/pen/XZZzqN

Hiten Patel
fonte
1

Eu estava tendo o mesmo problema. Consegui resolver definindo a opção:

responsive: false,
maintainAspectRatio: true,
showScale: false,

E em css, defina a largura do div do contêiner igual à da tela:

    #canvasContainer { 
      width: 300px;
    }
    
    canvas {
      width: 300px;
    }

Nova Qiu
fonte
0

Eu tive o mesmo tipo de problema de dimensionamento ao usar o Angular CLI. Consegui fazê-lo funcionar removendo esta linha do index.html:

<script src="node_modules/chart.js/dist/Chart.bundle.min.js"></script>

e então no arquivo angular-cli.json, na seção de scripts, usando isto:

"scripts": ["../node_modules/chart.js/dist/Chart.bundle.min.js"]

Fonte : mikebarr58

Wouter Vanherck
fonte
-3

Adicione dive isso resolverá o problema

<div style="position:absolute; top:50px; left:10px; width:500px; height:500px;"></div>
Rishabh Bhardwaj
fonte
-5
 let canvasBox = ReactDOM.findDOMNode(this.refs.canvasBox);
 let width = canvasBox.clientWidth;
 let height = canvasBox.clientHeight;
 let charts = ReactDOM.findDOMNode(this.refs.charts);
 let ctx = charts.getContext('2d');
 ctx.canvas.width = width;
 ctx.canvas.height = height;
 this.myChart = new Chart(ctx);
Robin ma
fonte