2011-11-23 24 views
5

CẬP NHẬT CÂU HỎI Tôi đã cập nhật này được gọn gàng hơn một chút ..:êm Animate thuộc tính thay đổi ~ 3000 Raphael đối tượng cùng một lúc

Trong fiddle này: http://jsfiddle.net/pX2Xb/4/ Tôi có một số mã raphael thu hút 3000 vòng kết nối đến một trang. Sau đó, nó cố gắng tạo hoạt ảnh cho tất cả các vòng kết nối cùng một lúc (thay đổi màu tô) trong 10 giây, kết quả là một hoạt ảnh trực quan. Thay đổi số vòng kết nối thành 20 để xem hoạt ảnh mượt mà hơn nhiều để so sánh.

Câu hỏi của tôi là (a) tôi có thể cập nhật cho 3000 thành phần mượt mà hơn và (b) nếu có, mã sẽ làm như thế nào?

Một số lưu ý:

  • Tôi sẵn sàng chấp nhận một thời gian nhỏ đánh nếu có một số cách để tối ưu hóa việc này, nhưng, ví dụ, tôi muốn tất cả vòng tròn để ít nhất đã được cập nhật trong 1.5x bất kể thời gian hoạt ảnh được đặt thành. Vì vậy, nếu hoạt ảnh là 10 giây, tất cả các vòng kết nối sẽ thay đổi trong 15.
  • 3000 yếu tố gần như giới hạn của tôi vào lúc này, vì vậy tôi rất vui khi được làm việc đó :) Nói rằng, nếu giải pháp có thể xử lý hiệu quả hơn thế, cho một trường hợp tổng quát, điều đó thực sự tuyệt vời.

chi tiết trở lên, trong trường hợp nó giúp

tôi là tạo ra một bản đồ lớn của quận Mỹ, trong đó có hơn 3000; Tôi đang sử dụng this Wikipedia svg file để nhận các đường dẫn SVG có liên quan để tạo bản đồ và hiển thị bản đồ bằng cách sử dụng RaphaelJs.

Theo đó, tôi kết thúc với hơn 3000 báo cáo tương tự như sau:

var cc_02130 = rsr.path("M 140.66674,.... 320.11635"); // county path 
    cc_02130.attr({id: '02130',.. .."marker-start": 'none'}); // init attrs 

Tôi cũng đang tạo ra một đối tượng Paper.set() để giữ tất cả những yếu tố này:

var myset = paper.set([cc_56039, cc_56040, cc_56041 ...]) 

Quên cho một thời điểm mà tệp thực sự được tạo ở đây khá lớn, tôi sẽ đánh giá cao các đề xuất của cách tôi có thể áp dụng các thay đổi đối với khối lượng đối tượng được nêu chi tiết ở trên, đó là cả CPU nhanh và hợp lý khôn ngoan (có thể là một yêu cầu lớn).

Tôi chắc chắn sẽ mở để thay đổi cấu trúc mã/đối tượng của mình, miễn là tôi có thể thay đổi từng thuộc tính của các hạt cụ thể. Ví dụ: tôi muốn có thể áp dụng màu khác nhau cho từng nội dung đường dẫn trong một hoặc hai giây (cho tất cả 3000+).

Thách thức mà tôi đang đối mặt không phải là cách áp dụng các thay đổi màu sắc, hoạt ảnh, v.v ..., nhưng làm thế nào để thực hiện điều này một cách nhanh chóng và hiệu quả. Ngay bây giờ, máy của tôi hét lên với tôi nếu tôi lặp lại và áp dụng các thay đổi trên 3000 đối tượng; như là một thay thế, tôi đã sử dụng setTimeout để phá vỡ những thay đổi thành những phần nhỏ hơn (có thể là 10 khi di chuyển, với độ trễ 40 ms). Hơn 3000 mục, điều này trở nên khá chậm và vẫn sử dụng rất nhiều CPU.

Cảm ơn, oli

+1

Tôi đoán là độ trễ của bạn đến từ số lượng lớn các lần vẽ lại được kích hoạt bởi bạn cập nhật các đối tượng, không phải do thay đổi đối tượng. 3000 cuộc gọi chức năng phải rất khả thi trong vòng một giây ngay cả trên máy chậm. Bạn có thể đo lường nếu bạn đang kích hoạt vẽ lại cho mỗi thay đổi không? Nếu có, hãy xem có cách nào để chặn vẽ lại hoặc thực hiện cập nhật hàng loạt trước khi vẽ lại hay không. – Munter

