Die Größe der Leinwand von Chart.j wird geändert

85

In ( Android WebView HTML5 Canvas-Fehler ) habe ich eine Frage zum Plotten von Diagrammen mit der Graph.js-Bibliothek gestellt. Das Problem, das ich jetzt habe, ist, dass, wenn ich die Funktion zum mehrfachen Zeichnen des Diagramms aufrufe, die Größe der Zeichenfläche jedes Mal geändert wird. Jedes Mal, wenn das Diagramm auf dieselbe Leinwand gezeichnet wird, ändert sich auch seine Größe. Ich habe auch versucht, die Größe der Leinwand einzustellen, aber ohne Erfolg.

Was könnte der Grund sein? Warum wird die Größe der Leinwand jedes Mal geändert?

Jaka
quelle
Jetzt gibt es eine Seite auf der offiziellen Website von Chart.js, hier: chartjs.org/docs/latest/general/responsive.html Die Lösung wurde getestet und funktioniert einwandfrei .
Amine27

Antworten:

175

Ich hatte viele Probleme damit, denn nach all dem sah meine Liniengrafik beim Bewegen der Maus schrecklich aus und ich fand einen einfacheren Weg, hoffe es wird helfen :)

Verwenden Sie diese Chart.js-Optionen:

// 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
quelle
Danke @NoFlag für die Antwort. Für mich wurden Höhen- und Breitenattribute nicht auf die Zeichenfläche angewendet, falls jemand hier nach einer Lösung für den Versuch sucht, die Größe der Zeichenfläche zu ändern, versuchen Sie, auf true zu reagieren. * Chart.defaults.global.responsive = false *
sghosh968
13
Vergessen Sie nicht, dass Sie, damit diese Methode ordnungsgemäß funktioniert, die Leinwand in a platzieren <div>und die Höhe und / oder Breite auf <div>der Leinwand anstelle der Leinwand einstellen müssen .
Totymedli
2
Diese Flags sind jetzt standardmäßig auf gesetzt true, sodass Sie sie nicht mehr berühren müssen: chartjs.org/docs/latest/general/responsive.html
João Pimentel Ferreira
Stellen Sie dazu auch die Breite und Höhe der Leinwand ein. Dann funktioniert es gut. Danke
Mazhar MIK
63

Was passiert, ist, dass Chart.js die Größe der Zeichenfläche multipliziert, wenn sie aufgerufen wird, und dann versucht, sie mithilfe von CSS wieder zu verkleinern. Der Zweck besteht darin, Diagramme mit höherer Auflösung für Geräte mit hoher Auflösung bereitzustellen.

Das Problem ist, dass es nicht merkt, dass es dies bereits getan hat. Wenn es als aufeinanderfolgende Zeiten bezeichnet wird, multipliziert es die bereits (verdoppelte oder was auch immer) Größe WIEDER, bis die Dinge anfangen zu brechen. (Was tatsächlich passiert, ist die Überprüfung, ob der Zeichenfläche mehr Pixel hinzugefügt werden sollen, indem das DOM-Attribut für Breite und Höhe geändert wird. Wenn dies der Fall ist, wird es mit einem Faktor multipliziert, normalerweise 2, dann geändert und dann der CSS-Stil geändert Attribut, um die gleiche Größe auf der Seite beizubehalten.)

Wenn Sie es beispielsweise einmal ausführen und Ihre Leinwandbreite und -höhe auf 300 festgelegt sind, werden sie auf 600 festgelegt, und das Stilattribut wird auf 300 geändert. Wenn Sie es jedoch erneut ausführen, wird die Breite und Höhe des DOM angezeigt sind 600 (überprüfen Sie die andere Antwort auf diese Frage, um zu sehen, warum) und setzen Sie sie dann auf 1200 und die CSS-Breite und -Höhe auf 600.

Nicht die eleganteste Lösung, aber ich habe dieses Problem gelöst, während ich die verbesserte Auflösung für Retina-Geräte beibehalten habe, indem ich einfach die Breite und Höhe der Leinwand vor jedem aufeinanderfolgenden Aufruf von Chart.js manuell eingestellt habe

var ctx = document.getElementById("canvas").getContext("2d");
ctx.canvas.width = 300;
ctx.canvas.height = 300;
var myDoughnut = new Chart(ctx).Doughnut(doughnutData);
jcmiller11
quelle
Ich bin auf diesen Fehler gestoßen: Nicht gefangener Referenzfehler: doughnutData ist nicht definiert
Dulith De Costa
11
Irren. Ja, das ist dort nur eine Platzhaltervariable, da ich einfach nicht weiß, welche Daten Sie grafisch darstellen wollten.
Jcmiller11
25

Das funktioniert bei mir:

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

Die wesentliche Tatsache ist, dass wir die Größe der Zeichenfläche im div-Tag festlegen müssen.

