iPhone SE 2020

我们再回到网站看动画,可以看到在出现芯片图片之前会有两行字。

iPhone 11 Pro called.
It wants its chip back.

获取 Video 链接

返回网站,按下 F12 打开开发者工具。

inline-video-media 的 Div 标签下就能找到这段5秒钟的视频文件。(如下.)

我们新建立一个 section tag 将这段代码加入到其中与the-chip的Div标签处在同级。

1
2
3
4
5
6
7
8
9
10
11
<section id="chip-section">
<video src="https://www.apple.com/105/media/us/iphone-se/2020/90024c0f-285a-4bf5-af04-2c38de97b06e/anim/arcade-loop/large.mp4" muted playsinline autoplay loop></video>
<!-- 解释一下 video 的属性,muted 代表静音,playsinline 表示用手机播放时不弹出网页播放器,autoplay 表示自动开始播放, loop 表示循环播放 -->
<h1>
iPhone 11 Pro called.<br>
It wants its chip back.
</h1>
<div id="the-chip">
(SVG标签)此处省略,参考上文。
</div>
</section>

完善CSS

添加以下 CSS:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#chip-section {
position: sticky; /* 粘性定位: 为了让滚动条下拉也网页也处在同一位置 */
top: 0;
width: 100%;
height: 100vh;
overflow: hidden;
}

video {
height: 100vh; /* 填充高度 */
width: auto; /* 宽度按比例缩放 */
position: relative; /* 居中显示 */
left: 50%;
transform: translate(-50%, 0);
}

#the-chip {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100px;
height: 100px;
box-shadow: 0px 0px 0px 100vw black, 0px 0px 0px 30px black inset;
z-index: 10;
}

#A13 {
position: absolute;
width: 100%;
height: 100%;
}

h1 {
position: absolute;
top: 0;
left: 0;
color: #fff;
z-index: 20;
font-family: Helvetica;
font-size: 64px;
letter-spacing: -1px;
text-align: center;
width: 100%;
top: 50%;
transform: translate(0, -50%);
margin: 0;
}

大致的效果如下,可以看见是一个由文字遮罩住下面的芯片的效果:

See the Pen oNjYpXP by Chang (@alias_e) on CodePen.

将 CSS 配置好,就要开始 JS 的部分了。

添加 JS

首先要知道页面滚动的位置。即是用目前的滚动距离除以页面的总高度减去可见区域窗口高度。
此外再使用 querySelector 获取到一些其他的变量方便操作。

1
2
3
4
5
6
7
8
9
window.addEventListener('scroll', (e) => {
let scrolled = document.documentElement.scrollTop / (document.documentElement.scrollHeight - document.documentElement.clientHeight)
// scrolled 即是在 0 到 1.0 之间的浮点数

let $h1 = document.querySelector('h1')
let $theChip = document.querySelector('#the-chip')
let $A13 = document.querySelector('#A13')
let $A13TextBg = document.querySelector('#the-chip .text-bg')
})

再分析一下网页,可以知道向下滚动时,文字消失,出现芯片图像,之后图像再放大,渐变为透明,露出背后的 video。

放大

我们先来实现放大。透过下面的代码,让芯片图像在滚动到最底时等于视窗宽度的10倍。

1
$theChip.style.width = $theChip.style.height = document.documentElement.clientWidth * 10 * (scrolled) + 'px'

此时发现我们已经能够成功滚动,但是出现了3个问题

  1. 当滚动条处于最上方时,芯片的高和宽等于0。
    这个比较好解决,直接在 CSS 那边 给 the-chip 加上 min-widthmin-height 都为 100 px 就可以了。
  2. 当滚动条处于最下方时,芯片还是不够大。
    这个也很好解决,直接把放大倍率改大一点就可以了,所以将上面代码的10倍,改成20倍。
  3. 在刚开始滚动的时候放大比较快,然而在快滚到底部时比较慢。
    这其实是一个加速度问题,可以参考Easings.net上的easeInCubic曲线
    1
    2
    3
    function easeInCubic(x: number): number {
    return x * x * x;
    }
    可以在 Math Function 看到直接将参数乘以3倍就能得到我们需要的曲线。

于是我们把 JS 最后一行改成这样:

1
$theChip.style.width = $theChip.style.height = document.documentElement.clientWidth * 20 * (scrolled * scrolled * scrolled) + 'px'

渐出渐入

我们先来处理文字的渐出。
估计用滚动的十分之一的时间来完成渐出。即到10%。
所以加上:

1
2
3
4
5
6
if (scrolled <= 0.1) {
$h1.style.opacity = (0.1 - scrolled) / 0.1
$h1.style.marginTop = scrolled * 1000 * -1 + 'px'
} else {
$h1.style.opacity = 0
}

接着我们来处理芯片图像的渐入。估计10%-20%的部分完成。
先将 A13opacity 设置成 0.0。
然后再回到 JS 加上:

1
2
3
4
5
if (scrolled <= 0.2) {
$A13.style.opacity = (scrolled - 0.1) / 0.1
} else {
$A13.style.opacity = 1
}

当放大到足够大时,我们需要将 A13 文字再渐出,透视背后的视频。
差不多到50%时,开始文字渐出。以下代码实现:

1
2
3
4
5
6
7
if (scrolled >= 0.5) {
$A13TextBg.style.opacity = (1 - scrolled) / 0.5
$theChip.classList.add('transparent')
} else {
$A13TextBg.style.opacity = 1
$theChip.classList.remove('transparent')
}

此时的效果预览:

See the Pen iPhoneSE_Stage2 by Chang (@alias_e) on CodePen.

但发现还是有个问题,放到最大时,还是不够大。旁边还是有黑边。
所以我们直接在滚动到95%的时候将 the-chip 渐出。

1
2
3
4
5
if (scrolled >= 0.95) {
$theChip.style.opacity = (1 - scrolled) / 0.05
} else {
$theChip.style.opacity = 1
}

最后我们看一看效果,可以看到效果还是比较理想的。

See the Pen iPhoneSE_Stage3 by Chang (@alias_e) on CodePen.

🥳 加载 Disqus 评论