Tôi đang làm việc trên trò chơi dựa trên HTML5, trong đó tôi muốn pha trộn các khu vực bán nguyệt có màu sắc khác nhau được vẽ trên hàng trăm ô vuông trong lưới. Hiệu ứng này giống như bản đồ nhiệt. Sau một số nghiên cứu, tôi phát hiện ra kỹ thuật "bóng tối" được Simon Sarris ghi lại ở trên.
Triển khai kỹ thuật này cung cấp giao diện tôi muốn. Và tôi thích điều đó thật dễ hiểu. Tuy nhiên, trong thực tế, tôi thấy rằng việc dựng hình ngay cả một vài (~ 150) bóng tối chậm hơn nhiều so với kỹ thuật trước đây của tôi (tuy nhiên không hấp dẫn) trong việc vẽ hàng ngàn rặng đầy.
Vì vậy, tôi quyết định thực hiện một số phân tích.Tôi đã viết một số JavaScript cơ bản (phiên bản sửa đổi có thể xem tại https://jsfiddle.net/Flatfingers/4vd22rgg/) để vẽ 2000 bản sao của năm loại hình dạng khác nhau lên các phần không chồng chéo của canvas 1250x600, ghi lại thời gian đã trôi qua cho từng hoạt động trong số năm hoạt động này các phiên bản của năm trình duyệt máy tính để bàn lớn cùng với Safari di động. (Xin lỗi, máy tính để bàn Safari. Tôi cũng không có một Android tiện dụng để kiểm tra.) Sau đó, tôi đã thử kết hợp khác nhau của các hiệu ứng và ghi lại thời gian trôi qua.
Đây là một ví dụ đơn giản về cách tôi vẽ hai gradient với sự xuất hiện tương tự như shadowed cung điền:
var gradient1 = context.createRadialGradient(75,100,2,75,100,80);
gradient1.addColorStop(0,"yellow");
gradient1.addColorStop(1,"black");
var gradient2 = context.createRadialGradient(125,100,2,125,100,80);
gradient2.addColorStop(0,"blue");
gradient2.addColorStop(1,"black");
context.beginPath();
context.globalCompositeOperation = "lighter";
context.globalAlpha = 0.5;
context.fillStyle = gradient1;
context.fillRect(0,0,200,200);
context.fillStyle = gradient2;
context.fillRect(0,0,200,200);
context.globalAlpha = 1.0;
context.closePath();
timings
(2000 hình dạng không chồng chéo, bộ globalAlpha, drawImage() được sử dụng cho gradient nhưng không được sử dụng cho bóng đổ)
IE 11 (64-bit Windows 10)
Rects = 4 ms
Arcs = 35 ms
Gradients = 57 ms
Images = 8 ms
Shadows = 160 ms
Edge (64-bit Windows 10)
Rects = 3 ms
Arcs = 47 ms
Gradients = 52 ms
Images = 7 ms
Shadows = 171 ms
Chrome 48 (64-bit Windows 10)
Rects = 4 ms
Arcs = 10 ms
Gradients = 8 ms
Images = 8 ms
Shadows = 203 ms
Firefox 44 (64-bit Windows 10)
Rects = 4 ms
Arcs = 21 ms
Gradients = 7 ms
Images = 8 ms
Shadows = 468 ms
Opera 34 (64-bit Windows 10)
Rects = 4 ms
Arcs = 9 ms
Gradients = 8 ms
Images = 8 ms
Shadows = 202 ms
Mobile Safari (iPhone5, iOS 9)
Rects = 12 ms
Arcs = 31 ms
Gradients = 67 ms
Images = 82 ms
Shadows = 32 ms
QUAN SÁT
- Trong số các hình đầy, các thao tác điền luôn là hoạt động nhanh nhất trong tất cả các trình duyệt và môi trường được kiểm tra.
- Đầy vòng cung (vòng tròn) có tốc độ chậm hơn khoảng 10 lần so với IE 11 và Edge so với các rãnh đầy, so với khoảng 3,5x chậm hơn trong các trình duyệt chính khác.
- Độ dốc khoảng 3 lần chậm hơn so với các đường viền trong IE 11, Chrome 48 và Opera 34, nhưng chậm hơn 100 lần đáng kể trong Firefox 44 (xem Bugzilla report 728453).
- Hình ảnh qua drawImage() nhanh hơn khoảng 1,5 lần so với các đường viền đầy trong tất cả các trình duyệt trên máy tính để bàn.
- Vòng cung có bóng tối chậm nhất, dao động từ khoảng 50x chậm hơn so với các rãnh đầy trong IE, Edge, Chrome và Opera chậm hơn 100 lần trong Firefox.
- Chrome 48 và Opera 34 đều có tốc độ đáng kể trong mọi danh mục hình dạng ngoại trừ hình cung có bóng, nhưng chúng không tệ hơn các trình duyệt khác ở đó.
- Sự cố Chrome và Opera khi drawImage() thu hút 1000 hình dạng trong đó shadowOffsetX hoặc shadowOffsetY được cung cấp một giá trị ngoài độ phân giải màn hình vật lý.
- IE 11 và Edge chậm hơn để vẽ các cung và độ dốc so với các trình duyệt máy tính để bàn khác.
- drawImage() chậm trên Safari trên thiết bị di động. Nó thực sự nhanh hơn để vẽ nhiều gradient và bóng tối hơn là vẽ một bản sao nhiều lần với drawImage().
- Bản vẽ trong Firefox rất nhạy cảm với các thao tác trước: vẽ bóng và tô màu làm cho bản vẽ vòng cung chậm hơn. Thời gian nhanh nhất được hiển thị.
- Vẽ trong Mobile Safari rất nhạy cảm với các hoạt động trước: bóng làm cho độ dốc chậm hơn; gradient và vòng cung tạo drawImage() thậm chí còn chậm hơn bình thường. Thời gian nhanh nhất được hiển thị.
PHÂN TÍCH
Trong khi tính năng shadowOffset là một cách đơn giản và hiệu quả trực quan để kết hợp hình dạng, nó là chậm hơn so với tất cả các kỹ thuật khác đáng kể. Điều này giới hạn tính hữu dụng của nó đối với các ứng dụng chỉ cần vẽ một vài bóng, và không cần phải vẽ nhiều bóng một cách nhanh chóng và liên tục.Hơn nữa, khi tăng tốc sử dụng drawImage(), cho shadowOffsetX hoặc shadowOffsetY một giá trị lớn hơn khoảng 3000 khiến Chrome 48 và Opera 34 bị treo trong gần một phút, tiêu thụ chu kỳ CPU và sau đó làm hỏng trình điều khiển hiển thị nVidia của tôi, ngay cả sau khi cập nhật nó lên phiên bản mới nhất. (Google Tìm kiếm không tìm thấy báo cáo lỗi nào cho Chromium mô tả lỗi này khi một shadowOffset lớn và drawImage() được sử dụng cùng nhau.)
Đối với các ứng dụng cần pha trộn các hình dạng không rõ ràng, cách tiếp cận tương tự nhất với bóng tối là đặt globalCompositeOperation thành "nhẹ hơn" và sử dụng drawImage() với giá trị globalAlpha để vẽ liên tục độ dốc xuyên tâm, hoặc vẽ các gradient riêng lẻ nếu chúng cần màu khác nhau. Đây không phải là một kết hợp hoàn hảo cho các bóng chồng chéo, nhưng nó gần và tránh thực hiện các phép tính trên mỗi pixel. (Tuy nhiên, lưu ý rằng trong Safari di động, trực tiếp vẽ các hình cung đầy bóng thực sự nhanh hơn gradient và drawImage().) Trong khi thiết lập globalCompositeOperation thành "lighter" khiến IE 11 và Edge giảm khoảng 10 lần trong bản vẽ, sử dụng gradient xuyên tâm vẫn còn nhanh hơn việc sử dụng các cung tròn được tô bóng trong tất cả các trình duyệt dành cho máy tính để bàn chính và chỉ chậm hơn hai lần so với các cung tròn được tô bóng trong Safari trên thiết bị di động.
KẾT LUẬN
Nếu nền tảng mục tiêu duy nhất của bạn là iPad/iPhone, phương pháp nhanh nhất cho hình dạng pha trộn đẹp hình dáng như shadowed cung điền. Nếu không, phương pháp nhanh nhất với diện mạo tương tự mà tôi đã tìm thấy cho đến nay hoạt động trong tất cả các trình duyệt máy tính để bàn chính là vẽ gradient xuyên tâm với globalCompositeOperation được đặt thành "lighter" và kiểm soát độ mờ với globalAlpha.
Lưu ý: Có một số cách rõ ràng rằng hiệu suất có thể được cải thiện trong các bài kiểm tra bản vẽ mà tôi đã thực hiện. Đặc biệt, vẽ từng thể hiện của từng hình dạng vào một bộ đệm ngoài màn hình và sau đó vẽ toàn bộ bộ đệm một lần vào khung nhìn thấy được sẽ mang lại một cải thiện hiệu suất đáng kể. Nhưng điều đó sẽ phủ nhận mục tiêu của thử nghiệm này, đó là so sánh tốc độ tương đối của việc vẽ các loại hình dạng khác nhau trên khung nhìn thấy được.
Khu vực chồng chéo của hai gradient được hợp nhất nhưng không cộng lại. - Bạn có thể mô tả sự hợp nhất trên cơ sở từng pixel. –