uniapp实现楼层导航 ,滚动定位,锚点导航

news2024/11/24 18:38:59

uniapp实现楼层导航的核心技术要点:

1、scroll-view作为视图容器,

2、用其属性scroll-into-view,用于完成点击联动

在这里插入图片描述

3、uni.createSelectorQuery().selectAll();获取右侧所有元素信息,获取top值存入数组,用于计算滑动时需要的联动

在这里插入图片描述
代码示例(可直接复制查看)

<template>
	<view class="bodys">
		<view class="scroll_box" id="scroll_box">
			<scroll-view :style="{ height: scrollHeight + 'rpx' }" scroll-y='true' class="left_box"
				:scroll-into-view="leftIntoView">
				<view class="left_item" v-for="(item,i) in leftArray" :key='i' @click="onLeft" :data-index="i"
					:id="'left-'+i" :class="{select:i == leftIndex}">
					{{item}}
				</view>
			</scroll-view>
			<scroll-view :style="{ height: scrollHeight + 'rpx' }" @scroll="mainScroll" :scroll-into-view="scrollInto"
				scroll-y='true' class="right_box" scroll-with-animation="true">
				<slot></slot>
				<view class="right_item" v-for="(item,i) in rightArray" :key='i' :id="'item-'+i">
					<view class="rigth_title">
						{{item.title}}
					</view>
					<view class="lis" v-for="(items,j) in item.list" :key='j'>
						{{items}}
					</view>
				</view>
				<view class="fill-last" :style="{ height: fillHeight + 'px' }"></view>
			</scroll-view>
		</view>
	</view>
</template>

<script>
	export default {
		name: "side-navigation",
		data() {
			return {
				leftArray: [],
				rightArray: [],
				scrollHeight: 400,
				scrollInto: "",
				leftIndex: 0,
				topArr: [],
				scrollTopSize: 0,
				fillHeight: 0, // 填充高度,用于最后一项低于滚动区域时使用
			}
		},
		computed: {
			/* 计算左侧滚动位置定位 */
			leftIntoView() {
				return `left-${this.leftIndex > 3 ? this.leftIndex - 3 : 0}`;
				//return `left-${this.leftIndex}`;	//根据实际情况
			}
		},
		mounted() {
			/* 等待DOM挂载完成 */
			this.$nextTick(() => {
				/* 在非H5平台,nextTick回调后有概率获取到错误的元素高度,则添加200ms的延迟来减少BUG的产生 */
				setTimeout(() => {
					/* 等待滚动区域初始化完成 */
					this.initScrollView().then(() => {
						/* 获取列表数据,你的代码从此处开始 */
						this.getListData();		//根据实际情况  用时换成自己的或注释
					});
				}, 200);
			});
		},
		methods: {
			/* 初始化滚动区域 */
			initScrollView() {
				return new Promise((resolve, reject) => {
					let view = uni.createSelectorQuery().select('#scroll_box');
					view.boundingClientRect(res => {
						console.log(res);
						this.scrollTopSize = res.top;
						this.scrollHeight = res.height;	//根据实际情况来赋值
						this.$nextTick(() => {
							resolve();
						});
					}).exec();
				});
			},
			// 获取数据
			getListData() {
				new Promise((resolve, reject) => {
					uni.showLoading();
					setTimeout(() => {
						let [left, main] = [
							[],
							[]
						];

						for (let i = 0; i < 25; i++) {
							left.push(`${i + 1}类商品`);

							let list = [];
							let r = Math.floor(Math.random() * 10);
							r = r < 1 ? 3 : r;
							for (let j = 0; j < r; j++) {
								list.push(j);
							}
							main.push({
								title: `第${i + 1}类商品标题`,
								list
							});
						}

						// 将请求接口返回的数据传递给 Promise 对象的 then 函数。
						resolve({
							left,
							main
						});
					}, 1000);
				}).then(res => {
					uni.hideLoading();
					this.leftArray = res.left;
					this.rightArray = res.main;
					// DOM 挂载后 再调用 getElementTop 获取高度的方法。
					this.$nextTick(() => {
						this.getElementTop();
					});
				});
			},
			// 获取元素顶部信息
			getElementTop() {
				new Promise((resolve, reject) => {
					let view = uni.createSelectorQuery().selectAll('.right_item');
					view.boundingClientRect(data => {
						resolve(data);
					}).exec();
				}).then(res => {
					console.log(res);
					let topArr = res.map(item => {
						return item.top - this.scrollTopSize; /* 减去滚动容器距离顶部的距离 */
					});
					this.topArr = topArr;

					/* 获取最后一项的高度,设置填充高度。判断和填充时做了 +-20 的操作,是为了滚动时更好的定位 */
					let last = res[res.length - 1].height;
					if (last - 20 < this.scrollHeight) {
						this.fillHeight = this.scrollHeight - last + 20;
					}
				});
			},
			// 点击左侧导航
			onLeft(e) {
				const index = e.currentTarget.dataset.index;
				// this.leftIndex = index
				this.scrollInto = `item-${index}`
			},
			// 右侧滑动
			mainScroll(e) {
				let top = e.detail.scrollTop;
				let index = 0;
				/* 查找当前滚动距离 */
				for (let i = this.topArr.length - 1; i >= 0; i--) {
					/* 在部分安卓设备上,因手机逻辑分辨率与rpx单位计算不是整数,滚动距离与有误差,增加2px来完善该问题 */
					if (top + 2 >= this.topArr[i]) {
						index = i;
						break;
					}
					
				}
				this.leftIndex = index < 0 ? 0 : index;
			},
		},

	}
