设计

由设计师开发的新网站,背后的思考故事
Vivien·2023 年 11 月 23 日

上个月初,我们发布了全新的 exping 官网。经过一年的稳定迭代后,exping 增加了很多新特性,也受到了很多用户的喜爱,甚至一度登上了 App Store 图形和设计分类的第二名,当我们意识到一些新用户想要了解「exping 是什么?」,却只能访问我们已经远远「落后」的官网时,我们认为是时候要把官网的更新安排到计划中了。

IMG_7766.png

在这次官网的改版中,我们对网站的信息架构进行了全面的梳理和优化,让你能更加直观快速地找到需要的信息,大大提升了访问效率,同时也将我们在这一年中对视觉和品牌形象方向的调整融入到新的官网设计中。最终官网不但拥有了一个全新的设计,还增加了博客更新动态帮助中心等很多新内容。

设计和开发这个产品对我而言也是一段很特别的旅程,是的,我称之为「产品」,对于它有很多内容我可以展示,但在这篇文章里我想重点地聊聊全新首页的一些动画和交互,这也能看到我们如何把 exping 的理念融合到产品、设计和开发的过程中。

浏览,而非操作

在视觉设计的过程中,我们非常兴奋地设计了很多可交互的元素在网页上,然而随着开发的进行和浏览其他产品网站的增多,我发现这可能不是一个合适的选择。浏览网站的主要行为是获取信息,而非主动操作,如果内容大都需要主动交互才能触发,网页很多内容将会处于一种「待触发」的状态而让整体处于一种「未完成」的样子,这真是糟糕透了。主动触发的交互适合作为餐后「甜点」,而不应该是「主菜」。

尽管已经进入开发了,我还是决定对首页的交互重新设计。当然也随着一边开发一边融入更多新的设计想法,我们的工作台变得凌乱不堪,我的另一位搭档曾称之为「爱因斯坦的桌面」。

story-desktop.png

而由一位设计师来驱动开发这件事,后面也给我们带来了一些麻烦,不过现在我们还是先把重点放回首页的动画中去。

基于滚动的动画

基于我的想法,第一步调整是把很多需要主动触发的交互调整为随着滚动而触发的动画。聊到基于滚动的动画,有一些不错框架可以供我们选择,比如 GSAP ScollTrigger,Framer Motion 和 CSS 原生支持的新属性。

Chrome 在半年前公开了一些新的网页动画特性,其中一点提到了基于滚动的动画,Google 的一位工程师创建了 Scroll-driven Animations 这个网站来讲解这个新特性,并提供一个插件 Scroll-Driven Animations Debugger 来协助开发。

我最终选择了在另一个项目中我曾使用过的 GSAP。

GSAP 是一个强大的 JavaScript 动画库,可以构建在各种浏览器运行的高性能动画,能以任何 JavaScript 能触及的对象如 CSS, SVG, canvas, React, Vue, WebGL, 颜色, 字符串等来创建动画。前段时间 GSAP 官网更新了全新的视觉,推荐大家了解。

事实上更重要的原因是 GSAP 中的 Timeline 写法很适合设计师,GSAP 的写作语法和页面的语法稍微有点不一样,初看时有一种又要学习一门新语言的感觉,但 Timeline 的语法一旦上手后,却像我熟悉的在 AE 中使用时间轴设计思路一样,我的脑海里浮现出了一句话:Design with code.

story-1.png

更自然的动画🌟

除了上面提到的把很多交互调整为基于滚动的动画外,每一部分的标题、描述和行动按钮其实也有更基础的自然出场动画。这是我们计划之外花了更多时间的部分,也是我在这个网站里最喜欢的效果之一。这也让我亲自体会到从「它看起来这样」到「它实际这样」中间隔着多少的细节。

OK,让我们开始吧。

自然而然地出现

当谈论到自然的时候,第一件事则是自然而言地看见,我希望达到的效果是「当你应该看到它的时候,它就自然地出现在你的视线中」,这句话说出来很简单,但实现则是另一回事。

