让我们一起去太空旅行,好吗?
思考应用程序交互中的视觉关系可以帮助提供令人愉悦的用户体验。这一切都始于屏幕的布局。
我们将使用核心版本的“Vanilla TypeScript”来进行说明,但这适用于所有版本。
在布局第一个页面时,我们知道我们希望地球移动到它在第二个页面上的位置,而太空人的面罩则直奔我们而来,露出第二个页面的静止画面。
我们可以用以下方式表示它 - 省略 css 细节,只关注布局标记结构 - 查看 上面的 StackBlitz 示例 与 css
<GridLayout rows="3*, 2*">
<image
src="~/assets/Earth.png"
sharedTransitionTag="earth"
width="75%"
stretch="aspectFit"
></image>
<image
src="~/assets/SpaceMan.png"
sharedTransitionTag="spaceman"
stretch="aspectFill"
></image>
<GridLayout rows="160,auto,auto,auto,*" sharedTransitionTag="title">
<label row="1" text="SPACE" />
<label row="2" text="TRAVEL" />
<button row="3" text="TICKETS AVAILABLE" width="55%" tap="{{ open }}" />
</GridLayout>
<GridLayout
row="1"
rows="auto,*"
columns="auto,*"
sharedTransitionTag="infobox"
>
<ContentView width="150" height="100">
<image
src="~/assets/Astronaut.jpg"
width="150"
height="100"
stretch="aspectFill"
></image>
</ContentView>
<StackLayout col="1">
<label text="98% RATING" />
<label text="FIND OUT MORE" />
</StackLayout>
<label row="1" colSpan="2" text="{{descriptionText}}" textWrap="true" />
</GridLayout>
</GridLayout>
遵循 GridLayout 文档,我们使用一个 2 行网格来表示一般布局,其中 1 行占用 3 倍可用空间,3*
,其余占用 2 倍可用空间,2*
。
在第一行中,我们把地球图像放在太空人图像的下面(在这种情况下,像 Photoshop 文件一样分层),以及我们的“太空旅行”文字,按钮层叠在上面。
在第二行中,我们有一个详细的描述区域。
我们知道我们想要在地球和太空人图像上进行一些关系视觉运动,因此我们用 sharedTransitionTag
值声明它们。
<image
src="~/assets/Earth.png"
sharedTransitionTag="earth"
width="75%"
stretch="aspectFit"
></image>
<image
src="~/assets/SpaceMan.png"
sharedTransitionTag="spaceman"
stretch="aspectFill"
></image>
我们还希望“太空旅行”标题和“票务信息”按钮一起向左移动,当显示下一页面时,因此我们将它们包含在一个布局容器中,我们可以为它声明 sharedTransitionTag
<GridLayout rows="160,auto,auto,auto,*" sharedTransitionTag="title">
<label row="1" text="SPACE" />
<label row="2" text="TRAVEL" />
<button row="3" text="TICKETS AVAILABLE" width="55%" tap="{{ open }}" />
</GridLayout>
最后,我们希望详细的描述区域向下移动并让路,因此我们也为它放置 sharedTransitionTag
<GridLayout
row="1"
rows="auto,*"
columns="auto,*"
sharedTransitionTag="infobox"
></GridLayout>
使用 SharedTransition API,我们可以自定义我们希望共享元素过渡的方式。
import { SharedTransition } from '@nativescript/core';
// setup page navigation to move to a new "earth-view" we will layout in a moment
page.frame.navigate({
moduleName: 'earth-view',
// we define our transition here
transition: SharedTransition.custom(new PageTransition(), {
// where the page we're moving away from should end up
pageEnd: {
// on iOS, we can define "independent" tag movement
sharedTransitionTags: {
// fade spaceman out while moving and scaling up
spaceman: {
opacity: 0,
y: 20,
scale: {
x: 6,
y: 6,
},
},
// fade title out while moving off to the left
title: {
opacity: 0,
x: -200,
},
// fade infobox out while moving it down and out
infobox: {
opacity: 0,
y: 800,
},
},
},
// how the page returns back
pageReturn: {
// we use duration to override default spring settings
// in this example, looks better with linear duration animation
duration: 600,
},
}),
});
在布局第二个页面时,我们只需要考虑设计中的关系元素,并按我们想要的方式进行布局。
<GridLayout rows="*, *, *, *">
<GridLayout columns="auto,auto">
<image
src="~/assets/back.png"
tap="{{close}}"
stretch="aspectFill"
width="20"
height="20"
/>
<button col="1" text="Back" tap="{{close}}" width="50" />
</GridLayout>
<GridLayout row="1" rowSpan="2" rows="auto,auto,auto">
<label text="EARTH" />
<label
row="1"
text="Earth is the third planet from the Sun and the only object in the universe known to harbor life."
textWrap="true"
width="70%"
/>
<image
row="2"
src="~/assets/Moon.png"
stretch="aspectFit"
width="80"
height="80"
/>
</GridLayout>
<GridLayout rows="*" row="2" rowSpan="2">
<image
src="~/assets/Earth.png"
stretch="aspectFit"
sharedTransitionTag="earth"
/>
</GridLayout>
</GridLayout>
这个例子最有趣的地方或许在于,我们只用 sharedTransitionTag="earth"
声明一个视图,因为它同时存在于页面 A 和页面 B 上。这样做可以让地球从它在页面 A 上的位置流畅地过渡到它在页面 B 上的更大的新位置。
动画的其余部分实际上由提供的 SharedTransition.custom
选项覆盖,对于 iOS,它仅在页面 A 上定义了各种 sharedTransitionTag
元素,以根据这些选项进行动画处理。
那么如果 iOS 支持仅在一个页面上存在的“独立”标记元素,而不存在于另一个页面上,那么如何处理 Android 呢?
注意:Android 的“独立”标记元素将在未来的核心版本中得到支持。
解决方法实际上很简单。您可以在标记的 <android>
部分内包含您希望 Android 与之创建关系的视图布局。因此,我们可以简单地为包含我们想要动画的另一个 sharedTransitionTag
的部分执行此操作,例如
<android>
<GridLayout rows="3*, 2*" rowSpan="4">
<image
src="~/assets/SpaceMan.png"
stretch="aspectFill"
sharedTransitionTag="spaceman"
scaleX="8"
scaleY="8"
translateY="940"
></image></GridLayout
></android>
在 Android 上,当导航到页面时,它现在将找到这些关系 sharedTransitionTag
,并根据其视图声明的位置进行动画处理。
这个例子说明了 @nativescript/core 中共享元素过渡的 versatility,适用于 iOS 和 Android,让您实现视觉上令人惊叹的效果。
您有一些关于真正引人入胜的视觉效果的想法吗?与社区分享,并在 Twitter 上添加 #nstricks
标签,我们期待看到您想出的美丽作品!