Đ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);