首先要定义的是什么叫做「当你应该看到它的时候」,在我不断地去浏览不同页面的时候,我发现这件事情可以基本等同于我什么时候看完当前部分准备去看下一个部分。再换个说法是,当下一个部分从页面底部出现并滚动到到什么位置时,会到达我的视线范围。理解了这件事情后剩下的就是通过调试不同的位置数值来达到自然的感受。

story-2.png

下一件事需要定义你看到的「它」,指这一个部分还是标题单一个元素,这两者之间有一个内边距的差别的,尽管很微小,但也是我需要考虑的要素,这个问题没有正确与否之分,我最终选择了以元素自身作为 Trigger。

story-3.png

一个和多个

在上一个部分,我们设计好了单个元素(标题)的出场动画,但是一个部分里往往有几个标准的元素:标题、描述、行动按钮和内容,那它们的动画也要遵循以自身为 Trigger,当用户应该看到他们时才出现的规则吗?

这样的做法是不合适的,如果用户在标题出场后停止滚动,结果就会变成标题已经出现,而其他元素因为还没到达我们定义的「自然点」,标题以下的区域空白一片的情况,尽管这是个很少的出现的情况。

我的处理方式是将这几个元素视为一个整体,统一以标题为 Trigger ,以此来激活一个连续出现的时间线动画,以此来处理多个元素出现的动画。

story-4.png

上面的元素排列都有一个共同的特征,他们是垂直分布的,所以它们会从上到下依次播放动画,那么左右分布的元素呢?是不是也要给他们依次出现的动画,在这里我的答案是 no,他们的动画顺序会像下面示意的一样。

story-5.png

一遍或多遍

让我们继续完善这个动画:这个动画只需要播放一次吗?当这个部分分别从上方和下方离开视线,再次重新进入视线后,它的动画需要再次播放一遍吗?这同样是一个没有标准答案的问题,我的处理方式是:

  • 往上离开视线并重新进入视线:不重复播放动画

  • 往下离开视线并重新进入视线:逆向运行动画并在出现时再次播放动画

story-6.png

在实现上这件事情反而非常好解决,因为 GSAP 提供了几个简单的配置来处理这件事情,这也是我选用 GSAP 的理由之一。

设计师都讨厌线性动画

这当然是一句玩笑,但是我们需要处理的最后一件事和这一点有关。为了让动画的过渡更缓和,设计师在设计动画时都喜欢使用 Ease 而非 Linear 曲线。然而,在这里就遇到了行不通的情况,我们基本可以认为用户在页面滚动时是匀速滚动的,为了让基于滚动的动画和用户的滚动速度关联起来,所有滚动驱动的动画都需要使用对应的 Linear 曲线,不然会产生微妙的违和感。

story-7.png

举个例子:当你在滚动前 50px 时,一个元素从 100% 缩放到了 110%,但是继续滚动 50px 时元素却从 110% 缩放到了 150%,这会让你产生一种错觉:怎么滚动同样的距离,动画怎么突然变得那么快,是不是我错过了什么?

这就是为什么我要用设计师最讨厌的 Linear 曲线的原因。

结束了吗?

当你以为已经处理完这个基础动画的问题了,这时候其实还有更多的细节问题在等着你,不要忘记了,我们这是在做一个几乎哪里都能访问网站,面对的视口尺寸千奇百怪。我们前面一直在讨论的情况仅仅是针对常规宽屏屏幕的情况。如果我们面对的是一个高度大于宽度的窗口,本应该位于第二屏或第三屏的内容从一开始就出现在视线内了要怎么处理呢?

另一件事情是,当高度变得很高时,之前我们所定下来的「自然点」,在这个比例下还会是自然的位置吗?

story-8.png

这两个提问,以及上面我提出的一系列思考,都是一些没有标准答案的问题,但我还要花这么大篇幅来讲述,更多地是想说明在「视觉语言」对应到实现的「代码语言」时,中间是有多少的细节是我们在前往完美的道路上需要考虑的。

游乐场

在开发的过程中,我们记录了很多想法,甚至可以说这个首页是我们的一个游乐场,只要在我们的能力之内,我们可以放心地随意建设和探索,所以我曾开玩笑说过「这是一个正经工程师无法开发出来的网站」。

亮点介绍部分

