uniapp vue3 h5,微信小程序滚动屏幕元素渐入动画&自定义导航栏

2023-11-19

项目文件下载地址

实际效果如下:
在这里插入图片描述

一、滚动屏幕元素渐入

注意事项:
animate.css需要添加样式兼容微信小程序;
微信小程序滚动时boundingClientRect获取不到标签信息

1、HBuilderX打开uniapp创建的vue3项目,在编辑器下方打开终端输入npm install animate.css --save 安装模块
animate.css官网地址
参考官方文档安装使用animate.css

npm install animate.css --save

在这里插入图片描述

2、main.js中引入animate.css

import 'animate.css';

在这里插入图片描述
3、app.vue中添加全局样式兼容微信小程序
项目中我已将改代码放入base.scss文件中

//animate.css 兼容小程序
page {
--animate-duration: 1s;
--animate-delay: 1s;
--animate-repeat: 1;
}

在这里插入图片描述

4、根据animate.css官网文档给标签添加动画,然后再通过js监听屏幕滚动当标签出现在屏幕可视区时给标签切换class,页面全部代码如下:
main-layout 是自定义组件,除去即可

<template>
	<view class="home-wrap">
		//<main-layout title="首页">
			<view class="animate-item animate__animated " v-for="(item,index) in domList" :id="'item'+item.id"
				:class="item.show?item.showClass:item.hideClass">{{item.text}}</view>
		//</main-layout>
	</view>
</template>

<script lang="ts">
	import {
		defineComponent,
		computed,
		onMounted,
		watch,
		ref,
		getCurrentInstance,
		reactive,
		nextTick,
		toRefs,
		toRef
	} from 'vue';
	export default {
		setup(props,context){
			//dom节点列表
			let domList: {
				id: String | Number,
				text: String,
				show: Boolean,
				showClass: String,
				hideClass: String,
				siteInfo: Object
			} [] = ref([{
				id: 1,
				text: '1',
				show: true,
				showClass: 'animate__fadeInLeftBig',
				hideClass: 'animate__fadeOutLeftBig',
				siteInfo: {}
			}, {
				id: 2,
				text: '2',
				show: true,
				showClass: 'animate__fadeInRightBig',
				hideClass: 'animate__fadeOutRightBig',
				siteInfo: {}
			}, {
				id: 3,
				text: '3',
				show: true,
				showClass: 'animate__fadeInLeftBig',
				hideClass: 'animate__fadeOutLeftBig',
				siteInfo: {}
			}, {
				id: 4,
				text: '4',
				show: true,
				showClass: 'animate__fadeInRightBig',
				hideClass: 'animate__fadeOutRightBig',
				siteInfo: {}
			}, {
				id: 5,
				text: '5',
				show: true,
				showClass: 'animate__fadeInLeftBig',
				hideClass: 'animate__fadeOutLeftBig',
				siteInfo: {}
			}, {
				id: 6,
				text: '6',
				show: true,
				showClass: 'animate__fadeInRightBig',
				hideClass: 'animate__fadeOutRightBig',
				siteInfo: {}
			}, {
				id: 7,
				text: '7',
				show: true,
				showClass: 'animate__fadeInLeftBig',
				hideClass: 'animate__fadeOutLeftBig',
				siteInfo: {}
			}, {
				id: 8,
				text: '8',
				show: true,
				showClass: 'animate__fadeInRightBig',
				hideClass: 'animate__fadeOutRightBig',
				siteInfo: {}
			}, {
				id: 9,
				text: '9',
				show: true,
				showClass: 'animate__fadeInLeftBig',
				hideClass: 'animate__fadeOutLeftBig',
				siteInfo: {}
			}])
		
			// 获取上下文this
			const instance = getCurrentInstance();
			// 获取屏幕高度
			const sysInfo = uni.getSystemInfoSync();
			// 屏幕滚动防抖定时器
			let scrollTimer = null;
			
			const screenScroll = (): void => {
				//屏幕滚动停止后获取dom节点信息,执行动画
				if (scrollTimer) clearTimeout(scrollTimer);
				scrollTimer = setTimeout(() => {
					domList.value.forEach(async (t, i) => {
						await getNodeInfo('item' + t.id).then(res => {
							domList.value[i].siteInfo = res;
						})
						if (i == domList.value.length - 1) {
							loadAni();
						}
					})
				}, 100)
			
			}
			const getNodeInfo = (id: String): any => {
				// 获取位置信息并返回
				return new Promise(resolve => {
					const query = uni.createSelectorQuery().in(instance);
					query.select('#' + id).boundingClientRect(data => {
						// console.log("得到布局位置信息" + JSON.stringify(data));
						// console.log("节点离页面顶部的距离为" + data.top);
						resolve({
							domInfo: data ? data.height : 100,
							domTop: data ? data.top : 100
						})
					}).exec();
			
				});
			}
			const loadAni = (): void => {
				const screenH: String | Number = sysInfo.screenHeight;
				domList.value.forEach((t, i) => {
					if ((t.siteInfo.domTop > 0) && (t.siteInfo.domTop < screenH)) {
						domList.value[i].show = true;
					} else {
						domList.value[i].show = false;
					}
				})
			}
			onMounted(() => {
				screenScroll();
				
			})
		
			return{
				domList,
				screenScroll
			}
		},
		onPageScroll() {
			this.screenScroll();
			
		},
		onReachBottom() {
		   console.log('bottom')
		}
	}
