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


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

    前言

    最近在优化H5页面,我注意到当开发完成的移动端H5页面嵌入到微信小程序或者原生app中时,当触发页面路由切换会与原生app看上去有点格格不入,因为H5页面切换路由时是直接替换了原来页面的内容,在视觉效果上看到的是页面的跳转变化都是在同一个页面上,并没有一级二级页面这种视觉差,因此,参考了原生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包裹,实现代码如下:

      <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>
      
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

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

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

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

    import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router';
    
    const routes: Array = [
        {
            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;
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

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

    // 监听当前路由的变化
    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 }
    );
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    3、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);
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86

    注意

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

    #app>div {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    写在最后

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

  • 相关阅读:
    shell脚本获取文件中的版权(Copyright)
    Linux——网络配置
    第一篇 如何选择深度学习主机
    【Nacos】1.1 从单体架构到微服务
    超详细反编译python打包的exe
    Android --- Activity
    网络编程中的重难点:套接字的应用和理解
    三万字带你了解那些年面过的Java八股文
    自定义字符串排序
    shell编程之命令替换
  • 原文地址:https://blog.csdn.net/qq_34185872/article/details/133900357