【问题标题】:CSS transitions blocked by JavaScript被 JavaScript 阻止的 CSS 过渡
【发布时间】:2012-11-20 05:25:03
【问题描述】:

我正在尝试在 JavaScript 的 非常 密集时期创建一个加载栏,其中构建和填充了一些非常重的 3d 数组。在用户单击按钮之前,此加载栏需要保持空白。

冻结发生无论是否我正在使用-webkit-transition(这个应用程序可以是chrome独有的,在我的情况下不需要跨浏览器)。

寻求简单我已经建立了这样的酒吧......

<div id="loader">
    <div id="thumb">
    </div>
</div>

...然后试图在我的主要for 循环的各个阶段增加该条:

for(i = 0; i < 5 ; i++){
    document.getElementById('thumb').style.width = i*25 + '%';
    //More Code
}

问题是在 JavaScript 完成之前一切都会冻结。 我在 Stack Overflow 上发现了一个类似的问题,Using CSS animation while javascript computes,并在 cmets 中找到并考虑和/或尝试了以下内容:

  • 网络工作者

    不要认为它会起作用,因为我的脚本正在用对象和构造函数填充数组,其中包含根据this site 不起作用的函数

  • jQuery

    不是一个选项,我不能在我的应用程序中使用外部库 - 在任何情况下,仅为加载栏导入整个库似乎有点矫枉过正......

  • 关键帧

    这是有希望的,我试过了,但最后它也冻结了,所以不高兴

  • timeOut()s

    想过这个,但既然加载栏的目的是减少挫败感,增加等待时间似乎适得其反

我很乐意在这个阶段有任何条增量,即使它不平滑!我很确定这不仅仅是我一个人遇到的问题 - 也许有人有一个有趣的解决方案?

P.S.:我将其作为一个新问题发布,而不是添加到引用的问题中,因为我专门寻求有关 JavaScript(而不是 jQuery)的帮助,并且如果我可以使用转换(! =动画)在宽度上。

【问题讨论】:

  • 您可以将您的工作分成几部分,并通过超时将这些部分链接在一起。 (在一个片段结束时,安排运行下一个片段的超时。)这允许浏览器在每个片段之间运行动画。
  • 正如@RaymondChen 所指出的,您不使用window.setTimeout(…) 的理由并不合理。该方法让其余代码(或用户)等待;它会安排代码供以后执行。
  • 谢谢,但我不需要添加延迟吗?据我所知,延迟 0 不会给过渡时间......正如问题中提到的,让用户等待更多似乎适得其反......
  • 延迟 10ms .. 甚至 5ms 怎么样?几乎不引人注意?试试看!!
  • 这可能只是一个 typeo,但setTimeout(createMap(), 50) 将执行该函数并将结果分配给 setTimeout,这可能不是您想要的。它应该类似于:setTimeout(createMap, 50).

标签: javascript css-transitions


【解决方案1】:

有些人已经提到你应该使用超时。这是合适的方法,因为它会让浏览器有时间“呼吸”并在任务中呈现进度条。

您必须拆分代码才能异步工作。假设你目前有这样的东西:

function doAllTheWork() {
  for(var i = 0; i < reallyBigNumberOfIterations; i++) {
    processorIntensiveTask(i);
  }
}

那么你需要把它变成这样的:

var i = 0;
function doSomeWork() {
  var startTime = Date.now();
  while(i < reallyBigNumberOfIterations && (Date.now() - startTime) < 30) {
    processorIntensiveTask(i);
    i++;
  }

  if(i < reallyBigNumberOfIterations) {
    // Here you update the progress bar
    incrementBar(i / reallyBigNumberOfIterations);

    // Schedule a timeout to continue working on the heavy task
    setTimeout(doSomeWork, 50);
  }
  else {
    taskFinished();
  }
}

function incrementBar(fraction) {
  console.log(Math.round(fraction * 100) + ' percent done');
}

function taskFinished() { console.log('Done!'); }

doSomeWork();

注意表达式(Date.now() - startTime) &lt; 30。这意味着循环将在 30 毫秒的跨度内完成尽可能多的工作。您可以将这个数字设置得更大,但是从用户的角度来看,任何超过 100 毫秒(基本上是每秒 10 帧)的时间都会开始变得迟缓。

与同步版本相比,使用这种方法可能会花费更长的时间来完成整个任务。但是,根据用户的经验,指示 something 正在发生比在 nothing 似乎正在发生时无限期地等待要好——即使后者的等待时间更短。

【讨论】:

  • 感谢您的回答,用我的代码实现需要一些时间,但我认为这最终是要走的路......虽然目前我有 5 个处理器密集型任务和已经在每个人之间尝试了timeOut(),并且在所有五个人的结尾都没有得到任何反应......但我会尝试回到你身边。
  • 非常感谢,这样拆分确实很有帮助(我还有工作要做,但上面的答案最适合我的具体问题)。完全同意(在我目前的情况下)600 毫秒的投资,这比以前增加了 25%,只是 感觉 看到取得的进展不那么令人沮丧了。当然,我需要(现在可以)改进和调整它。谢谢@meetamit!
【解决方案2】:

您是否尝试过更简单并制作一个函数,比如说:

伪:

Function increment_bar(amount = 10)
{
 document.getElementById('thumb').style.width = i*amount + '%';
}

然后,无论您在哪里进行处理工作,只需每隔 x 秒或每当您在处理过程中达到某个特定点时调用该函数(比如说 10-20% 完成?)

伪:

{
    Doing_work_here;
    increment_bar(25);
    LOOP
}

【讨论】:

  • 感谢您的回答,我还没有尝试从特定功能中进行操作,我只是直接致电document.getElementById()。我会尝试一下,但是您认为它是否在函数中会有所不同吗?我会觉得这很令人惊讶(但一切皆有可能!)
  • 不...酒吧只是停留在 0,一切都窒息到最后,然后 BAM! 100 % 就在淡出之前。 function increment(input){ document.getElementById('thumb').style.width = input*25 + '%'; }
  • 道歉 - 很遗憾没有为你做这件事,因为它会更简单!
  • 不用担心@Paul,如果有什么安慰的话,我最终将您的方法与上述答案结合使用:-D
猜你喜欢
  • 2013-02-28
  • 2016-11-03
  • 1970-01-01
  • 2020-11-11
  • 1970-01-01
  • 2012-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多