</script>

<style>
	page,.bodys {
		height: 100%;
	}

	.scroll_box {
		display: flex;
		height: 100%;
	}

	.left_box {
		width: 30%;
	}

	.left_item {
		height: 80rpx;
	}

	.lis {
		height: 200rpx;
		border-radius: 10rpx;
		background: #808080;
		color: #FFFFFF;
		text-align: center;
		line-height: 200rpx;
		margin-bottom: 10rpx;
	}

	.select {
		background-color: #4CD964;
	}
</style>


实际实战

组件并不是顶高(不占全屏)
scrollHeight 为内容最大高度,高度动态适配

onLoad(){
	//获取系统信息,获取手机高度。单位为'rpx'
	
	uni.getSystemInfo({
		success: (result) => {
			// console.log(result)
			this.navHeight = result.statusBarHeight * (750 / result.windowWidth) + 88
			this.scrollHeight = 2*result.windowHeight-yHeight-this.navHeight;
		}
	})
	scrollHeight 滚动条里内容高度
	windowHeight 获取到的手机高度
	yHeight 在滚动条上方的高度(如果下方也有内容,也要加上)
	navHeight 自定义导航栏高度
	
	
}

在这里插入图片描述
页面生命周期 onPageScroll()
监听页面滚动 页面在垂直方向已滚动的距离(单位px)
根据需求写

//页面生命周期  
//监听页面滚动   页面在垂直方向已滚动的距离(单位px)
onPageScroll(e) {
	this.scrollTop = e.scrollTop;
	// console.log(e);
	
	if(e.scrollTop>100){
		this.params.opacity=1
		this.colors='#281F14'
	}else{
		this.params.opacity=0
		this.colors='#ffffff'
	}
}

右侧滑动时

mainScroll(e) {
	let top = e.detail.scrollTop;
	// console.log(e)
	let index = 0;
	/* 查找当前滚动距离 */
	for (let i = this.topArr.length - 1; i >= 0; i--) {
		// console.log(i)
		// console.log(this.topArr)
		// console.log(this.topArr[i])
		/* 滚动距离与系统高度有误差,可以增加第二层楼栋的高度,再减去1,来完善该问题 */
		if ((top + this.topArr[1]-1) >= this.topArr[i]) {
			index = i;
			break;
		}
	}
	// console.log(index)
	this.leftIndex = index < 0 ? 0 : index;
}

uniapp参考
还有一些vue和原生js参考,以后用到可以参考。
vue参考
原生态JS实现楼层导航案例

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/100174.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue-cli工程中每个文件夹和文件的用处

