前言
在做移動(dòng)端項(xiàng)目的時(shí)候,每次進(jìn)行push操作,頁面都是一閃切到下個(gè)界面,整個(gè)體驗(yàn)十分H5,尤其是嵌入APP的Hybrid項(xiàng)目,這種體驗(yàn)很容易讓用戶發(fā)覺這是一個(gè)H5頁面,那我們怎么樣才能解決這種突兀的轉(zhuǎn)場呢?
思考
之前用過ionic3開發(fā)過一些項(xiàng)目,為了支持APP的熱更新功能
作為UI框架,他們在過場動(dòng)畫方面下足了功夫,讓整個(gè)APP體驗(yàn)提升了不少
所以我也希望可以在vue項(xiàng)目中加入絲滑的過場動(dòng)畫,來承上啟下
剛好Vue官方也提供了專門處理動(dòng)畫的<transition>組件
我們就嘗試用該組件來完成頁面的轉(zhuǎn)場動(dòng)畫
動(dòng)畫形式主要參考iOS系統(tǒng)push頁面時(shí)的過渡效果

解決方案
代碼樣例依賴:
"vue": "^3.0.5",
"vue-router": "^4.0.11"
"vite": "^2.4.4"
1、動(dòng)畫部分解析
A -> B , A在下,B在上,且B左側(cè)增加陰影
A從(0, 0)向左移50%
B從(0, 100%)向左移100%B -> A , A在下,B在上,且B左側(cè)增加陰影
A從(-50%, 0)向右移50%
B從(0, 0)向右移100%整個(gè)動(dòng)畫過程是有漸變蒙版,以及動(dòng)畫的貝塞爾曲線,這里忽略蒙版變化,貝塞爾也選擇常用的內(nèi)置
ease-out
2、實(shí)現(xiàn)動(dòng)畫內(nèi)容
- css部分:按照上面分解的內(nèi)容,可以較容易的實(shí)現(xiàn)
這里有幾個(gè)遇到的坑:
1、頁面切換動(dòng)畫執(zhí)行from頁面白屏
因?yàn)槭俏臋n流的原因,老頁面被新頁面擠到下面去了,所以使用absolute讓其定位到應(yīng)該出現(xiàn)的位置
2、陰影設(shè)置的問題
需要在初始狀態(tài)和active狀態(tài)都設(shè)置陰影,以避免陰影出現(xiàn)漸變
.slide-right-enter-active,
.slide-left-enter-active,
.slide-right-leave-active,
.slide-left-leave-active {
/* 這里保持動(dòng)畫過程中的陰影 */
box-shadow: -20px 0 20px 0px rgba(0, 0, 0, 0.1);
will-change: transform;
transition: all 0.5s ease-out;
/* 這里為了解決入棧出棧時(shí)的白屏現(xiàn)象 */
position: absolute;
}
.slide-right-enter-from {
/* 這里設(shè)置0,為了避免一開始頁面內(nèi)容一閃而過的情況 */
opacity: 0;
transform: translateX(-50%);
}
.slide-right-leave-to {
z-index: 100;
/* 這里為了優(yōu)化陰影溢出屏幕,不至于突然消失 */
transform: translateX(102%);
}
.slide-right-leave-from {
box-shadow: -20px 0 20px 0px rgba(0, 0, 0, 0.1);
}
.slide-left-enter-from {
z-index: 100;
transform: translateX(100%);
box-shadow: -20px 0 20px 0px rgba(0, 0, 0, 0.1);
}
.slide-left-leave-to {
opacity: 0.4;
transform: translateX(-50%);
}
- 動(dòng)畫設(shè)置完成了,接下來需要判斷動(dòng)畫觸發(fā)邏輯,前進(jìn)還是后退
這里我采用了路由跳轉(zhuǎn)設(shè)置params.routeMode的方式來決定動(dòng)畫形式
const router = useRouter();
router.beforeEach((to, from) => {
const toDepth = to.params.routeMode;
if (toDepth === "push") {
to.meta.transitionName = "slide-left";
} else if (toDepth === "pop") {
to.meta.transitionName = "slide-right";
}
return true;
});
- 最后是模板,路由入口設(shè)置動(dòng)畫
<router-view v-slot="{ Component, route }">
<transition :name="route.meta.transitionName">
<component :is="Component" />
</transition>
</router-view>
結(jié)果展示

完整Demo地址:https://github.com/ZTStory/vue_page_transition
在線演示:https://ztstory.github.io/vue_page_transition/#/
ps:如何搭建自己GitHub Pages?看這里
歡迎大家互相學(xué)習(xí),喜歡別忘記star哦!