让动画等待

Avatar of Donovan Hutchinson
Donovan Hutchinson

DigitalOcean 为您的旅程各个阶段提供云产品。立即开始使用 价值200美元的免费积分!

我最近发布了一门针对希望提高 Web 动画技能的设计师和开发人员的 CSS 动画课程。在制作课程时,我遇到了一个问题,即内容在资产下载之前就开始动画。本文介绍了我为解决这个问题并确保所有动画按预期播放而采取的方法。

我们都经历过这种情况。例如,我们希望在加载时淡入一个英雄标题,所以我们添加了淡入关键帧,设置动画,但动画在背景图像下载之前就开始了。我们看到一个半加载的图像淡入,更糟糕的是,我们的徽标或标题在背景准备好之前就出现了。

谢天谢地,我们有办法解决它。

问题:并行事件

当我们加载一个网站时,浏览器会尝试通过同时下载和渲染 HTML 和 CSS 以及其他资产(如图像)来尽可能地加快速度。

这种加载方式意味着我们可以更快地看到一些布局和文本内容,但如果你创建了一个大的杂志风格的标题,图像可能无法及时到达。

让我们使用一些内置的浏览器技巧来阻止动画,直到正确的时间。

load 事件和 animation-play-state

浏览器为我们提供了一个方便的 JavaScript load 事件,用于指示内容已完成加载。该事件将针对图像和脚本等元素触发。我们可以使用它来控制动画播放的时间。

我们将使用一些 JavaScript 来监听加载事件,并使用 animation-play-state 在事件发生之前暂停我们的动画。

以下 JavaScript 代码应该可以解决问题。

document.body.classList.add('js-loading');

window.addEventListener("load", showPage);

function showPage() {
  document.body.classList.remove('js-loading');
}

代码的作用如下。第一行将 js-loading 类添加到 body 元素。然后它设置了一个事件监听器。

事件监听器会等待 load 事件发生,然后运行函数 removeLoadingClass。此时,所有图像和其他资产都已下载。

最后,removeLoadingClassbody 标签中删除该类。

此代码应该添加到页面 HTML 中,例如 head 中。如果从外部文件加载,则 CSS 可能在该代码执行之前加载并解析,这将使动画有机会在我们准备就绪之前开始。

让我们使用此类让页面上的任何动画都等到内容准备就绪。

等待一张图像

这种方法会等待页面上的所有资产加载。你可能只想等待一张图像,例如标题中的图像。幸运的是,每个图像都有加载事件。在 在 JavaScript 中测量图像宽度 中介绍的方法可以提供帮助。

我们可以调整 JavaScript 代码,使其专注于一个特定的图像。

// Adjust the "querySelector" value to target your image
var img = document.querySelector("img");
document.body.classList.add('js-loading');
img.addEventListener("load", removeLoadingClass);
function removeLoadingClass() {
  document.body.classList.remove('js-loading');
}

animation-play-state 属性

现代浏览器很好地支持 animation-play-state 属性。它告诉浏览器当前动画是正在运行还是暂停。默认情况下,动画是“运行”的。

我们可以使用此属性在加载内容时让页面上的所有动画“暂停”。我们将把它添加到我们的 CSS 中。

.js-loading *,
.js-loading *:before,
.js-loading *:after {
  animation-play-state: paused !important;
}

此代码会在 body 具有 js-loading 类时,将页面上所有内容的播放状态设置为“暂停”。

它将确保它也适用于所有 :before:after 伪元素。

当 JavaScript 从 body 标签中删除 js-loading 类时,该规则不再适用,所有动画都将处于预期的运行状态。

这种方法的一个好处是,我们不需要在样式表中更改任何其他内容!

如果 JavaScript 失败怎么办?

如果我们依靠 JavaScript 来处理屏幕上的内容显示,这始终是一个值得问的问题。有时 JavaScript 会失败。它可能被禁用。插件可能会做不可预测的事情。虽然在大多数情况下这将有效,但 JavaScript 始终是有点不受我们控制的,所以最好考虑一下如果 JavaScript 未按预期工作会发生什么。

在这种情况下,我认为我们没事。如果 JavaScript 没有运行,它就不会应用 js-loading 类。动画将立即播放。这可能会导致背景图像在动画时加载时出现一些怪异,但这是最坏的情况,也是一个合理的回退。

实际操作

让我们测试一下,看看它是否有效。我们需要一张大图片。我在 Unsplash 上找到了这张非常漂亮的 NASA 照片。它的尺寸超过了 2MB。

当页面加载时,我们应该会看到最初的空白屏幕。为了真正看到它在行动,我们可以使用 Chrome 的内置节流功能。打开检查器,选择“网络”选项卡,然后打开包含速度预设的下拉菜单。从此处,我们选择“良好 3G”,这应该足够慢,让我们看到它在行动。

Chrome 中的预设网络速度

在此演示中按“重新运行”,直到图像完全加载,否则没有任何动画会播放。

查看笔 使用 load 和 animation-play-state 等待图像加载 #2 由 Donovan Hutchinson (@donovanh) 在 CodePen 上编写。

尝试删除 JavaScript(并在重新加载之前清除缓存),以查看差异!

加载微调器

如果你想避免在此时出现空白页面,你应该使用一些加载文本或动画来让人们知道。这取决于你认为延迟时间有多长。如果你有一张非常大的图片,而且页面往往会等待超过一秒或两秒,那么加载微调器可能是个好主意。

另一方面,可能值得进一步压缩图像或将其缩小,以便它更快地加载。尝试一下,看看对你来说什么效果最好。


我希望这种技术可以帮助你让动画协同工作。

如果你想了解有关动画你的网站的更多信息,你可能会喜欢 CSSAnimation.rocks 上的教程。在 Twitter 上关注 @cssanimation