动手实现H5仿原生app前进后退切换效果

动手实现H5仿原生app前进后退切换效果

前言

最近在优化H5页面,我注意到当开发完成的移动端H5页面嵌入到微信小程序或者原生app中时,当触发页面路由切换会与原生app看上去有点格格不入,因为H5页面<router-view>切换路由时是直接替换了原来页面的内容,在视觉效果上看到的是页面的跳转变化都是在同一个页面上,并没有一级二级页面这种视觉差,因此,参考了原生app中的页面切换效果,我打算将已经成熟的H5项目改造一下,优化视觉上的体验效果。 话不多说,先上效果:

实现思路

在观察原生APP页面切换时不难发现,其实就两个效果,在路由前进时旧的页面需要从中心往左平移直至隐藏,新的页面则需要右边隐藏状态平移到屏幕中央。在页面返回到时候做相反的操作,要返回的页面从左边隐藏平移到屏幕上,原来的页面平移到右边隐藏。由于项目用的是Vue3,我就用vue作为代码演示。

transition 组件

由于vue提供了一个过渡动画的标签transition,那么在这里我就不重复造轮子了,直接用这个标签来实现过度效果。简单介绍下transition这个标签。 1、必需只能包含一个根元素 2、主要是针对于v-if、v-show或路由动态组件,增加动态过渡效果 3、可根据name自定义过渡动画效果 4、自定义动画类名 -enter、 -leave、-enter-active、 -leave-active、-enter-to、-enter-to

具体使用方法可到官网查看,这就不过多介绍了。

开始实现

App.vue 改造

为了实现全局的页面切换效果,所以直接在App.vue中将router-view包裹,实现代码如下:

html 复制代码
  <router-view v-slot="{ Component }">
    <transition :name="transName">
      <keep-alive :include="includeRoute">
        <component :is="Component" :key="$route.name" v-if="$route.meta.keepAlive" />
      </keep-alive>
    </transition>
    <transition :name="transName + 'normal'">
      <component :is="Component" :key="$route.name" v-if="!$route.meta.keepAlive" />
    </transition>
  </router-view>
  

注意,这里使用两个transition是需要考虑如果有部分页面是keep-alive,有部分不是的情况,需要赋予不同的name值

判断当前路由前进还是后退

1、首先在定义路由时需要增加路由层级,用于后续判断页面是前进还是后退。代码如下:

javascript 复制代码
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';

const routes: Array<RouteRecordRaw> = [
    {
        path: '/',
        name: 'app',
        redirect:'/home',
    },
    {
        path: '/home',
        name: 'home',
        component: () => import(/* webpackChunkName: "home" */ './home.vue'),
        meta: {
            title: '首页',
            keepAlive: true,
            deepth: -1
        }
    },
    {
        path: '/page1',
        name: 'page1',
        component: () => import(/* webpackChunkName: "page1" */ './page1.vue'),
        meta: {
            title: 'page1',
            keepAlive: true,
            deepth: 1
        }
    },
    {
        path: '/page2',
        name: 'page2',
        component: () => import(/* webpackChunkName: "page2" */ './page2.vue'),
        meta: {
            title: 'page2',
            keepAlive: false,
            deepth: 2
        }
    },
   
];

const router = createRouter({
    history: createWebHistory('/'),
    routes
});

export default router;

2、根据路由切换,判断页面的前进后退状态,动态改变transition的name,用来实现不同的过渡效果

typescript 复制代码
// 监听当前路由的变化
watch(
  () => router.currentRoute.value,
  (newValue: any, oldValue: any) => {
    if (newValue?.meta?.deepth && oldValue?.meta?.deepth) {
      if (oldValue.meta.deepth <= newValue.meta.deepth) {
        transName.value = 'push';
      } else {
        transName.value = 'back';
      }
    }
  },
  { immediate: true }
);

3、css部分实现,主要定义页面前进后退时的动画效果

css 复制代码
.push-enter-active {
  animation-name: push-in;
  animation-duration: 0.5s;
}

.push-leave-active {
  animation-name: push-out;
  animation-duration: 0.5s;
}

.pushnormal-enter-active {
  animation-name: push-in;
  animation-duration: 0.5s;
}

.pushnormal-leave-active {
  animation-name: push-out;
  animation-duration: 0.5s;
}




@keyframes push-in {
  0% {
    transform: translate(100%, 0);
  }

  100% {
    transform: translate(0, 0);
  }
}

@keyframes push-out {
  0% {
    transform: translate(0, 0);
  }

  100% {
    transform: translate(-100%, 0);
  }
}

.back-enter-active {
  animation-name: back-in;
  animation-duration: 0.5s;
}

.back-leave-active {
  animation-name: back-out;
  animation-duration: 0.5s;
}

.backnormal-enter-active {
  animation-name: push-in;
  animation-duration: 0.5s;
}

.backnormal-leave-active {
  animation-name: back-out;
  animation-duration: 0.5s;
}

@keyframes back-in {
  0% {
    width: 100%;
    transform: translate(-100%, 0);
  }

  100% {
    width: 100%;
    transform: translate(0, 0);
  }
}

@keyframes back-out {
  0% {
    width: 100%;
    transform: translate(0, 0);
  }

  100% {
    width: 100%;
    transform: translate(100%, 0);
  }
}

注意

为了实现两个页面能左右切换,所以在定义每个页面样式时需要使用fixed布局

css 复制代码
#app>div {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
}

写在最后

在前端开发中通过实现一些动态效果,在用户使用体验上都能得到较大的改善,作为前端页面优化的一部分,有更多的动画效果值得我们花时间去研究。欢迎点赞收藏,关注我,了解更多的前端知识。

相关推荐
T1mzhou6 分钟前
ARM64 Linux 6.10内核启动流程2-rootfs 怎么挂上
linux·服务器·前端
小小尚@1 小时前
WebGIS/ECharts 地图开发|MapLand 在线行政区划边界一键下载 GeoJSON 工具
前端·javascript·echarts
默_笙2 小时前
🚍 一条 Todo 的奇幻漂流:TypeScript 全栈类型安全的"护照检查"
前端·javascript
计算机魔术师2 小时前
NVIDIA 以 129.3 亿美元收购 Hugging Face
前端
平头哥技术团队2 小时前
Day 01 | 用 HTML 写第一个网页:双击就能在浏览器打开
前端
weixin_422555423 小时前
el-menu子菜单点击就被激活,恢复之前的激活状态
javascript·vue.js·elementui
计算机魔术师3 小时前
两年翻45倍!英伟达靠买买买建成千亿投资帝国
前端
paopaokaka_luck3 小时前
基于springboot3+vue3的精准扶贫管理系统(AI 问答、ECharts 图形化分析)
前端·人工智能·echarts
l1m0_3 小时前
智能电动自行车管理后台实战:AI生成页面与React组件化技巧
前端·react.js·ui·ai·设计
Patrick_Wilson4 小时前
为什么gitlab的MR会默认有一个merge commit
前端·git·gitlab