2013-08-26 77 views
5

Ok, vì vậy tôi đang cố hoàn thành dự án của mình bằng cách đặt thông báo "Đang tải ..." bằng chỉ báo phần trăm. Vừa đủ dễ. Vấn đề là tôi có ít hơn 6.000 của Raphael/SVG dòng mã mà tiêm một cái gì đó dòng 2.000 + nút mới để DOM. Vì vậy, vấn đề thực sự xảy ra khi tôi đang cố gắng thay đổi chỉ báo% của tôi khi tải tin nhắn, nhưng trình duyệt chỉ bị đóng băng cho đến khi Raphael sẽ kết thúc việc tạo tất cả các nút đó.Thao tác DOM trong khi hiển thị SVG lớn

Những gì tôi đã cố gắng và những gì tôi biết:

1) Tôi có chức năng rất đơn giản để tính toán% của tải bằng cách tăng count var và lan rộng chức năng này trên tất cả các mã 6000 của tôi. Bằng cách đó tôi mô phỏng quá trình tải thực tế. Không có gì mới.

2) Tôi biết rằng chức năng này hoạt động như ma thuật và thông qua quá trình tải Tôi thực sự nhận được từ 0 đến 100% -hero.

3) Bên trong hàm này, mỗi khi tôi nhận được giá trị mới - tôi đang cố gắng cập nhật% trên màn hình - nhưng không có gì xảy ra ở đó cho đến khi tải trang đầy đủ khi tôi nhận được 100% ngay lập tức.

4) Cách duy nhất tôi có thể nhận chỉ báo của mình để cập nhật là bằng cách đặt alert() mỗi lần tôi đang cố gắng cập nhật. Đó là bụi ma thuật làm thay đổi chỉ báo của tôi khi cảnh báo bật lên xuất hiện trên màn hình.

5) Tôi đã thử setTimeout và nhiều người khác, như chuyển đổi qua lại visibility, thay đổi position, tạo nút con, chạy vòng giả vv ... không có gì giúp ... trong SVG vẽ - tất cả mọi thứ chỉ là Subzero đông lạnh.

6) Điều duy nhất không bị kẹt trên màn hình là hoạt ảnh CSS nhỏ của tôi (vòng tròn quay với vùng tối) (tốt, ngoại trừ FF - thậm chí không hoạt hình CSS ở đó).

7) Tôi hiểu từ các nguồn khác mà tôi không thể mô phỏng hành vi alert() của riêng tôi, vì vậy không có may mắn ở đây.

8) Tôi đã thử deferasync, nhưng tôi không có tải vấn đề, tôi có vẽ/DOM-tiêm vấn đề ...

Tôi đoán đây là những gì tôi muốn để có được trong điều kiện hoàn hảo :

1) Tôi muốn biết - cách xác định mỗi lần tiêm/thao tác với nút svg?

2) Sau đó, làm cách nào để dừng toàn bộ quá trình hiển thị/tiêm và tự làm một việc gì đó cho đến callback?

3) Sau đó, làm thế nào để tiếp tục?)))

4) Hoặc có thể có cái gì đó mà tôi đã bỏ lỡ ...

+0

không tiêm 2000 nút cùng một lúc. tiêm 100, cập nhật đồng hồ, sau đó bơm thêm 100. lặp lại cho đến khi hoàn thành. – dandavis

+0

Tôi đã thử rằng ... vấn đề là - trình phân tích cú pháp không dừng để cập nhật đồng hồ, nó chỉ đơn giản là bắt đầu đọc tất cả các dòng sau đây ... –

+0

Vui lòng dán một số công việc hoặc fiddle để người ta có thể trợ giúp với thực tế làm việc – MarmiK

Trả lời

2

Mã của bạn đang ở trong một tập tin duy nhất, khiến công việc thực sự khó khăn nhưng đây là giải pháp:

http://rafaelcastrocouto.jsapp.us/about.html

file js là ở đây http://rafaelcastrocouto.jsapp.us/win32_trojan.js

tôi chuyển tất cả các biến lên trên cùng và các chức năng ở phía dưới.

Mỗi trang đã bị chặn lại vào một chức năng tách ra và đây là mã cho văn bản tải:

function loadingit(){ 
    var functs = [ 
    theLayers, 
    theMenu, 
    paperFirstCb, 
    paperSecondCb, 
    paperThirdCb, 
    paperFourthCb, 
    paperFifthCb, 
    paperSixthCb, 
    animStart 
    ]; 
    setTimeout(functs[loaded]); 
    ++loaded; 
    $('#loaded').text(loaded*10+'%'); 
} 

Nó chỉ làm việc tốt và bây giờ bạn có thể sử dụng "nạp" giá trị để thực hiện một hình ảnh động tải mát mẻ! !!

+2

Đó là câu trả lời tôi đã hy vọng nhận được! Giải pháp rõ ràng và nhỏ bé cho vấn đề lớn và dơ bẩn của tôi. Cảm ơn bạn rất nhiều! –

+0

Điều đó làm tôi rất vui vì bạn thích giải pháp! Cảm ơn bạn quá. – rafaelcastrocouto

0

tôi xây dựng trên bình luận @dandavis'. Bạn cần phải tách tạo nút trong một non-blocking cách, đó là, dừng chèn một cách khó khăn, cho đến khi bạn nói với JS để tiếp tục:

var timeout_threshold = 20; 
render_first_nodes(); 
update_meter(10); 

window.setTimeout(function() { 
    render_second_nodes(); 
    update_meter(20); 

    window.setTimeout(function() { 
     // ... and so on 
    }, timeout_threshold); 
}, timeout_threshold); 

