Biểu đồ / đồ thị tương tác nhanh và đáp ứng: SVG, Canvas, khác?


114

Tôi đang cố gắng chọn công nghệ phù hợp để sử dụng cho việc cập nhật một dự án về cơ bản hiển thị hàng nghìn điểm trong một biểu đồ có thể thu phóng, xoay được. Việc triển khai hiện tại, sử dụng Protovis, là kém hiệu quả. Kiểm tra nó tại đây:

http://www.planethunters.org/classify

Có khoảng 2000 điểm khi thu nhỏ hoàn toàn. Hãy thử sử dụng tay cầm ở phía dưới để phóng to một chút và kéo nó để xoay xung quanh. Bạn sẽ thấy rằng nó khá lộn xộn và mức sử dụng CPU của bạn có thể tăng lên 100% trên một lõi trừ khi bạn có một máy tính thực sự nhanh. Mỗi thay đổi đối với khu vực lấy nét gọi là vẽ lại đến protovis, khá chậm và tệ hơn với nhiều điểm được vẽ hơn.

Tôi muốn thực hiện một số cập nhật cho giao diện cũng như thay đổi công nghệ trực quan hóa cơ bản để đáp ứng tốt hơn với hoạt ảnh và tương tác. Từ bài viết sau, có vẻ như sự lựa chọn là giữa một thư viện dựa trên SVG khác hoặc một thư viện dựa trên canvas:

http://www.sitepoint.com/how-to-choose-between-canvas-and-svg/

d3.js , phát triển từ Protovis, dựa trên SVG và được cho là hiển thị hình ảnh động tốt hơn . Tuy nhiên, tôi không rõ là tốt hơn bao nhiêu và trần hiệu suất của nó là bao nhiêu. Vì lý do đó, tôi cũng đang xem xét một cuộc đại tu hoàn chỉnh hơn bằng cách sử dụng thư viện dựa trên canvas như KineticJS . Tuy nhiên, trước khi đi quá sâu vào việc sử dụng cách tiếp cận này hay cách khác, tôi muốn nghe ý kiến ​​của một người đã thực hiện một ứng dụng web tương tự với nhiều dữ liệu này và lấy ý kiến ​​của họ.

Điều quan trọng nhất là hiệu suất, tập trung thứ hai vào việc dễ dàng thêm các tính năng tương tác khác và lập trình hoạt ảnh. Có thể sẽ không có nhiều hơn 2000 điểm cùng một lúc, với những thanh lỗi nhỏ trên mỗi điểm. Phóng to, thu nhỏ và xoay xung quanh cần phải trơn tru. Nếu các thư viện SVG gần đây nhất hoạt động tốt ở mức này, thì có lẽ sự dễ sử dụng d3 sẽ vượt trội hơn so với việc tăng cường thiết lập cho KineticJS, v.v. Nhưng nếu có một lợi thế hiệu suất lớn khi sử dụng canvas, đặc biệt là đối với những người có máy tính chậm hơn, thì tôi chắc chắn sẽ thích đi theo cách đó.

Ví dụ về ứng dụng do NYTimes tạo ra sử dụng SVG nhưng vẫn tạo hoạt ảnh mượt mà có thể chấp nhận được: http://www.nytimes.com/interactive/2012/05/17/business/dealbook/how-the-facebook-offering-compares.html . Nếu tôi có thể đạt được hiệu suất đó và không phải viết mã vẽ canvas của riêng mình, tôi có thể sẽ chuyển sang SVG.

Tôi nhận thấy rằng một số người dùng đã sử dụng kết hợp giữa thao tác d3.js kết hợp với kết xuất canvas . Tuy nhiên, tôi không thể tìm thấy nhiều tài liệu về điều này trực tuyến hoặc liên hệ với OP của bài đăng đó. Nếu bất kỳ ai có kinh nghiệm thực hiện loại triển khai DOM-to-Canvas ( demo , ) này, tôi cũng muốn nghe ý kiến ​​của bạn. Nó có vẻ là một sự kết hợp tốt giữa khả năng thao tác dữ liệu và có quyền kiểm soát tùy chỉnh đối với cách hiển thị nó (và do đó là hiệu suất), nhưng tôi tự hỏi liệu việc tải mọi thứ vào DOM có làm chậm mọi thứ hay không.

Tôi biết rằng có một số câu hỏi hiện tại tương tự như câu hỏi này, nhưng không câu hỏi nào trong số họ chính xác hỏi điều tương tự. Cảm ơn bạn đã giúp đỡ.