</script>

<style lang="scss">
	.home-wrap{
		overflow: hidden;
		.animate-item{
			border: 1px solid #bbb;
			margin: 10px 10px 100px;
			text-align: center;
			padding: 10px;
		}
	}
</style>

二、uniapp自定义头部导航栏

在这里插入图片描述

1、pages.json中这只导航栏样式为自定义

"globalStyle": {
		"navigationStyle": "custom"
	},

在这里插入图片描述

2、编写头部组件代码

<template>
	<view class="main-wrap" :style="'padding-top:'+(statusBarHeight+titleBarHeight)+'px;'">
		<view class="head-bar">
			//状态栏占位
			<view class="status-bar" :style="'height:'+statusBarHeight+'px'">
				
			</view>
			<view class="title-bar" :style="'height:'+titleBarHeight+'px'">
			//导航左侧返回键
				<view class="title-bar-left">
					<uni-icons type="back" size="30" v-if="back" @click="backPage"></uni-icons>
				</view>
				//导航栏中间标题
				<view class="title-bar-center">
					{{cTitle}}
				</view>
				//导航栏右侧插槽
				<view class="title-bar-right">
					<slot name="titleRight"></slot>
				</view>
			</view>
		</view>
		//导航栏下方页面内容区域插槽
		<view class="main">
			<slot></slot>
		</view>
		
	</view>
</template>

