Thay đổi kích thước canvas Chart.js


86

Trong ( Android WebView HTML5 canvas error ), tôi đã đăng một câu hỏi liên quan đến việc vẽ biểu đồ bằng thư viện Graph.js. Vấn đề tôi gặp phải bây giờ là nếu tôi gọi hàm để vẽ biểu đồ nhiều lần, canvas sẽ thay đổi kích thước mỗi lần. Mỗi lần biểu đồ được vẽ lại trên cùng một canvas, kích thước của nó cũng thay đổi. Tôi cũng đã thử đặt kích thước của canvas nhưng không thành công.

Điều gì có thể là lý do? Tại sao canvas luôn thay đổi kích thước?


Bây giờ họ là trang dành riêng trên trang web chính thức của Chart.js, tại đây: chartjs.org/docs/latest/general/responsive.html Đã thử nghiệm giải pháp và nó hoạt động tốt.
Amine27

Câu trả lời:


175

Tôi đã gặp rất nhiều vấn đề với điều đó, vì sau tất cả những điều đó đồ họa đường của tôi trông rất khủng khiếp khi di chuột qua và tôi đã tìm thấy một cách đơn giản hơn để làm điều đó, hy vọng nó sẽ giúp ích :)

Sử dụng các tùy chọn Chart.js sau:

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

Cảm ơn @NoFlag vì câu trả lời. Đối với tôi, các thuộc tính chiều cao và chiều rộng không được áp dụng cho canvas, nếu bất kỳ ai đến đây tìm kiếm giải pháp để cố gắng thay đổi kích thước canvas, hãy thử đặt đáp ứng thành true. * Chart.defaults.global.responsive = false *
sghosh968

13
Đừng quên rằng để phương pháp này hoạt động bình thường, bạn cần đặt canvas trong a <div>và đặt chiều cao và / hoặc chiều rộng trên đã nói <div>thay vì canvas.
totymedli

2
Các cờ này hiện được đặt theo mặc định true, vì vậy bạn không cần phải chạm vào chúng: chartjs.org/docs/latest/general/responsive.html
João Pimentel Ferreira

Cùng với điều này, thiết lập chiều rộng và chiều cao của canvas. Sau đó, nó hoạt động tốt. Cảm ơn
Mazhar MIK

63

Điều đang xảy ra là Chart.js nhân kích thước của canvas khi nó được gọi sau đó cố gắng thu nhỏ lại bằng cách sử dụng CSS, mục đích là để cung cấp đồ thị có độ phân giải cao hơn cho các thiết bị dpi cao.

Vấn đề là nó không nhận ra nó đã làm điều này, vì vậy khi được gọi là lần liên tiếp, nó sẽ nhân kích thước đã (nhân đôi hoặc bất kỳ) LẠI cho đến khi mọi thứ bắt đầu phá vỡ. (Điều thực sự đang xảy ra là nó đang kiểm tra xem nó có nên thêm nhiều pixel hơn vào canvas hay không bằng cách thay đổi thuộc tính DOM cho chiều rộng và chiều cao, nếu cần, nhân nó với một số hệ số, thường là 2, sau đó thay đổi điều đó, rồi thay đổi kiểu css để duy trì cùng một kích thước trên trang.)

Ví dụ: khi bạn chạy nó một lần và chiều rộng và chiều cao canvas của bạn được đặt thành 300, nó sẽ đặt chúng thành 600, sau đó thay đổi thuộc tính style thành 300 ... nhưng nếu bạn chạy lại, nó sẽ thấy rằng chiều rộng và chiều cao DOM là 600 (kiểm tra câu trả lời khác cho câu hỏi này để xem tại sao) và sau đó đặt nó thành 1200 và chiều rộng và chiều cao css thành 600.

Không phải là giải pháp thanh lịch nhất, nhưng tôi đã giải quyết được vấn đề này trong khi vẫn duy trì độ phân giải nâng cao cho các thiết bị retina bằng cách chỉ cần đặt chiều rộng và chiều cao của canvas theo cách thủ công trước mỗi lần gọi liên tiếp tới Chart.js

var ctx = document.getElementById("canvas").getContext("2d");
ctx.canvas.width = 300;
ctx.canvas.height = 300;
var myDoughnut = new Chart(ctx).Doughnut(doughnutData);

Tôi đã gặp lỗi này: Uncaught ReferenceError :mealnutData is
notined

11
Ờ. vâng, đó chỉ là một biến giữ chỗ ở đó, vì tôi chỉ đơn giản là không biết dữ liệu nào bạn đang cố gắng vẽ biểu đồ.
jcmiller11

26

Điều này phù hợp với tôi:

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

Thực tế cần thiết là chúng ta phải đặt kích thước của canvas trong thẻ div.