Tiếp theo : cách triển khai mà tôi đã kết thúc bằng cách sử dụng tại https://github.com/zooniverse/LightCurves


"Điều quan trọng nhất là hiệu suất, với trọng tâm là thứ cấp trên một cách dễ dàng thêm tương tác khác" +1 cho canvas
Philipp

Câu hỏi đặt ra là SVG có đủ trên hầu hết các trình duyệt cho 2k điểm + các phần tử biểu đồ khác không? Nếu vậy, và sự chậm chạp chỉ là do điểm yếu của protovis, thì tôi thà gắn bó với SVG.
Andrew Mao

1
Mike Bostock alread đã đưa ra một câu trả lời hay. Đối với một số thông tin bổ sung, bạn có thể xem hai tài nguyên sau: stackoverflow.com/questions/5882716/html5-canvas-vs-svg-vs-div/… blogs.msdn.com/b/ie/archive/2011/04/22 /…
mit

8
Tiếp theo: Tôi đã triển khai điều này với cách tiếp cận SVG / canvas kết hợp, trong đó SVG xử lý các trục và đường lưới và canvas có thể hiển thị các chấm cực kỳ nhanh chóng. Nó là siêu nhanh!
Andrew Mao

Câu trả lời:


183

May mắn thay, vẽ 2000 vòng tròn là một ví dụ khá dễ kiểm tra. Vì vậy, đây là bốn cách triển khai có thể thực hiện, mỗi triển khai Canvas và SVG:

Những ví dụ này sử dụng hành vi thu phóng của D3 để thực hiện thu phóng và di chuyển. Ngoài việc các vòng tròn được hiển thị trong Canvas hay SVG, sự khác biệt chính khác là bạn sử dụng tính năng thu phóng hình học hay ngữ nghĩa .

Thu phóng hình học có nghĩa là bạn áp dụng một biến đổi duy nhất cho toàn bộ khung nhìn: khi bạn phóng to, các vòng tròn trở nên lớn hơn. Phóng to ngữ nghĩa ngược lại có nghĩa là bạn áp dụng các phép biến đổi cho từng vòng tròn riêng lẻ: khi bạn phóng to, các vòng tròn vẫn giữ nguyên kích thước nhưng chúng trải rộng ra. Planethunters.org hiện đang sử dụng tính năng phóng to ngữ nghĩa, nhưng có thể hữu ích khi xem xét các trường hợp khác.

Thu phóng hình học đơn giản hóa việc triển khai: bạn áp dụng một lần dịch và chia tỷ lệ, sau đó tất cả các vòng tròn được hiển thị lại. Việc triển khai SVG đặc biệt đơn giản, cập nhật một thuộc tính "biến đổi". Hiệu suất của cả hai ví dụ phóng to hình học cảm thấy đầy đủ hơn. Đối với khả năng phóng to ngữ nghĩa, bạn sẽ nhận thấy rằng D3 nhanh hơn đáng kể so với Protovis. Điều này là do nó thực hiện ít công việc hơn cho mỗi sự kiện thu phóng. (Phiên bản Protovis phải tính toán lại tất cả các thuộc tính trên tất cả các phần tử.) Tính năng thu phóng ngữ nghĩa dựa trên Canvas nhanh hơn SVG một chút, nhưng tính năng thu phóng ngữ nghĩa SVG vẫn cho cảm giác nhạy.

Tuy nhiên, không có viên đạn ma thuật nào để thực hiện, và bốn cách tiếp cận khả thi này không bắt đầu bao phủ hết không gian khả năng. Ví dụ: bạn có thể kết hợp thu phóng hình học và ngữ nghĩa, sử dụng cách tiếp cận hình học để xoay (cập nhật thuộc tính "biến đổi") và chỉ vẽ lại các vòng tròn riêng lẻ trong khi thu phóng. Bạn thậm chí có thể kết hợp một hoặc nhiều kỹ thuật này với các phép biến đổi CSS3 để thêm một số khả năng tăng tốc phần cứng (như trong ví dụ về gói cạnh phân cấp ), mặc dù điều đó có thể khó thực hiện và có thể giới thiệu các tạo tác trực quan.

