页面过渡是网络上最复杂的事情之一,有充分的理由。从一个页面导航到另一个页面时涉及很多事情:安装新页面,仅在过渡完成后才下马,处理共享状态,更新URL,处理浏览器导航等...
...框架多年来一直试图解决这个问题,但今天仍然是一个挑战。好消息是,由于Chrome提出的Shared Element Transition API,我们很快就可以更轻松地做到这一点。
但是在那之前,我们还有更多工作要做!
以我的portfolio为例,让我们看看Svelte可以如何做页面过渡!
简要
使Instagram移动应用程序成功的事情之一就是它的出色UX。特别是“故事”。它在各处复制,Messenger,WhatsApp,Google Photos等。故事打开,关闭和从上一个/下一步移动的方式使导航变得平稳且自然。
让我们看一下要复制的动画:
- 当我单击其缩略图时,这个故事会打开。
- 我可以滑动或单击故事以转到下一个/上一个。
- 我可以拖延故事以返回主页。
那么,我们如何使用Svelte在我们的网站上创建类似Instagram的体验?
Svelte和Sveltekit工具包
svelte提供了特殊的动画属性,可以应用于元素上以定义其在坐骑和下马上的行为:
<div in:fn={params} out:fn={params} />
应用out
Prop将等到执行fn
后才从DOM删除元素。
Svelte动画工具包的优势在于,用于动画的功能可以是一种自定义功能,可以使您可以很好地控制过渡。
使用Sveltekit,当组件安装/下卸下或Svelte key更改时,in
和out
动画被调用。
因此,如果有URL更改,但是该组件保持不变(例如,如果我们从 /story /1转到 /story /2,则更改了URL,但是显示这两个页面的组件是相同的),我们需要使用一个key
:
import { page } from "$app/stores";
...
{#key $page.params.story}
<div in:fn={params} out:fn={params} />
{/key}
不同的动画取决于导航
在我们的情况下,我们希望“故事”能够以不同的位置进行动画动画:
- “左/右滑动”如果我们下一个/上一个
- “扩展进出”如果我们进出故事
多亏了自定义Svelte动画功能,我们可以处理所有这些方案:
<script>
$: transitionsConfig = [
{
condition: c => c.toHomepage,
transition: customScale
},
{
condition: c => c.toHigherIndex,
transition: customFly,
inParams: { x: width, duration: 400, opacity: 1 },
outParams: { x: -width, duration: 400, opacity: 1 }
},
{
condition: c => c.toLowerIndex,
transition: customFly,
inParams: { x: -width, duration: 400, opacity: 1 },
outParams: { x: width, duration: 400, opacity: 1 }
}
];
$: config = transitionsConfig.find(({ condition }) => {
const { from, to } = $navigating;
const fromIndex = parseInt(from.params.story);
const toIndex = parseInt(to.params.story);
// If there is no story index in the pathname...
if (!toIndex) {
// ...it means we are going to the homepage: "/".
return condition({
toHomepage: true
});
}
return condition({
toHigherIndex: fromIndex < toIndex,
toLowerIndex: fromIndex > toIndex
});
});
$: ({ transition, inParams, outParams } = config);
</script>
<div in:transition={inParams} out:transition={outParams} />
这样,您可以“解决”用户导航的正确过渡。