<script lang="ts">
	import { defineComponent, computed, onMounted, watch,ref,getCurrentInstance,reactive,nextTick ,toRefs} from 'vue'
	export default {
		name:"MainLayout",
		props:{
			title:{
				type:String||Number,
				default:''
			},
			back:{
				type:Boolean,
				default:false
			}
			
		},
		created() {
			this.setHeaderHeight();
		},
		setup(props, context){
			let statusBarHeight = ref<Number>(0);
			let titleBarHeight = ref<Number>(0);
			let tabBarHeight = ref<Number>(60);
			
			
			
			const setHeaderHeight =():void=>{
				uni.getSystemInfo({
					success:e=>{
					 let statusBar = 0  //状态栏高度
					      let customBar = 0  // 状态栏高度 + 导航栏高度  
					      let navbar = 0 // 自定义标题与胶囊对齐高度
					      
					      
					      // #ifdef MP
					      statusBar = e.statusBarHeight
					      customBar = e.statusBarHeight + 45
					      if (e.platform === 'android') {
					        customBar = e.statusBarHeight + 50
					      }
					      // #endif
					      
					      
					      // #ifdef MP-WEIXIN
					      statusBar = e.statusBarHeight
					      const custom = wx.getMenuButtonBoundingClientRect()
					      customBar = custom.bottom + custom.top - e.statusBarHeight
					 
					      navbar = (custom.top - e.statusBarHeight) * 2 + custom.height
					      // #endif
					 
					 
					      // #ifdef MP-ALIPAY
					      statusBar = e.statusBarHeight
					      customBar = e.statusBarHeight + e.titleBarHeight
					      // #endif
					 
					 
					      // #ifdef APP-PLUS
					      console.log('app-plus', e)
					      statusBar = e.statusBarHeight
					      customBar = e.statusBarHeight + 45
					      // #endif
					 
					 
					      // #ifdef H5
					      statusBar = 0
					      customBar = e.statusBarHeight + 45
					      // #endif
						  
						  
						titleBarHeight.value = navbar||customBar;
						statusBarHeight.value = statusBar;
				}
				})
			}
			
			const cTitle = computed({
				get:()=>{
					return props.title ;
					},
				set:()=>{}
			})
			
			const backPage = ():void=>{
				uni.navigateBack({
				    //关闭当前页面,返回上一页面或多级页面。
				    delta:1
				});
			}
			
			return {
				setHeaderHeight,
				statusBarHeight,
				titleBarHeight,
				tabBarHeight,
				cTitle,
				backPage
			}
		}
		
	}
</script>

<style lang="scss">
	//@import "@/styles/base.scss";
	.main-wrap {
		display: block;
		position: relative;
		width:100%;
		
		.head-bar{
			position: fixed;
			top: 0;
			left: 0;
			right: 0;
			z-index:999;
			.status-bar{
				background-color: #fff;
			}
			.title-bar{
				display: flex;
				align-items: center;
				justify-content: space-between;
				background-color: $uni-bg-color-nav;
				.title-bar-left,.title-bar-right{
					width: 50px;
				}
				.title-bar-center{
					white-space: nowrap;
					overflow: hidden;
					text-overflow: ellipsis;
					max-width: calc(100% - 100px);
				}
				
			}
		}
		
		
		
		
	}

</style>

3、 main.js全局引用该组件

import MainLayout from "./layout/index.vue"
//vue2
Vue.component("main-layout", MainLayout);
//vue3
app.component("main-layout", MainLayout);

在这里插入图片描述

4、页面上直接使用该组件

<main-layout title="首页" back>
			 <template v-slot:titleRight>
				<text>右插槽</text>
			  </template>
			<text>页面内容</text>
		</main-layout>

结语:有用点赞,无用留言批评

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

uniapp vue3 h5,微信小程序滚动屏幕元素渐入动画&自定义导航栏 的相关文章