Tuy nhiên, sở thích cá nhân của tôi là giữ càng nhiều SVG càng tốt và chỉ sử dụng Canvas cho "vòng lặp bên trong" khi kết xuất là nút cổ chai . SVG có rất nhiều tiện ích để phát triển — chẳng hạn như CSS, kết hợp dữ liệu và trình kiểm tra phần tử — nên việc bắt đầu với Canvas thường là quá trình tối ưu hóa quá sớm. Kết hợp Canvas với SVG, như trong hình ảnh IPO Facebook mà bạn đã liên kết, là một cách linh hoạt để giữ lại hầu hết những tiện ích này trong khi vẫn tạo ra hiệu suất tốt nhất. Tôi cũng đã sử dụng kỹ thuật này trong Cubism.js , trong đó trường hợp đặc biệt của hình ảnh hóa chuỗi thời gian có lợi cho bộ nhớ đệm bitmap.

Như những ví dụ này cho thấy, bạn có thể sử dụng D3 với Canvas, mặc dù các phần của D3 là SVG cụ thể. Xem thêm biểu đồ hướng lựcví dụ phát hiện va chạm này .


Chà, đó là một câu trả lời tuyệt vời, và từ chính bậc thầy về hình dung! Tôi nghĩ rằng tôi sẽ phải gắn bó với tính năng phóng to ngữ nghĩa và trên máy tính của tôi, trình kết xuất dựa trên canvas nhanh hơn phiên bản SVG khi lia / phóng to (có thể liên quan đến việc triển khai trình duyệt?). Những gì bạn đã nói về việc sử dụng SVG với canvas làm vòng lặp bên trong chính xác là những gì tôi đang tìm kiếm để xác nhận và các ví dụ mã chỉ là một phần thưởng ngọt ngào. Cám ơn rất nhiều!
Andrew Mao

Tôi chỉ có ý nghĩ thử các ví dụ phóng to ngữ nghĩa trên các trình duyệt khác nhau: Chrome, cả hai đều khá nhanh, tôi không thể phân biệt được; IE: SVG hơi chậm hơn; Firefox (nhận xét cuối cùng): SVG rất chậm so với canvas. Tôi đoán điều đó cũng làm phức tạp quyết định một chút, nhưng làm cho việc hiển thị canvas trở thành một lựa chọn an toàn. Một câu hỏi nữa: Việc sử dụng KineticJS thay vì canvas trực tiếp có ảnh hưởng đáng kể đến hiệu suất không?
Andrew Mao

1
Andrew, hơi muộn nhưng đây là kinh nghiệm của tôi với FF: Nó đang bắt kịp. Tôi đã từng chạy FF 15 và D3 SVG chuyển đổi nhanh chóng bắt đầu chậm lại. Nhưng mỗi phiên bản mới đều nhanh hơn đáng kể. Bây giờ tôi đang sử dụng FF 18 beta và nó nhanh so với 17. Tuy nhiên, không chắc liệu nó có mượt như chrome hay không.
dùng2503795

@AndrewMao Xin chào Andrew, tôi gặp phải một tình huống mà có vẻ như kết xuất là nút cổ chai. Tôi cần xoay và thu phóng một số điểm và khoảng 6000 đường cong. stackoverflow.com/questions/17907769/svg-path-rendering-speed/… Nhưng tôi không hiểu lắm Bostock khi anh ấy nói "giữ càng nhiều SVG càng tốt và chỉ sử dụng Canvas cho" vòng lặp bên trong "" mà tôi có Tuy nhiên, nhìn vào bốn ví dụ .. Bạn có thể làm sáng tỏ cho tôi một số điều?
kakacii

@kakacii quá trình chuyển đổi có chậm như nhau trong tất cả các trình duyệt không? Nếu vậy, tôi sẽ nói rằng bạn đang sử dụng sai mã hoặc bạn đã đạt đến giới hạn hiển thị của trình duyệt. Nếu bạn có thể đăng một số mã, tôi có thể giúp đỡ. mbostock đã đề cập đến việc sử dụng SVG để đơn giản hóa thao tác và canvas chỉ khi cần thiết vì nó phức tạp hơn để viết mã. Tuy nhiên, các thư viện như KineticJS phải đơn giản hóa điều đó ở một mức độ nào đó.
Andrew Mao,

8

Tôi nghĩ rằng trong trường hợp của bạn , quyết định giữa canvas và svg không giống như quyết định giữa »cưỡi Ngựa« hay lái »Porsche«. Đối với tôi, nó giống như quyết định về màu sắc của những chiếc xe.

Hãy để tôi giải thích: Giả sử rằng, dựa trên khuôn khổ, các hoạt động

  • vẽ một ngôi sao,
  • thêm một ngôi sao và
  • loại bỏ một ngôi sao