đồng ý! chỉ cần đặt canvas bên trong div, sau đó đảm bảo rằng tùy chọn cho 'responsive' KHÔNG sai (nó đúng theo mặc định). Sau đó, chỉ cần áp dụng quy tắc định cỡ cho div.
NoelB

20

Trong IOS và Android, trình duyệt ẩn thanh công cụ khi bạn đang cuộn, do đó thay đổi kích thước của cửa sổ đưa vào biểu đồ dẫn đầu để thay đổi kích thước biểu đồ. Giải pháp là duy trì tỷ lệ khung hình.

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

Điều này sẽ giải quyết vấn đề của bạn.


6

Như jcmiller11 đã đề xuất, việc đặt chiều rộng và chiều cao sẽ hữu ích. Một giải pháp đẹp hơn một chút là lấy lại chiều rộng và chiều cao của canvas trước khi vẽ biểu đồ. Sau đó, sử dụng những con số đó để thiết lập biểu đồ trong mỗi lần vẽ lại biểu đồ tiếp theo. Điều này đảm bảo rằng không có hằng số nào trong mã 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); 
}

Xin lỗi, bạn có thể giải thích cách này hoạt động không? Ví dụ: tôi mở một trang thì canvas có một kích thước, nhưng sau đó nếu tôi thay đổi kích thước cửa sổ và canvas sẽ có kích thước khác (và có lẽ tôi không cần kích thước ban đầu vì nó dành cho kích thước trước đó của cửa sổ)?
kiradotee

6

Tôi đã phải sử dụng kết hợp nhiều câu trả lời ở đây với một số chỉnh sửa nhỏ.

Đầu tiên, bạn cần phải bọc phần tử canvas bên trong vùng chứa cấp khối. Tôi nói với bạn, đừng không để cho các yếu tố canvas có anh chị em; hãy để nó là một đứa trẻ cô đơn, vì nó cứng đầuhư hỏng . (Trình bao bọc có thể không cần bất kỳ giới hạn kích thước nào được đặt trên nó, nhưng để đảm bảo an toàn, có thể tốt khi áp dụng chiều cao tối đa cho nó.)

Sau khi đảm bảo rằng các điều kiện trước đó được đáp ứng, khi bắt đầu biểu đồ, hãy đảm bảo các tùy chọn sau được sử dụng:

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

Nếu bạn muốn điều chỉnh chiều cao của biểu đồ, hãy làm như vậy ở cấp phần tử canvas.

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

Đừng cố gắng đối phó với đứa trẻ theo bất kỳ cách nào khác. Điều này sẽ dẫn đến một biểu đồ hài lòng, được bố trí hợp lý, một biểu đồ nằm yên trong nôi của nó.


3

Tôi đã gặp một vấn đề tương tự và tìm thấy câu trả lời của bạn .. Cuối cùng tôi đã đi đến một giải pháp.

Có vẻ như nguồn của Chart.js có như sau (có lẽ vì nó không được kết xuất lại và biểu đồ hoàn toàn khác trong cùng một khung vẽ):

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

Điều này là tốt nếu nó được gọi một lần, nhưng khi bạn vẽ lại nhiều lần, bạn sẽ thay đổi kích thước của phần tử DOM canvas nhiều lần gây ra kích thước lại.

Hy vọng rằng sẽ giúp!


1

Nếu bất kỳ ai gặp sự cố, tôi đã tìm thấy một giải pháp không liên quan đến việc hy sinh khả năng phản hồi, v.v.

Chỉ cần bọc canvas của bạn trong vùng chứa div (không có kiểu dáng) và đặt lại nội dung của div thành canvas trống có ID trước khi gọi hàm tạo Biểu đồ.

Thí dụ:

HTML:

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

JS:

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

1

Tôi đã cố thay đổi kích thước Canvas bằng jQuery nhưng nó không hoạt động tốt. Tôi nghĩ CSS3 là tùy chọn tốt nhất mà bạn có thể thử, nếu bạn muốn phóng to khi di chuột ở một mức nhất định.

Sau tùy chọn di chuột từ liên kết codepan khác:

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

Theo liên kết codepan của tôi:

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


1

Tôi đã có cùng một vấn đề. Tôi đã có thể giải quyết nó bằng cách đặt tùy chọn:

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

Và trong css, đặt chiều rộng của div container giống như canvas:

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


0

Tôi đã gặp cùng một loại vấn đề mở rộng khi sử dụng Angular CLI. Có thể làm cho nó hoạt động bằng cách xóa dòng này khỏi index.html:

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

và sau đó trong tệp angle-cli.json, trong phần script, sử dụng điều này:

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

Nguồn : mikebarr58


-3

Thêm divvà nó sẽ giải quyết vấn đề

<div style="position:absolute; top:50px; left:10px; width:500px; height:500px;"></div>

-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);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.