dist 文件夹&#xff1a;默认 npm run build 命令打包生成的静态资源文件&#xff0c;用于生产部署 node_modules&#xff1a;存放npm命令下载的开发环境和生产环境的依赖包 public&#xff1a;有的叫assets&#xff1a;存放项目中需要用到的资源文件&#xff0c;css、js、im…

【Linux】软件包管理器yum

​&#x1f320; 作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《学会Linux》 &#x1f387; 座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录&#x1f449;Linux软件…

未来已来,光伏产业将走向何方?十大趋势待揭晓!

碳中和大背景下&#xff0c;光伏已经成为发展最迅猛的热门产业之一。在能源产业变革中&#xff0c;光伏将成为未来最大的绿电来源。 据预测&#xff0c;到2030年&#xff0c;全球可再生能源的占比将超过50%。届时&#xff0c;光伏发电和风电将成为全球可再生能源的主力军。根据…

Android入门第50天-读写本地文件

简介 为了这个系列&#xff0c;我的代码已经准备到了第150天了。接下来的内容会越来越精彩&#xff0c;我们也越来越开始进入Android的一些高级功能上的编程了。今天我们就要讲Android中对本地文件进行读写的全过程。 课程目标 输入文件名、输入文件内容后按【保存到SD卡】&a…

毕业设计 - 基于SSH的任务调度系统的设计与实现 【源码+论文】

文章目录前言一、项目设计1. 模块设计2. 实现效果二、部分源码项目源码前言 今天学长向大家分享一个 Java web 毕业设计项目: 基于SSH的任务调度系统的设计与实现 一、项目设计 1. 模块设计 根据需求调研结果确定本任务调度系统的功能结构&#xff0c;最终系统实现的系统将…

Django

文章目录基础知识创建项目启动项目创建超级用户创建项目构建个人博客网站简单构建开启本地虚拟环境初步创建blog应用常用的模板标签和过滤器注&#xff1a;常用的模板标签注&#xff1a;常用的过滤器模板嵌套全局模板文件夹模板文件设置建议使用css美化页面导航栏页面美化css框…

捋一捋什么是MySQL插入意向锁?

Insert Intention Lock&#xff0c;中文我们也称之为插入意向锁。 这个可以算是对我们之前所讲的 Gap Lock 的一个补充&#xff0c;关于 Gap Lock&#xff0c;如果还有小伙伴不懂&#xff0c;可以参考&#xff1a;聊一聊MySQL的记录锁、间隙锁与 Next-Key Lock。 1. 为什么需…

Java基础之《netty(14)—异步模型》

一、基本介绍 1、异步的概念和同步相对。当一个异步过程调用发出后&#xff0c;调用者不能立刻得到结果。实际处理这个调用的组件在完成后&#xff0c;通过状态、通知和回调来通知调用者。 2、netty中的I/O操作是异步的&#xff0c;包括Bind、Write、Connect等操作会简单的返…

【云原生 | 47】etcdctl客户端的使用方法详解

&#x1f341;博主简介&#xff1a; &#x1f3c5;云计算领域优质创作者 &#x1f3c5;2022年CSDN新星计划python赛道第一名 &#x1f3c5;2022年CSDN原力计划优质作者 &#x1f3c5;阿里云ACE认证高级工程师 &#x1f3c5;阿里云开发者社区专…

后台基础权限框架搭建实现[木字楠博客]

文章目录1、项目整合SpringSecurity1.1、引入SpringSecurity依赖1.2、启动测试1.3、自定义实体类继承UserDetails1.4、自定义配制文件1.5、重写loadUserByUsername方法1.6、自定义匿名访问注解1.8、编写SpringSecurity配制类后台权限框架搭建&#xff1a;本项目权限主要依赖Spr…

Polynomial Round 2022 (Div. 1 + Div. 2, Rated, Prizes!) A-C

比赛链接 目录 A. Add Plus Minus Sign 题意&#xff1a; 思路&#xff1a; 代码&#xff1a; B. Coloring 题意&#xff1a; 思路&#xff1a; 代码&#xff1a; C. Ice and Fire 题意&#xff1a; 思路&#xff1a; 代码&#xff1a; A. Add Plus Minus Sign 题意…