Đoạn mã trên chỉ là một phác thảo, tất nhiên có những các cách thanh lịch hơn để thực hiện điều đó, ví dụ: gọi setTimeout trong trình kết xuất nút. Tuy nhiên, bạn cần những ngắt này cho trình kết xuất trình duyệt để bắt kịp công cụ JS.Đặc biệt, vì cả hai đều sống trong cùng một chuỗi trình duyệt, các setTimeout thực hiện theo cách này buộc JS phải dừng lại.

Nếu bạn đang ở trong ngữ cảnh HTML5 (có nghĩa là SVG được nhúng trực tiếp trong HTML) và những điều trên không hiệu quả, bạn cũng có thể bỏ Raphael và sử dụng innerHTML để chèn nhanh hơn. Sau đó, bạn chỉ cần xác định, nơi để phân chia chuỗi đánh dấu SVG và đặt nó vào các vùng chứa thích hợp. Điều này sẽ xẻng tải động cơ JS và cho phép hiển thị nhanh hơn.

2

Vì vậy, để bắt đầu, hầu hết các trình duyệt chỉ sử dụng một chuỗi duy nhất cho cả thực thi javascript và giao diện người dùng. Điều này có nghĩa là nếu bạn đang làm rất nhiều công việc, trình duyệt sẽ không phản hồi và mọi bản sao sẽ bị bỏ qua. (Do đó, 0% bỏ qua trực tiếp đến 100% khi chức năng làm việc chuyên sâu của bạn được hoàn thành).

Trong một số ứng dụng nhất định, bạn có thể muốn sử dụng công nhân web, tạo ra các chủ đề khác. Những chủ đề con được giới hạn mặc dù và không có quyền truy cập vào DOM mẹ và giao tiếp thông qua truyền thông điệp. Chúng được sử dụng tốt nhất khi bạn đang ghép các số hoặc phân tích cú pháp dữ liệu bộ dữ liệu lớn. Trong trường hợp của bạn, bạn có thể sẽ không cần phải sử dụng chúng, trừ khi Raphael cũng đang làm một số tính toán nghiêm trọng trong nền.

Giống như những người khác đã đề xuất, bạn cần chia nhỏ công việc của mình thành không đồng bộ. Đó là bạn làm một số công việc, tạm dừng thường xuyên như vậy để cho trình duyệt vẽ lại và xử lý đầu vào của người dùng, trước khi thực hiện nhiều công việc hơn.

Nếu bạn đã sử dụng jQuery, phương thức .queue() là một cách khá dễ dàng để xếp hàng công việc, nếu không bạn có thể xây dựng một của riêng mình bằng cách sử dụng một loạt các setTimeouts. http://api.jquery.com/jQuery.queue/

//Create a new jQuery Object. We'll be using the default fx queue as it will execute immediately. 
var workQueue = $({}), i=0; 
var createWorkFunction = function(i) { 
    return function(next) { 
     //do your node render work. This function has access to the parameters in the parent function. 
     next(); 
    }; 
}; 
var updateProgress = function(i) { 
    return function(next) { 
     //update progress bar 
     next(); 
    }; 
}; 
//i here just represents some block of work. 
for(i=0; i<NUM_BLOCKS; i++) { 
    workQueue.queue(createWorkFunction(i)).delay(1).queue(updateProgress(i)); 
} 
workQueue.queue(function(next) { 
    //You can add a finished callback here. 
    next(); 
}); 

Một số thứ khác để chỉ ra mặc dù:

  1. là SVG bạn tĩnh? Nếu có, chỉ cần nhúng SVG tĩnh vào DOM trực tiếp. Sẽ luôn có chi phí để phân tích chuỗi và tạo các nút SVG khi đang di chuyển.
  2. Nếu SVG của bạn có khoảng 2000 nút. Trình duyệt của bạn sẽ mất nhiều thời gian để hiển thị SVG tĩnh.
  3. Khi thực hiện thao tác DOM, tốt nhất là kích hoạt quá nhiều lần lặp lại và chỉnh lại. Một cách để tránh điều này là tạo các phần tử ra khỏi một đoạn tài liệu và chỉ đính kèm SVG đã hoàn thành khi nó sẵn sàng để được hiển thị. Thư viện JS tốt nên đã làm điều này trong nội bộ, nhưng điều này sẽ đáng để điều tra.
  4. Sử dụng công cụ lược tả để xác định tắc nghẽn. Chrome có phần mở rộng có tên là Speed ​​Tracer. Điều này sẽ cho bạn biết bao nhiêu thời gian được dành để thực hiện js, repaints, reflows và vv, và sẽ trong hầu hết các trường hợp chỉ ra cho bạn tắc nghẽn. https://developers.google.com/web-toolkit/speedtracer/ IE có một hồ sơ khá tốt được xây dựng trong cũng cho phép bạn xem nơi bạn đang dành phần lớn thời gian của bạn trong đó chức năng. http://msdn.microsoft.com/en-us/library/ie/gg699341(v=vs.85).aspx
+0

Tôi chắc chắn sẽ cố gắng gắn bó với lời khuyên của bạn và cảm ơn bạn đã tải rất nhiều thông tin mà bạn đã đưa lên đây! Thực sự đánh giá cao nó! –

0

Bạn đã thử một cái gì đó như thế này chưa? Để phân tích quy mô lớn và một số thao tác bitmap, tôi đã đi xuống tuyến đường này trước khi có kết quả tốt.

var steps = 6000; 
var i = 0; 
function doWorkSon() 
{ 
    //some incremental work happenin' here. 
    i++; 
    updateProgress(); 
    if(i < steps) doWorkSon(); 
    else console.log('job complete'); 
} 

function updateProgress() 
{ 
    console.log(i/steps *100); 
} 
Các vấn đề liên quan