苹果产品页面以其流畅的动画而闻名。例如,当您向下滚动页面时,产品可能会滑入视野,MacBook 会打开,iPhone 会旋转,所有这些都展示了硬件,演示了软件,并讲述了产品如何使用的互动故事。
只需查看 iPad Pro 移动网页体验的这段视频:
您在那里看到的许多效果并非仅使用 HTML 和 CSS 创建的。那么,您会问?好吧,这可能有点难以弄清楚。即使使用浏览器的 DevTools 也并非总能揭示答案,因为它通常无法看到 <canvas></canvas>
元素之外的内容。
让我们深入研究其中一种效果,看看它是如何制作的,以便您可以在我们自己的项目中重新创建一些这些神奇的效果。具体来说,让我们复制 AirPods Pro 产品页面和英雄图像中的动态光效。
基本概念
这个想法是创建一个动画,就像一系列快速连续的图像一样。您知道,就像翻书一样!不需要复杂的 WebGL 场景或高级 JavaScript 库。
通过将每一帧与用户的滚动位置同步,我们可以在用户向下(或向上)滚动页面时播放动画。
从标记和样式开始
此效果的 HTML 和 CSS 非常简单,因为魔法发生在 <canvas></canvas>
元素内部,我们通过赋予其 ID 来使用 JavaScript 控制它。
在 CSS 中,我们将文档的高度设置为 100vh,并将我们的内容高度设置为比 100vh 高 5 倍,以便为我们提供必要的滚动长度以使其工作。我们还将文档的背景颜色与图像的背景颜色相匹配。我们要做的最后一件事是定位 <canvas></canvas>
元素,将其居中,并限制最大宽度和高度,使其不超过视口的尺寸。
<code>html { height: 100vh; } body { background: #000; height: 500vh; } canvas { position: fixed; left: 50%; top: 50%; max-height: 100vh; max-width: 100vw; transform: translate(-50%, -50%); }</code>
现在,我们可以向下滚动页面(即使内容没有超过视口高度),我们的 <canvas></canvas>
仍然位于视口顶部。这就是我们需要的全部 HTML 和 CSS。
让我们继续加载图像。
获取正确的图像
由于我们将使用图像序列(再次,就像翻书一样),我们将假设文件名按升序顺序连续编号(即 0001.jpg、0002.jpg、0003.jpg 等)在同一目录中。
我们将编写一个函数,根据用户的滚动位置返回所需图像文件的路径和编号。
<code>const currentFrame = index => ( `https://www.apple.com/105/media/us/airpods-pro/2019/1299e2f5_9206_4470_b28e_08307a42f19b/anim/sequence/large/01-hero-lightpass/${index.toString().padStart(4, '0')}.jpg` )</code>
由于图像编号是整数,我们需要将其转换为字符串并使用 padStart(4, '0')
在我们的索引前面添加零,直到达到四位数字以匹配我们的文件名。例如,将 1 传递到此函数将返回 0001。
这给了我们一种处理图像路径的方法。这是在 <canvas></canvas>
元素上绘制的序列中的第一张图像:
如您所见,第一张图像在页面上。此时,它只是一个静态文件。我们想要的是根据用户的滚动位置更新它。我们不仅希望加载一个图像文件,然后通过加载另一个图像文件来替换它。我们希望在 <canvas></canvas>
上绘制图像,并使用序列中的下一张图像更新绘图(但我们稍后会讨论)。
我们已经创建了根据我们传入的数字生成图像文件路径的函数,因此我们现在需要做的是跟踪用户的滚动位置并确定该滚动位置对应的图像帧。
将图像连接到用户的滚动进度
要了解我们需要传递哪个数字(以及因此要加载哪个图像)在序列中,我们需要计算用户的滚动进度。我们将创建一个事件侦听器来跟踪该事件并处理一些数学计算来计算要加载的图像。
我们需要知道:
- 滚动开始和结束的位置
- 用户的滚动进度(即用户向下滚动页面的百分比)
- 与用户滚动进度对应的图像
我们将使用 scrollTop
获取元素的垂直滚动位置,在本例中是文档顶部。这将作为起始值。我们将通过从文档滚动高度减去窗口高度来获取结束(或最大)值。从那里,我们将 scrollTop
值除以用户可以向下滚动的最大值,这将给我们用户的滚动进度。
然后,我们需要将该滚动进度转换为与我们的图像编号序列对应的索引号,以便为该位置返回正确的图像。我们可以通过将进度数乘以我们拥有的帧数(图像数)来做到这一点。我们将使用 Math.floor()
将该数字向下取整,并将其包装在 Math.min()
中以及我们的最大帧数中,以便它永远不会超过总帧数。
<code>window.addEventListener('scroll', () => { const scrollTop = html.scrollTop; const maxScrollTop = html.scrollHeight - window.innerHeight; const scrollFraction = scrollTop / maxScrollTop; const frameIndex = Math.min( frameCount - 1, Math.floor(scrollFraction * frameCount) ); });</code>
使用正确的图像更新 <canvas></canvas>
我们现在知道在用户的滚动进度发生变化时需要绘制哪个图像。这就是 <canvas></canvas>
的魔力发挥作用的地方。<canvas></canvas>
具有许多很酷的功能,用于构建从游戏和动画到设计模型生成器以及介于两者之间的一切!
这些功能之一是称为 requestAnimationFrame
的方法,它与浏览器一起工作以更新 <canvas></canvas>
,如果我们使用的是直接图像文件而不是 <canvas></canvas>
,我们就无法做到这一点。这就是我选择 <canvas></canvas>
方法而不是例如 img
元素或具有背景图像的 <div> 的原因。<code>requestAnimationFrame
将匹配浏览器刷新率并通过使用 WebGL 使用设备的视频卡或集成显卡进行渲染来启用硬件加速。换句话说,我们将获得帧之间非常平滑的过渡——没有图像闪烁!
让我们在我们的滚动事件侦听器中调用此函数,以便在用户向上或向下滚动页面时交换图像。requestAnimationFrame
采用回调参数,因此我们将传递一个函数来更新图像源并在 <canvas></canvas>
上绘制新图像:
<code>requestAnimationFrame(() => updateImage(frameIndex 1))</code>
我们将 frameIndex
增加 1,因为虽然图像序列从 0001.jpg 开始,但我们的滚动进度计算实际上是从 0 开始。这确保了这两个值始终对齐。
我们传递给更新图像的回调函数如下所示:
<code>const updateImage = index => { img.src = currentFrame(index); context.drawImage(img, 0, 0); }</code>
我们将 frameIndex
传递给函数。这使用序列中的下一张图像设置图像源,该图像绘制在我们的 <canvas></canvas>
元素上。
预加载图像更好
从技术上讲,我们现在已经完成了。但是,拜托,我们可以做得更好!例如,快速滚动会导致图像帧之间出现一点滞后。这是因为每个新图像都会发送一个新的网络请求,需要一个新的下载。
我们应该尝试预加载图像新的网络请求。这样,每个帧都已下载,使过渡更快,动画更流畅!
我们要做的就是循环遍历整个图像序列并加载它们:
<code>const frameCount = 148; const preloadImages = () => { for (let i = 1; i </code>
演示!
关于性能的快速说明
虽然这种效果非常酷,但它也是很多图像。确切地说,是 148 张。
无论我们如何优化图像,或者提供它们的 CDN 多么快速,加载数百张图像总是会导致页面膨胀。假设我们在同一页面上多次使用此功能。我们可能会得到如下性能统计数据:
对于高速互联网连接且数据上限不严格的用户来说,这可能没问题,但对于没有这种便利的用户来说,我们不能这么说。这是一个难以平衡的问题,但我们必须注意每个人的体验——以及我们的决定如何影响他们。
我们可以做一些事情来帮助取得这种平衡,包括:
<code> - 加载单个后备图像而不是整个图像序列 - 为某些设备创建使用较小图像文件的序列 - 允许用户启用序列,也许可以使用启动和停止序列的按钮 苹果采用第一种方法。如果您在连接到缓慢的 3G 连接的移动设备上加载 AirPods Pro 页面,那么,性能统计数据开始看起来好多了: 是的,它仍然是一个繁重的页面。但它比我们根本没有任何性能考虑的情况下要轻得多。这就是苹果能够将如此多的复杂序列放到单个页面上的方式。 #### 进一步阅读 如果您有兴趣了解这些图像序列是如何生成的,一个好的起点是 AirBnB 的 Lottie 库。文档将引导您完成使用 After Effects 生成动画的基础知识,同时提供一种在项目中轻松包含它们的方法。 </code>
以上是让我们制作Apple产品页面上使用的那些精美的滚动动画之一的详细内容。更多信息请关注PHP中文网其他相关文章!

React生态系统为我们提供了许多库,所有库都集中在拖放的相互作用上。我们有反应,反应,可爱dnd,

我可以说我经常使用背景折叠。 IT Wager IT几乎从未在日常CSS工作中使用。但是在斯特凡·朱迪斯(Stefan Judis)的帖子中,我想起了它,

使用RequestAnimationFrame进行动画化应该很容易,但是如果您还没有彻底阅读React的文档,那么您可能会遇到一些事情

听着,我不是GraphQL专家,但我确实喜欢与之合作。作为前端开发人员,它向我曝光数据的方式非常酷。它就像一个菜单


热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

SecLists
SecLists是最终安全测试人员的伙伴。它是一个包含各种类型列表的集合,这些列表在安全评估过程中经常使用,都在一个地方。SecLists通过方便地提供安全测试人员可能需要的所有列表,帮助提高安全测试的效率和生产力。列表类型包括用户名、密码、URL、模糊测试有效载荷、敏感数据模式、Web shell等等。测试人员只需将此存储库拉到新的测试机上,他就可以访问到所需的每种类型的列表。

安全考试浏览器
Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

Atom编辑器mac版下载
最流行的的开源编辑器

MinGW - 适用于 Windows 的极简 GNU
这个项目正在迁移到osdn.net/projects/mingw的过程中,你可以继续在那里关注我们。MinGW:GNU编译器集合(GCC)的本地Windows移植版本,可自由分发的导入库和用于构建本地Windows应用程序的头文件;包括对MSVC运行时的扩展,以支持C99功能。MinGW的所有软件都可以在64位Windows平台上运行。

Dreamweaver CS6
视觉化网页开发工具