半导体芯片制造过程可以用哪种测量仪器

近年来&#xff0c;面对持续高涨的芯片需求&#xff0c;半导体行业生产迎来了高难度挑战——对芯片工艺要求更精细&#xff0c;从5nm到3nm&#xff0c;甚至是2nm。“先进封装”的提出&#xff0c;是对技术的新要求&#xff0c;也是对封装工艺中材料和设备的全新考验。 芯片身上…

节点电力市场生产商的战略竞标:凸松弛方法(Matlab实现)

目录 1 电力市场 1.1 什么是电力市场 1.2 电力市场发展历程 1.3 对传统电力系统理论的挑战 2 节点电力市场生产商的战略竞标&#xff1a;凸松弛方法 2.1 简介 2 Matlab代码 1 电力市场 1.1 什么是电力市场 市场&#xff1a;商品交换(交换商品的过程称交易)关系的总和 …

pikachu靶场验证码绕过详解

今天继续给大家介绍渗透测试相关知识&#xff0c;本文主要内容是pikachu靶场验证码绕过详解。 免责声明&#xff1a; 本文所介绍的内容仅做学习交流使用&#xff0c;严禁利用文中技术进行非法行为&#xff0c;否则造成一切严重后果自负&#xff01; 再次强调&#xff1a;严禁对…

endo-BCN-PEG3-Biotin,endo-BCN三聚乙二醇-生物素

【中文名称】endo-BCN三聚乙二醇-生物素 【英文名称】 endo-BCN-PEG3-Biotin&#xff0c;BCN-PEG3-Biotin (endo) 【CAS号】1263166-92-2 【分子式】C29H46N4O7S 【分子量】594.77 【基团部分】BCN 【纯度标准】95% 【外观颜色】 白色固体 &#xff08;具体由其分子量大小决定…

MyBatis学习 | 简介HelloWord

文章目录一、简介二、HelloWord2.1 环境搭建2.2 创建全局配置文件2.3 创建工具类2.4 创建数据库表和对应的JavaBean2.5 创建SQL映射文件2.6 非接口式与接口式编程2.6.1 非接口式编程2.6.2 接口式编程⭐2.7 简单总结学习地址&#x1f517; https://www.bilibili.com/video/BV1mW…

动态规划问题——换钱的方法数

题目&#xff1a; 给定数组arr&#xff0c;arr中所有的值都为正数且不重复。每个值代表一种面值的货币&#xff0c;每种面值的货币可以使用任意张&#xff0c;再给定一个整数aim&#xff0c;代表要找的钱数&#xff0c;求换钱有多少种方法。 举例&#xff1a; arr [5, 10, 2…

【PCL1.11.0+win10+vs2019】环境配置/ 点云格式转换及可视化

文章目录一、安装1.1 下载PCL1.2 安装PCL1.3 安装OSGeo4W二、配置2.1 配置环境变量2.2 配置VS2019三、点云格式转换以及可视化参考一、安装 1.1 下载PCL 首先我们需要下载pcl1.11.0 &#xff0c;这个版本与vs2019对应。 有两种下载方法&#xff1a;百度网盘、官网下载。二选一…

docker原理及服务编排

一、什么是docker Docker 是一个开源项目&#xff0c;诞生于2013年初&#xff0c;最初是dotCloud公司内部的一个业余项目。它基于Google公司推出的Go语言实现。项目后来加入了Linux基金会&#xff0c;遵从了Apache 2.0协议&#xff0c;项目代码在GitHub上进行维护。 Docker 项…

【毕业设计_课程设计】基于Spark网易云音乐数据分析

文章目录0 项目说明1 系统模块2 分析内容3 界面展示4 项目工程0 项目说明 基于Spark网易云音乐数据分析 提示&#xff1a;适合用于课程设计或毕业设计&#xff0c;工作量达标&#xff0c;源码开放 1 系统模块 包含爬虫,Scala代码,Spark,Hadoop,ElasticSearch,logstash,Flume…