Redimensionnement du canevas Chart.js

86

Dans ( Erreur de canevas Android WebView HTML5 ), j'ai posté une question concernant le traçage de graphiques à l'aide de la bibliothèque Graph.js. Le problème que j'ai maintenant est que si j'appelle la fonction pour tracer le graphique plusieurs fois, la toile se redimensionne à chaque fois. Chaque fois que le graphique est redessiné sur le même canevas, sa taille change également. J'ai aussi essayé de définir la taille de la toile mais sans succès.

Quelle pourrait être la raison? Pourquoi le canevas est-il redimensionné à chaque fois?

Jaka
la source
Maintenant, leur page est dédiée à cela sur le site officiel de Chart.js, ici: chartjs.org/docs/latest/general/responsive.html J'ai testé la solution et cela fonctionne très bien.
Amine27

Réponses:

175

J'ai eu beaucoup de problèmes avec cela, car après tout cela, mon graphique de ligne avait l'air terrible lorsque la souris survolait et j'ai trouvé un moyen plus simple de le faire, j'espère que cela aidera :)

Utilisez ces options 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
la source
Merci @NoFlag pour la réponse. Pour moi, les attributs de hauteur et de largeur n'étaient pas appliqués au canevas, au cas où quelqu'un se retrouverait ici à la recherche d'une solution pour essayer de redimensionner le canevas, essayez de définir responsive sur true. * Chart.defaults.global.responsive = false *
sghosh968
13
N'oubliez pas que pour que cette méthode fonctionne correctement, vous devez placer le canevas dans un <div>et définir la hauteur et / ou la largeur sur ledit <div>au lieu du canevas.
totymedli
2
Ces indicateurs sont désormais définis par défaut sur true, vous n'avez donc pas besoin de les toucher: chartjs.org/docs/latest/general/responsive.html
João Pimentel Ferreira
Parallèlement à cela, définissez également la largeur et la hauteur de la toile. Ensuite, cela fonctionne très bien. Merci
Mazhar MIK
63

Ce qui se passe, c'est que Chart.js multiplie la taille du canevas lorsqu'il est appelé, puis tente de le réduire à l'aide de CSS, le but étant de fournir des graphiques de résolution plus élevée pour les appareils à haute résolution.

Le problème est qu'il ne se rend pas compte qu'il a déjà fait cela, donc lorsqu'il est appelé plusieurs fois, il multiplie à NOUVEAU la taille déjà (doublée ou autre) jusqu'à ce que les choses commencent à se casser. (Ce qui se passe réellement, c'est de vérifier s'il doit ajouter plus de pixels au canevas en modifiant l'attribut DOM pour la largeur et la hauteur, le cas échéant, en le multipliant par un facteur, généralement 2, puis en le modifiant, puis en changeant le style css attribut pour conserver la même taille sur la page.)

Par exemple, lorsque vous l'exécutez une fois et que la largeur et la hauteur de votre canevas sont définies sur 300, il les définit sur 600, puis change l'attribut de style sur 300 ... mais si vous le réexécutez, il voit que la largeur et la hauteur du DOM sont 600 (vérifiez l'autre réponse à cette question pour voir pourquoi), puis définissez-le sur 1200 et la largeur et la hauteur css sur 600.

Ce n'est pas la solution la plus élégante, mais j'ai résolu ce problème tout en conservant la résolution améliorée pour les appareils Retina en définissant simplement la largeur et la hauteur du canevas manuellement avant chaque appel successif à 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
la source
Je suis tombé sur cette erreur: Uncaught ReferenceError: doughnutData is not defined
Dulith De Costa
11
Se tromper. oui, ce n'est là qu'une variable d'espace réservé, car je ne sais tout simplement pas quelles données vous tentiez de représenter graphiquement.
jcmiller11
26

Cela fonctionne pour moi:

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

Le fait essentiel est que nous devons définir la taille du canevas dans le div-tag.

Patrick Pirzer
la source
se mettre d'accord! placez simplement le canevas dans un div, puis assurez-vous que l'option pour 'responsive' n'est PAS false (c'est vrai par défaut). Ensuite, appliquez simplement la règle de dimensionnement au div.
NoelB
20

Dans IOS et Android, le navigateur masque la barre d'outils lorsque vous faites défiler, modifiant ainsi la taille de la fenêtre qui permet de redimensionner le graphique. La solution est de maintenir le rapport hauteur / largeur.

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

Cela devrait résoudre votre problème.

Pradeep Rajashekar
la source
6

Comme jcmiller11 l'a suggéré, le réglage de la largeur et de la hauteur aide. Une solution légèrement plus agréable consiste à récupérer la largeur et la hauteur du canevas avant de dessiner le graphique. Ensuite, utilisez ces nombres pour définir le graphique à chaque nouveau dessin ultérieur du graphique. Cela garantit qu'il n'y a pas de constantes dans le code 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
la source
Pardon, pouvez-vous expliquer comment cela fonctionne? Par exemple, j'ouvre une page, la toile a une taille, mais si je redimensionne la fenêtre et la toile aura une taille différente (et je n'ai probablement pas besoin de la taille d'origine car elle était pour la taille précédente de la fenêtre)?
kiradotee le
6

J'ai dû utiliser une combinaison de réponses multiples ici avec quelques ajustements mineurs.

Tout d'abord, il est nécessaire que vous enveloppiez l'élément canvas dans un conteneur de niveau bloc. Je vous le dis, ne laissez pas l'élément canvas avoir des frères et sœurs; que ce soit un enfant solitaire, car il est têtu et gâté . (L'emballage peut ne pas nécessiter de restrictions de dimensionnement, mais pour des raisons de sécurité, il peut être bon de lui appliquer une hauteur maximale.)

