web-dev-qa-db-fra.com

Chart.js canvas redimensionner

En ( erreur dans le canevas Android WebView HTML5 ), j’ai posé 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 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 la toile redimensionne-t-elle à chaque fois?

78
Jaka

Cela me posait de nombreux problèmes, car après tout cela, mon graphisme de trait était épouvantable en survol de la souris et j’ai trouvé un moyen plus simple de le faire. J'espère que cela vous 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,
162
NoFlag

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

Le problème est qu’elle ne réalise pas qu’elle l’a déjà fait. Ainsi, quand on l’appelle plusieurs fois de suite, elle multiplie à nouveau la taille déjà (doublée ou autre) jusqu’à ce que les choses commencent à casser. (Ce qui se passe réellement, c’est qu’il vérifie s’il doit ajouter plus de pixels au canevas en modifiant les attributs de largeur et de hauteur du DOM, s’il le faut, en le multipliant par un facteur, généralement 2, en le modifiant puis en modifiant 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 toile sont définies sur 300, elles sont définies à 600, puis modifient l'attribut de style en 300 ... mais si vous l'exécutez à nouveau, il voit que la largeur et la hauteur du DOM sont 600 (vérifiez l’autre réponse à cette question pour voir pourquoi), puis réglez-le sur 1200, ainsi que 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 périphériques de la rétine en définissant simplement la largeur et la hauteur de la trame 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);
61
jcmiller11

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.

24
Patrick Pirzer

Dans IOS et Android, le navigateur masque la barre d'outils lorsque vous faites défiler le texte, ce qui modifie la taille de la fenêtre permettant à la carte de redimensionner le graphique. La solution consiste à conserver les proportions.

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

Cela devrait résoudre votre problème.

18
Pradeep Rajashekar

Comme suggéré par jcmiller11, il est utile de définir la largeur et la hauteur. Une solution légèrement plus agréable consiste à récupérer la largeur et la hauteur de la toile avant de dessiner le graphique. Ensuite, utilisez ces chiffres pour définir le graphique à chaque nouvelle redessin 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); 
}
6
Anon

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

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

Après avoir vérifié 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 de la zone de travail.

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

N'essayez pas de traiter l'enfant d'une autre manière. Cela devrait aboutir à un tableau satisfaisant, bien agencé, qui reste dans son berceau pacifiquement.

5
truefusion

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 présente les éléments suivants (probablement parce qu’il n’est pas censé restituer 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);
}

Cela convient si elle est appelée une fois, mais lorsque vous redessinez plusieurs fois, vous modifiez plusieurs fois la taille de l'élément DOM de la zone de dessin, ce qui provoque une nouvelle taille.

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

3
yahfree

J'ai essayé de redimensionner Canvas en utilisant jQuery mais cela ne fonctionnait pas bien. Je pense que CSS3 est la meilleure option que vous pouvez essayer, si vous voulez passer le curseur de la souris à certaines distances. niveau.

Option de survol suivante depuis un autre lien 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

1
Hiten Patel

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

Emballez simplement votre toile dans un conteneur div (sans style) et réinitialisez le contenu de la div en une toile 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
1
fpscolin

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

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

Et dans css, définissez la largeur du conteneur div identique à celle du canevas:

    #canvasContainer { 
      width: 300px;
    }
    
    canvas {
      width: 300px;
    }
0
Nova Qiu

J'avais le même type de problème de mise à l'échelle en utilisant Angular CLI. A réussi à 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

0
Wouter Vanherck