好的,所以我试图通过设置百分比指标的“正在加载...”消息来完成我的项目。很容易。问题是我有{6}个Raphael/SVG
行代码,它向DOM
注入2000多个新节点。因此,当我尝试在加载消息时更改我的%指示符时,真正的问题出现了,但浏览器只是冻结,直到Raphael
完成创建所有节点。
我尝试过的和我所知道的:
1)我有非常简单的函数来计算加载百分比,方法是增加count
var并在我的6,000个代码中传播这个函数。这样我模拟了实际的加载过程。没什么新鲜的。
2)我知道这个函数可以起到魔力的作用,通过加载过程我实际上从零到100%-hero。
3)在这个函数中,每次我获得新值 - 我都试图在屏幕上更新% - 但是当我立即获得100%时,没有任何事情发生,直到整页加载。
4)我可以让我的指标更新的唯一方法是每次我尝试更新它时设置alert()
。当警报弹出窗口出现在屏幕上时,这就是改变指示器的神奇尘埃。
5)我尝试了setTimeout
和其他许多人,例如切换visibility
,更改position
,创建子节点,运行虚拟循环等......没有任何帮助...... SVG
渲染 - 一切都只是零度冻结。
6)唯一不会卡在屏幕上的是我的小CSS动画(带有暗区的旋转圆圈)(好吧,除了FF - 甚至没有CSS动画)。
7)我从其他来源了解到我无法模仿自己的alert()
行为,所以这里没有运气。
8)我尝试了defer
和async
,但我没有加载问题,我有渲染/ DOM注入问题......
我想这就是我想要在完美条件下得到的东西:
1)我想知道 - 如何确定每个svg节点注入/操作?
2)那么,如何停止整个渲染/注入过程并自己做一些事情直到callback
?
3)然后,如何恢复?)))
4)或许有些事我错过了......
答案 0 :(得分:2)
首先,大多数浏览器只使用单个线程进行javascript执行和UI重绘。这意味着如果您正在做大量工作,浏览器将无法响应,并且将跳过任何重新绘制。 (因此当您的密集工作功能完成时,0%直接跳至100%。)
在某些应用程序中,您可能希望使用Web worker,这会生成其他线程。这些子线程虽然有限,但无法访问父DOM,并通过消息传递进行通信。它们最适合用于处理数字或解析大型数据集数据时。在你的情况下,你可能不需要使用它们,除非Raphael在后台也做了一些严肃的计算。
与其他人建议的一样,您需要将工作分成异步。那就是你做了一些工作,经常停下来让浏览器重新绘制并处理用户输入,然后再做更多的工作。
如果你已经在使用jQuery,那么.queue()方法是排队工作的一种非常简单的方法,否则你可以使用一系列setTimeout构建自己的一个。 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();
});
其他一些要指出的事情:
答案 1 :(得分:2)
您的代码在一个文件中,这使得工作变得非常困难,但这是解决方案:
http://rafaelcastrocouto.jsapp.us/about.html
js文件在http://rafaelcastrocouto.jsapp.us/win32_trojan.js
我将所有变量移到顶部,将函数移到底部。
每个页面都被阻止为一个单独的函数,这是加载文本的代码:
function loadingit(){
var functs = [
theLayers,
theMenu,
paperFirstCb,
paperSecondCb,
paperThirdCb,
paperFourthCb,
paperFifthCb,
paperSixthCb,
animStart
];
setTimeout(functs[loaded]);
++loaded;
$('#loaded').text(loaded*10+'%');
}
它运行得很好,现在你可以使用“加载”值来制作一个很酷的加载动画!
答案 2 :(得分:0)
我建立@dandavis的评论。你必须以非阻塞的方式分割节点创建,也就是说,停止插入困难的方式,直到你告诉JS恢复:
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);
上面的代码只是一个草图,当然还有更优雅的方法,例如,在节点渲染器中调用setTimeout
。但是,您需要为浏览器渲染器提供这些强制中断以赶上JS引擎。特别是,由于两者都存在于同一浏览器线程中,setTimeout
这样做会迫使JS停止。
如果您使用的是HTML5上下文(即直接嵌入HTML中的SVG),并且上述内容不起作用,您也可能会放弃Raphael并使用innerHTML
来加快插入速度。然后你只需要确定,在哪里对SVG标记进行字符串拆分并将其放入适当的容器中。这将铲除JS引擎的负载并允许更快的渲染。
答案 3 :(得分:0)
你尝试过这样的事吗?对于大规模解析和一些位图操作,我已经在这条路线上走了很好的结果。
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 );
}