Patrick Pirzer
quelle
zustimmen! Platzieren Sie einfach die Zeichenfläche in einem Div und stellen Sie sicher, dass die Option für "Responsive" NICHT falsch ist (standardmäßig "true"). Wenden Sie dann einfach die Größenregel auf das div an.
NoelB
20

Unter IOS und Android blendet der Browser beim Scrollen die Symbolleiste aus, wodurch die Größe des Fensters geändert wird, in dem die Diagrammdiagramme angezeigt werden, um die Größe des Diagramms zu ändern. Die Lösung besteht darin, das Seitenverhältnis beizubehalten.

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

Dies sollte Ihr Problem lösen.

Pradeep Rajashekar
quelle
6

Wie von jcmiller11 vorgeschlagen, hilft das Einstellen von Breite und Höhe. Eine etwas schönere Lösung besteht darin, die Breite und Höhe der Leinwand abzurufen, bevor Sie das Diagramm zeichnen. Verwenden Sie diese Zahlen dann zum Einstellen des Diagramms bei jeder nachfolgenden Neuzeichnung des Diagramms. Dies stellt sicher, dass der Javascript-Code keine Konstanten enthält.

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
quelle
Entschuldigung, können Sie erklären, wie das funktioniert? Wenn ich zum Beispiel eine Seite öffne, hat die Leinwand eine Größe, aber wenn ich die Größe des Fensters ändere, hat die Leinwand eine andere Größe (und vermutlich brauche ich nicht die Originalgröße, weil sie für die vorherige Größe des Fensters war)?
Kiradotee
6

Ich musste hier eine Kombination aus mehreren Antworten mit einigen kleinen Änderungen verwenden.

Zunächst müssen Sie das Canvas-Element in einen Container auf Blockebene einbinden. Ich sage euch, ich nicht lassen Sie das Canvas - Element Geschwister haben; lass es ein einsames Kind sein, denn es ist stur und verwöhnt . (Für die Verpackung müssen möglicherweise keine Größenbeschränkungen festgelegt werden. Aus Sicherheitsgründen kann es jedoch sinnvoll sein, eine maximale Höhe darauf anzuwenden.)

Stellen Sie beim Starten des Diagramms sicher, dass die folgenden Optionen verwendet werden, nachdem Sie sichergestellt haben, dass die vorherigen Bedingungen erfüllt sind:

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

Wenn Sie die Höhe des Diagramms anpassen möchten, tun Sie dies auf der Ebene der Zeichenflächenelemente.

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

Versuchen Sie nicht, auf andere Weise mit dem Kind umzugehen. Dies sollte zu einem zufriedenstellend übersichtlichen Diagramm führen, das friedlich in der Krippe bleibt.

truefusion
quelle
3

Ich hatte ein ähnliches Problem und fand Ihre Antwort. Ich kam schließlich zu einer Lösung.

Es sieht so aus, als hätte die Quelle von Chart.js Folgendes (vermutlich, weil es nicht dazu gedacht ist, ein völlig anderes Diagramm in derselben Zeichenfläche neu zu rendern):

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

Dies ist in Ordnung, wenn es einmal aufgerufen wird. Wenn Sie jedoch mehrmals neu zeichnen, ändert sich die Größe des Canvas-DOM-Elements mehrmals, was zu einer Größenänderung führt.

Hoffentlich hilft das!

yahfree
quelle
1

Wenn jemand Probleme hat, habe ich eine Lösung gefunden, bei der die Reaktionsfähigkeit usw. nicht beeinträchtigt wird.

Wickeln Sie einfach Ihre Zeichenfläche in einen div-Container (kein Styling) und setzen Sie den Inhalt der div auf eine leere Zeichenfläche mit ID zurück, bevor Sie den Diagrammkonstruktor aufrufen.

Beispiel:

HTML:

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

JS:

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

Ich habe versucht, die Größe von Canvas mit jQuery zu ändern, aber es funktioniert nicht gut. Ich denke, CSS3 ist die beste Option, die Sie anprobieren können, wenn Sie mit der Maus über eine bestimmte Stufe zoomen möchten.

Folgende Hover-Option von einem anderen Codepan-Link:

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

Folgen Sie meinem Codepan-Link:

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

Hiten Patel
quelle
1

Ich hatte das gleiche Problem. Ich konnte es lösen, indem ich die Option einstellte:

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

Stellen Sie in CSS die Breite des Container-Div auf die gleiche wie die Zeichenfläche ein:

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

Nova Qiu
quelle
0

Ich hatte die gleichen Skalierungsprobleme bei der Verwendung von Angular CLI. Konnte es zum Laufen bringen, indem diese Zeile aus der index.html entfernt wurde:

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

und dann in der Datei angle-cli.json im Abschnitt "Skripte" Folgendes:

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

Quelle : mikebarr58

Wouter Vanherck
quelle
-3

Fügen Sie hinzu divund es wird das Problem lösen

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