Tôi đang làm việc với một Canvas tương đối lớn có nhiều thứ phức tạp khác nhau được vẽ. Sau đó tôi muốn lưu trạng thái Canvas, vì vậy tôi có thể nhanh chóng đặt lại trạng thái của nó ở trạng thái hiện tại. Tôi sử dụng getImageData cho điều này và lưu trữ dữ liệu trong một biến. Sau đó, tôi vẽ thêm một số nội dung vào canvas và sau đó sẽ đặt lại Canvas thành vị trí khi tôi lưu trạng thái của nó, sử dụng putImageData.Tại sao putImageData lại quá chậm?
Tuy nhiên, hóa ra là putImageData rất chậm. Infact, nó là chậm hơn so với chỉ vẽ lại toàn bộ Canvas từ đầu, trong đó bao gồm một số drawImage bao gồm hầu hết các bề mặt, và hơn 40.000 lineTo hoạt động theo sau bởi đột quỵ và điền vào.
Vẽ lại canvas khoảng 2000 x 5000 pixel từ đầu mất ~ 170ms, sử dụng putImageData mặc dù mất 240ms khổng lồ. Tại sao putImageData quá chậm so với vẽ lại canvas, mặc dù vẽ lại canvas bao gồm việc lấp đầy toàn bộ canvas bằng drawImage và sau đó điền lại khoảng 50% canvas với đa giác bằng lineTo, stroke và fill. Vì vậy, cơ bản mỗi ist điểm ảnh duy nhất chạm ít nhất một lần khi vẽ lại.
Bởi vì drawImage có vẻ nhanh hơn rất nhiều sau đó putImageData (sau khi tất cả, phần drawImage của vẽ lại canvas mất ít hơn 30 ms). Tôi quyết định cố gắng lưu trạng thái của canvas không sử dụng getImageData, nhưng thay vì sử dụng canvas.toDataURL và sau đó tạo một Image từ URL dữ liệu mà tôi sẽ dính vào drawImage để vẽ nó vào khung vẽ. Hóa ra toàn bộ quy trình này nhanh hơn nhiều và chỉ mất khoảng 35ms để hoàn thành.
Vậy tại sao putImageData chậm hơn rất nhiều thì các lựa chọn thay thế (sử dụng getDataURL hoặc vẽ lại đơn giản)? Làm thế nào tôi có thể tăng tốc độ hơn nữa? Có và nếu, nói chung cách tốt nhất để lưu trữ trạng thái của canvas là gì?
(Tất cả các số được đo bằng Firebug từ trong Firefox)
Sẽ rất thú vị nếu bạn có thể đăng tải bản trình bày sự cố trực tuyến ở đâu đó. Trong noVNC (http://github.com/kanaka/noVNC) Tôi sử dụng putImageData cho rất nhiều mảng dữ liệu hình ảnh kích thước vừa và nhỏ và tôi không thấy vấn đề về hiệu suất với putImageData. Có lẽ bạn đang chạy vào một trường hợp hiệu suất cụ thể pessimal mà nên được bug'd. – kanaka
Bạn có thể xem tại đây http://www.danielbaulig.de/A3O/ Nó sẽ không hoạt động 100% nếu bảng điều khiển firebug được bật, vì vậy hãy đảm bảo bật nó lên. Phiên bản đã kiểm tra là phiên bản sử dụng putImageData. Bạn có thể kích hoạt nó bằng cách nhấp vào bất kỳ "gạch" nào. Nó sẽ làm mới khung đệm bằng cách sử dụng putImageData và sau đó "tô sáng" ô được chọn. Trong a3o_oo.js có một số dòng nhận xét, có thể được sử dụng để chuyển đổi giữa việc sử dụng putImageData (hiện tại), sử dụng getDataURL (hai dòng đề cập đến this.boardBuffer) và vẽ lại đồng bằng (dòng drawBoard) của canvas đệm. –
Câu hỏi hay và giải pháp tuyệt vời. Nhưng bạn đã bao giờ tìm ra lý do thực sự tại sao putImageData lại quá chậm so với drawImage? – cherouvim