Après vous être assuré que les conditions précédentes sont remplies, lors du lancement du graphique, assurez-vous que les options suivantes sont utilisées:

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

Si vous souhaitez ajuster la hauteur du graphique, faites-le au niveau de l'élément du canevas.

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

N'essayez pas de traiter avec l'enfant d'une autre manière. Cela devrait aboutir à un tableau satisfaisant et correctement présenté, qui reste paisiblement dans son berceau.

truefusion
la source
3

J'ai eu un problème similaire et j'ai trouvé votre réponse. J'ai finalement trouvé une solution.

Il semble que la source de Chart.js a ce qui suit (probablement parce qu'il n'est pas censé refaire le rendu et un graphique entièrement différent dans le même canevas):

    //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);
}

C'est bien s'il est appelé une fois, mais lorsque vous redessinez plusieurs fois, vous finissez par changer la taille de l'élément DOM du canevas plusieurs fois, ce qui entraîne une redimensionnement.

J'espère que ça t'as aidé!

yahfree
la source
1

Si quelqu'un a des problèmes, j'ai trouvé une solution qui n'implique pas de sacrifier la réactivité, etc.

Enveloppez simplement votre canevas dans un conteneur div (sans style) et réinitialisez le contenu du div dans un canevas vide avec ID avant d'appeler le constructeur Chart.

Exemple:

HTML:

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

JS:

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

J'ai essayé de redimensionner le canevas en utilisant jQuery mais cela ne fonctionnait pas bien. Je pense que CSS3 est la meilleure option que vous pouvez essayer, si vous voulez zoomer en survol à un certain niveau.

Option de survol suivant à partir d'un autre lien de 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);
}

Suivez mon lien codepan:

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

Hiten Patel
la source
1

J'avais le même problème. J'ai pu le résoudre en définissant l'option:

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

Et en css, définissez la largeur du div conteneur de la même manière que le canevas:

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

Nova Qiu
la source
0

J'ai eu le même type de problème de mise à l'échelle avec Angular CLI. A pu le faire fonctionner en supprimant cette ligne de l'index.html:

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

puis dans le fichier angular-cli.json, dans la section scripts, en utilisant ceci:

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

Source : mikebarr58

Wouter Vanherck
la source
-3

Ajoutez divet cela résoudra le problème

<div style="position:absolute; top:50px; left:10px; width:500px; height:500px;"></div>
rishabh bhardwaj
la source
-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
la source