+0

Tôi đồng ý @Munter - Bây giờ tôi hiểu vấn đề của tôi phải làm với việc vẽ lại/dựng hình thực tế tất cả các hình dạng này, trái ngược với lời gọi hàm thực tế. Với điều này trong tâm trí, tôi vẫn còn phần nào đảm bảo như thế nào tôi có thể cải thiện _this_ vấn đề. Đã cập nhật câu hỏi của tôi cho phù hợp. – oli

+0

Loại vấn đề của bạn phù hợp hơn với d3.js, nếu bạn có khả năng mất các trình duyệt không phải là svg. Đây là jsfiddle của bạn với hoạt ảnh được xử lý bởi d3: http://jsfiddle.net/ekMd6/ – Duopixel

Trả lời

10

Tôi không biết tại sao, nhưng D3.js hiệu quả hơn khi làm động một số lượng lớn các phần tử cùng một lúc.Bạn có thể làm cho họ cả hai làm việc trơn tru bằng cách tạo ra một chức năng Raphael tiếp nhận một bộ và trả về đối tượng html bạn muốn animate:

Raphael.st.nodes = function() { 
    var elements = []; 
    this.forEach(function (i) { 
    elements.push(i.node); 
    }); 
    return elements; 
} 

Và sau đó bạn hãy d3 mang nó từ đó

//circleholder is a Raphael set 
elements = circleholder.nodes() 
d3.selectAll(elements) 
    .transition() 
    .attr("fill", function(d,i){return colours[randomNum(14)]}) 
    .duration(ANIMATION_DELAY) 

đây là jsfiddle: http://jsfiddle.net/mFecs/

+2

Ví dụ rất tiện lợi khi sử dụng D3 với Raphael. Chắc chắn là một ý tưởng tôi sẽ ăn cắp cho các dự án trong tương lai! – slebetman

+0

@slebetman bạn có biết rằng việc ăn cắp mã chống lại các điều khoản sử dụng StackOverflow không? – ajax333221

+0

Cảm ơn @Duopixel thực sự đánh giá cao nhiều đầu vào của bạn trong việc này. Tôi sẽ sử dụng triển khai của bạn - tại thời điểm này, tôi đang xem xét việc thực hiện lại tất cả trong d3, nhưng chúng ta sẽ thấy - dù bằng cách nào, tôi chắc chắn sẽ sử dụng thư viện trong tương lai - vì vậy cảm ơn bạn! – oli

0

Như tôi hiện không phải là quen thuộc với Rapael.js, tôi chỉ đề xuất, theo cách JavaScript chung, bạn có thể tạo một changeRaphaelPathAttributeEvent, mà bạn muốn phát ra mỗi khi bạn muốn thay đổi đường dẫn, với các thay đổi thuộc tính làm đối số cho sự kiện đã nói. Và sau đó đính kèm xử lý sự kiện cho mỗi đường dẫn sẽ thực hiện thay đổi thuộc tính, nếu có thể. Bằng cách đó, bạn sẽ gặp vấn đề về việc truy cập vòng lặp tất cả các biến đường dẫn và thay đổi các thuộc tính một cách đồng bộ (điều này sẽ ảnh hưởng trực tiếp đến sự đáp ứng của trang trong khi xử lý); phương pháp sẽ có tác động thấp hơn đến hiệu suất mà người dùng trải nghiệm.

Lưu ý: Đây chỉ là một giải pháp để tránh xung đột hiệu suất ngay lập tức. Có lẽ có những giải pháp khác có sẵn để giảm thiểu số lượng đối tượng cần thiết để truy cập, bạn cũng nên cân nhắc (và tôi không thể nói cho bạn biết, vì tôi không biết rõ Raphael).

+0

Cảm ơn @Sune, tôi đang cố thực hiện điều này ngay bây giờ. Tôi chưa có nó, tuy nhiên, tôi lo ngại rằng nó vẫn sẽ gặp phải vấn đề tương tự, đó là trình duyệt đang cố gắng áp dụng các thay đổi cho tất cả các đối tượng svg này trong một lần giảm. – oli

0