在第三屏的亮点介绍部分,我们在背景放置了一个在不断变化的椭圆。这个动画的实现也很有意思,它本质上是一个矩形,而在 CSS 里,我们都知道 border-radius 属性可以单独设置多个不同的值的,而更进一步的是,这个参数可以细致到单个圆角中的两条边的弧度。

更具体的介绍可见这篇文章:CSS Border-Radius Can Do That?

给半径增加这个更细致的调节后,再增加几个关键帧,基础动画就完成了。但是等等,现在它看起来像是四个角的半径独立在运动,完全没有流动的感觉。

story-ball-1.gif

解决这个问题的方法是给整个元素加上了一个旋转动画,两个动画叠加后看起来就像边缘在流动一样。

story-ball-2.gif

协作功能部分

在 exping 里,你可以开启协作功能和其他创作者一起完成同一张地图,在这个功能的介绍部分,你可以同时看到浏览器和手机界面,我为它们设计了一个小互动。

要介绍协作功能,理所应当要演示协作同步数据的能力。这里使用了 GSAP 的另一个插件 Draggable,可以方便地实现拖动和边界限制。这里精妙的地方是处理两个元素位置同步变化。

story-co.gif

我一开始陷入了一个误区,想要用可拖动元素的原始坐标来作为原始值,通过数值运算来计算变换后的位置,直到查看了拖动后的代码才发现,拖动的效果实际上是在原来的元素新增了一个 transform: translate3d(x, y, z) 属性,我只需要属性中的数值数值提取出来,添加同样的变换到到另一个元素上就完成了。

还有一个不能忽视的点是,两张地图和元素的大小不一样,所以需要添加的变化还需要增加一个缩放比例。

story-9.png

惯性滚动

在移动端浏览网页时,浏览器默认带有了惯性滚动的效果,我们把这个效果同样带到了电脑网页上。本来用 GSAP 的 ScrollSmoother 插件可以很方便完成,不过可惜这个插件需要 Club 会员才能使用。我们在此选用了Lenis,最终的效果也很让我们满意。

惯性滚动的效果只添加到了首页上,其他内容页面是没有的,希望去对比的朋友们,可以用这个博客页面和首页对比就能感受出来区别了。

Bien-glass

这是我在网上四处闲逛时发现的一条推文:一个更自然的玻璃反射效果。背景模糊本来只有当两个元素重叠时才能显示出来,而这个改动可以让两个元素接近时已经带有反射的效果。

这真的太酷了,我花了大约半小时马上把它添加到了我们的网站中,但很可惜,它暂时只能用在非首页上,和上面的应用页面刚好相反。

story-11.png

网站里的交互和设计细节还远不止上面提到的这些,正如这个部分一开始提到的,这像是我们的一个游乐场,我们在这里玩得很快乐。

是时候发射了🚀

上文提到过,作为一个设计师去跟进整个项目的进程,给我们带来的一个麻烦:虽然我希望能平等地关注我们的方向、内容和设计开发等各种事情,但还是会不自觉地过于关注视觉呈现,不仅是交互动画,在开发中途还调整过某些部分的设计稿,我们总会觉得还有更多的想法可以添加上去,以及我们总能找到更多可以优化的地方,比如惯性滚动的阻尼值是不是可以再稍微调整?比如文案是不是可以继续优化?

然而作为一个要推出的产品去考虑,我必须选择一个合适的时机停下来。当我决定了这件事情后,我们在某一天的晚上,按下了发射按钮,然后对外推出了你所看到的这个官网。

顺便感谢我的另一位搭档——AI,帮我解决了一些开发中的疑问,让我完成首页的开发这件事成为了可能。

新的官网在上线后也达到了我们的预期,浏览量与之前相比大幅提升,这达成了我们的目标之一。在未来我们还会继续打磨我们的产品,包括 exping 和这个网站,有兴趣的朋友们可以使用 RSS 订阅我们的博客更新动态

在最后我想表达的是,不仅是出于工作需要,我们同样怀着乐趣和热情建造了这个新的官网,希望你能喜欢它并亲自去挖掘里面的细节。如果这篇文章或者这个网站能引起你的兴趣去尝试一下我们的产品,那真的太好了。