lấy thời gian tuyến tính. Vì vậy, nếu quyết định của bạn về khung là tốt, nó sẽ nhanh hơn một chút, nếu không thì chậm hơn một chút.

Nếu bạn cứ cho rằng khung công tác chỉ nhanh, thì điều hiển nhiên là việc thiếu hiệu suất là do số lượng sao cao và việc xử lý chúng là điều mà không khung công tác nào có thể làm được cho bạn, ít nhất là tôi không biết về điều này.

Điều tôi muốn nói là cơ sở của vấn đề dẫn đến một vấn đề cơ bản của hình học tính toán, đó là: tìm kiếm phạm vi và một vấn đề khác của đồ họa máy tính: mức độ chi tiết .

Để giải quyết vấn đề hiệu suất của bạn, bạn cần phải triển khai một bộ xử lý tiền xử lý tốt có thể tìm rất nhanh những ngôi sao nào sẽ hiển thị và có thể có thể tập hợp các ngôi sao gần nhau, tùy thuộc vào độ thu phóng. Điều duy nhất giúp chế độ xem của bạn sống động và nhanh chóng là giữ cho số lượng ngôi sao để vẽ càng thấp càng tốt.

Như bạn đã nói, điều quan trọng nhất là hiệu suất, hơn là tôi sẽ có xu hướng sử dụng canvas, vì nó hoạt động mà không cần hoạt động DOM. Nó cũng mang lại cơ hội sử dụng webGL, thứ giúp tăng hiệu suất đồ họa lên rất nhiều.

BTW: bạn đã kiểm tra paper.js chưa? Nó sử dụng canvas, nhưng giả lập đồ họa vector.

Tái bút: Trong Sách này, bạn có thể tìm thấy một cuộc thảo luận rất chi tiết về đồ họa trên web, các công nghệ, ưu và nhược điểm của canvas, SVG và DHTML.


7

Gần đây, tôi đã làm việc trên bảng điều khiển gần thời gian thực (làm mới sau mỗi 5 giây) và chọn sử dụng các biểu đồ hiển thị bằng canvas.

Chúng tôi đã thử Highcharts (thư viện Biểu đồ JavaScript dựa trên SVG) và CanvasJS (thư viện Biểu đồ JavaScript dựa trên Canvas). Mặc dù Highcharts là một API biểu đồ tuyệt vời và cung cấp nhiều tính năng hơn, chúng tôi quyết định sử dụng CanvasJS.

Chúng tôi cần hiển thị ít nhất 15 phút dữ liệu trên mỗi biểu đồ (với tùy chọn để chọn phạm vi tối đa hai giờ).

Vì vậy, trong 15 phút: 900 điểm (điểm dữ liệu mỗi giây) x2 (biểu đồ kết hợp đường và thanh) biểu đồ x4 = tổng cộng 7200 điểm.

Sử dụng trình biên dịch chrome, với CanvasJS bộ nhớ không bao giờ vượt quá 30MB trong khi với Highcharts sử dụng bộ nhớ vượt quá 600MB.

Ngoài ra với thời gian làm mới là 5 giây, kết xuất CanvasJS được phân bổ nhanh hơn sau đó Highcharts.

Chúng tôi đã sử dụng một bộ đếm thời gian (setInterval 5 giây) để thực hiện 4 lệnh gọi REST API để lấy dữ liệu từ máy chủ back end được kết nối với Elasticsearch. Mỗi biểu đồ được cập nhật dưới dạng dữ liệu được nhận bởi JQuery.post ().

Điều đó nói rằng đối với các báo cáo ngoại tuyến, tôi sẽ sử dụng Highcharts vì API linh hoạt hơn của nó.

Cũng có các bảng xếp hạng của Zing tuyên bố sử dụng SVG hoặc Canvas nhưng chưa xem xét chúng.

Canvas nên được xem xét khi hiệu suất thực sự quan trọng. SVG để linh hoạt. Không phải là các khung công tác canvas không linh hoạt, nhưng cần nhiều công việc hơn để khung công tác canvas có được chức năng tương tự như khung công tác svg.



0

Tôi cũng nhận thấy khi chúng tôi in sang PDF một trang có đồ họa SVG, tệp PDF kết quả vẫn chứa hình ảnh dựa trên vectơ, trong khi nếu bạn in một trang có đồ họa Canvas, hình ảnh trong tệp PDF kết quả sẽ được phân loại.

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.