Bạn đã viết tất cả các đường dẫn theo cách thủ công chưa? Tôi nghĩ là tốt hơn nếu bạn đặt tất cả các đường dẫn trong một đối tượng. Sau đó, bạn có thể lặp lại đối tượng và vẽ tất cả các đường dẫn bằng cách sử dụng, ví dụ: for in. Trong quá trình đó, bạn có thể cung cấp ID nội bộ cho mỗi đường dẫn sử dụng element.id = 'name'. Một khi bạn có tất cả các ID's nội bộ và các đường dẫn drawed, bạn có thể sử dụng phương pháp GetById: getById('pathId') Nếu bạn đang sử dụng Sets tôi khuyên bạn nên sử dụng Clousures, trước tiên bạn có thể khai báo các biến

var setName = Paper.Set() 

và sau đó đẩy các đường dẫn trong vòng lặp khác

for (countie in Lousiana){ 
    setName.push(countie) 
} 

Sau đó, bạn có các phương pháp như Paper.forEach() nếu bạn muốn áp dụng một số thuộc tính cho các thành phần. Hoặc Set.FotEach(). Cả hai đều có chức năng gọi lại như đối số, và sau đó thực thi hàm đó trong mỗi lần lặp.

Nếu bạn muốn chia sẻ mã của mình, đó không phải là vấn đề đối với tôi để kiểm tra và đưa ra ý kiến ​​của tôi về cách giải quyết một số tình huống. Tôi cũng đang làm việc với bản đồ, tôi đang phát triển Trò chơi video giáo dục, nếu bạn muốn tôi cũng có thể chia sẻ mã của tôi với bạn, không có nhiều tài liệu về Raphael, vì vậy sẽ hữu ích cho tôi để xem bạn sử dụng nó và có thể giống nhau cho bạn.

Tạm biệt!

+0

Cảm ơn bạn đã đề xuất, tôi đã thực hiện nhiều những gì bạn đã đề cập ngay bây giờ (đặc biệt là thích công cụ element.id/getById tiện lợi - không biết bạn có thể làm điều đó). Rất tiếc, tôi vẫn gặp sự cố khi tăng tốc mọi thứ nhưng sẽ sớm đăng mã ở đây. – oli

-1

Thành thật mà nói, việc thay đổi thuộc tính của 3000 mục phải dễ dàng đối với bất kỳ máy tính nào. Raphael sử dụng setInterval cho mỗi phần tử hoạt ảnh. Sau khi thuộc tính của phần tử được thay đổi, trình duyệt sẽ vẽ lại toàn bộ trang. Đây là 2999 lại không cần thiết.

Đây là những gì tôi sẽ làm: Thay vì sử dụng hoạt ảnh Raphael, hãy sử dụng vòng lặp để thay đổi từng phần tử. Nó phức tạp hơn một chút, nhưng nó nhanh hơn. Ngoài ra, bạn có thể thay đổi các bước trên giây. Nếu hoạt ảnh của bạn chạy quá chậm, chỉ cần giảm các bước mỗi giây.

Dưới đây là ví dụ: http://jsfiddle.net/dqJps/25/

Hy vọng điều này sẽ hữu ích.

+0

Cảm ơn @Joel. Tôi đã không có cơ hội để thử điều này vì tôi không chắc chắn làm thế nào tôi có thể áp dụng nó trên bảng (ví dụ, bằng cách sử dụng chức năng animate, dần dần thay đổi một thuộc tính theo thời gian). Tôi đã cập nhật câu hỏi của tôi cho phù hợp, nhờ sự giúp đỡ của bạn cho đến nay. – oli

+0

Việc vẽ lại không xảy ra cho đến khi mã javascript ngừng thực thi (trình duyệt nhập vòng lặp sự kiện), do đó, hãy gọi 3000 'changeAttribute()' trong một vòng lặp sẽ chỉ gây ra một lần vẽ lại. – slebetman

+0

@slebetman - Tôi đồng ý với những gì bạn đang nói, nhưng quan điểm của tôi là Raphael đặt 3000 setIntervals. Những thay đổi không bao giờ trong một vòng lặp. Khi mỗi khoảng thời gian kết thúc, trình duyệt sẽ phát hiện thay đổi HTML và vẽ lại trang (hoặc các phần liên quan của trang). – Joel

Các vấn đề liên quan