随机推荐

  • 函数计算简介

    什么是函数计算 大家都了解 Serverless 并不是没有服务器 而是开发者不再需要关心服务器 下图是一个应用从开发到上线的对比图 在传统 Serverful 架构下 部署一个应用需要购买服务器 部署操作系统 搭建开发环境 编写代码 构建
  • SQL关联表更新

    存在表数据 per user per emp info 需要将per emp info 中的name和post name更新到per user表中 mysql数据库 update per user u JOIN per emp info e
  • 我的英雄之路--转自HERO2008会刊

    HERO2007仍落落在目 HERO2008即将来临 能参加两届英雄大会 甚是荣幸 于是想写一写我的英雄之路 提笔易 落笔难 反复问自己是否配得上 英雄 二字 打开社区 看看自己的排名 虽排名速降 尚位居前列 于是厚起脸皮说说自己的在CSD
  • 【Vue项目实践】实现在线预览word文件、excel文件

    JUST DO IT 目录 一 查看word 1 引用mammoth js 2 页面布局 3 请求URL显示数据 二 查看Excel 1 引用sheetjs 2 页面布局 3 请求URL显示数据 三 项目应用 根据详情后缀分情况显示word
  • 修改CheckBox选择框、设置选择框颜色

    使用组件自带的属性 android buttonTint 可直接设置选择框的颜色 修改选择框选中与未选中时的状态 需设置选择器 selector XML
  • 医学图像公开数据集

    一 医学图像 1 阿里云 天池数据集 https tianchi aliyun com dataset spm 5176 14154004 J 4642415020 16 167b5699EO8yrc https tianchi aliyu
  • IDEA为spring-boot添加热部署

    在IDEA中 可以为spring boot添加热部署 一旦修改了java文件 spring boot会重新编译修改的文件 而不用重启 一 打开pom xml 添加依赖
  • 关于LC电路中电磁振荡过程的一个问题,向各位求教

    关于LC电路中电磁振荡过程的一个问题 向各位求教 复制链接 LC电路关键是产生能量在电感 L 和电容器 C 之间的转换 电感可以维持电流保持不变 电容可以维持两端电压不变 能量就在这个电压与电流之间转换 当电感中有电流时就会产生磁场 电容器
  • 若依框架自定义登录(免密登录)

    1 继承DaoAuthenticationProvider package com ruoyi framework config import org springframework security authentication BadC
  • iOS

    我们有的时候在创建UIView的时候 想要使用xib进行创建视图发现 xib文件不能和UIView文件一起创建 所以 我们要单独创建xib文件 我们选择Empty文件 而不要选择View文件 记得文件名和你之前创建的UIView文件名要一致
  • 简单了解默克尔(Merkle)树

    Merkle树是Ralph Merkle在1988年发明的 旨在构建更好的数字签名 原文是A DIGITAL SIGNATURE BASED ON A CONVENTIONAL ENCRYPTION FUNCTION本篇论文在Weki百科中
  • 各种平台下Perl模块的安装方法

    Perl到了第五版增加了模块的概念 用来提供面向对象编程的能力 这是Perl语言发展史上 的一个里程碑 此后 广大自由软件爱好者开发了大量功能强大 构思精巧的Perl模块 极大地 扩展了Perl语言的功能 CPAN Comprehensiv
  • 交换机access与trunk口

    交换机access与trunk口 转载自 https www cnblogs com weiyikang p 4945914 html 理论知识 以太网端口二种链路类型 Access 和Trunk Access 类型的端口 只能属于1 个V
  • 攻防世界-fileclude

  • Android-小游戏

    Android 打地鼠游戏 前端界面 布局文件 TableLayout 表格布局 TableRow 行 TextView 文本框 ImageView 图片框 java代码 Handler 消息处理 Runnable 建子线程 setOnCl
  • 自定义QMessageBox显示\按钮功能

    QPushButton okbtn new QPushButton QString fromLocal8Bit 确定 QPushButton cancelbtn new QPushButton QString fromLocal8Bit 取
  • Redis和MySQL的数据同步问题

    Redis的工作流程 1 前台发送请求 后台接口去查询 2 先去查询Redis缓存里面有没有数据 如果有数据 就直接返回数据 3 如果Redis缓存里面没有数据 就去查询数据库 在数据库中查到数据以后 保存到Redis缓存中 然后在返回前台
  • 5、面向对象的设计思想

    一 面向对象设计思想 1 1 面向过程的设计思想与面向对象的设计思想 例如 我要去新疆 面向过程 我开车 我挂挡 我踩油门 我过河北 我过陕西 面向对象 我命令车去新疆 车怎么去不关我事 信息封装在这这个类的内部 我不用去了解车整个开动的过
  • SATA M.2 NGFF PCIE AHCI NVME SSD固态硬盘的接口、总线和协议区分

    总线 协议 说接口之前先说总线 民用产品的硬盘总线多为 SATA 和 PCIe SATA 总线只能使用 AHCI 协议 NVME 对比 AHCI 的优势在于 低延时 低功耗 更适合固态硬盘 PCIe总线 可以使用 AHCI 也可以使用更高效
  • uniapp vue3 h5,微信小程序滚动屏幕元素渐入动画&自定义导航栏

    项目文件下载地址 实际效果如下 一 滚动屏幕元素渐入 注意事项 animate css需要添加样式兼容微信小程序 微信小程序滚动时boundingClientRect获取不到标签信息 1 HBuilderX打开uniapp创建的vue3项目