当前位置: 首页 > article >正文

基于HTML5的下拉刷新效果

基于HTML5的下拉刷新效果

    • 效果示例图
    • 示例代码

效果示例图

在这里插入图片描述

示例代码

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
		<meta name="viewport" content="width=device-width,initial-scale=1.0" />
		<title></title>
		<style type="text/css">
			* {
				padding: 0;
				margin: 0;
				box-sizing: border-box;
			}

			.main {
				width: 100%;
				height: 100vh;
				background-color: #f5f5f5;
				position: relative;
			}

			.dot-wrap {
				width: 100%;
				height: 30px;
				position: absolute;
				background-color: #fff;
				top: -30px;
			}

			.dot {
				position: absolute;
				width: 10px;
				height: 10px;
				border-radius: 10px;
				background-color: rgb(0, 0, 0, 0.3);
				top: 0;
				left: 50%;
				margin-left: -5px;
			}

			.dot:last-child {
				display: none;
			}

			.dot.loading {
				display: unset;
				animation: dot-move 1.5s infinite;
			}

			@keyframes dot-move {
				0% {
					transform: translateX(-20px);
				}

				33.33% {
					transform: translateX(-20px);
				}

				33.34% {
					transform: translateX(0px);
				}

				66.66% {
					transform: translateX(0px);
				}

				66.67% {
					transform: translateX(20px);
				}

				100% {
					transform: translateX(20px);
				}
			}

			.block-item {
				width: 100%;
				height: 200px;
				background-color: red;
				margin-bottom: 12px;
			}
		</style>
	</head>
	<body>


		<div class="main">
			<div class="dot-wrap">
				<div class="dot"></div>
				<div class="dot"></div>
				<div class="dot"></div>
				<div class="dot"></div>
			</div>

			<div class="block-item"></div>
			<div class="block-item"></div>
			<div class="block-item"></div>
			<div class="block-item"></div>
			<div class="block-item"></div>
			<div class="block-item"></div>
			<div class="block-item"></div>
			<div class="block-item"></div>
			<div class="block-item"></div>
			<div class="block-item"></div>
			<div class="block-item"></div>
			<div class="block-item"></div>
		</div>
	</body>
	<script type="text/javascript">
		let timerHandle = null;
		const mainDom = document.querySelector(".main");
		const dots = document.querySelectorAll(".dot");
		const rootDocument = document.documentElement;
		//当滚动条在最顶部时可以下拉刷新
		if (rootDocument.scrollTop === 0) {
			addTouchEvent();
		}

		//滚动监听
		window.onscroll = function() {
			//当滚动条到达顶部时,可以触发下拉拖动事件
			if (rootDocument.scrollTop <= 0) {
				rootDocument.scrollTop = 0;
				addTouchEvent();
			} else {
				removeTouchEvent();
			}
		}

		let distance, ox, oy, x, y = 0;

		function startEvent(e) {
			console.log("[start]", e)
			//获取手指起始值
			ox = e.touches[0].clientX;
			oy = e.touches[0].clientY;
		}

		function moveEvent(e) {
			if (!e.cancelable) {
				return; // 如果事件不可取消,直接返回,避免报错
			}
			//获取手指移动值
			x = e.touches[0].clientX;
			y = e.touches[0].clientY;

			//判断下拉意图
			if (y - oy > 0) {
				const deg = Math.atan(Math.abs(x - ox) / Math.abs(y - oy)) / Math.PI * 180;
				if (deg > 40) {
					ox = x;
					oy = y;
					return false;
				}
			} else {
				removeTouchEvent();
				if (rootDocument.scrollTop === 0) {
					addTouchEvent();
					return false;
				}
			}

			//手指移动的距离
			distance = y - oy;

			//添加阻尼效果
			let percent = (100 - distance * 0.5) / 100;
			percent = percent < 0.5 ? 0.5 : percent;

			distance = distance * percent

			//设置页面偏移距离
			mainDom.style.transform = `translateY(${distance}px)`
			console.log("[move]", distance)
			if (distance > 20 && distance <= 50) {
				dots[0].style.transform = `translateX(-${(distance-20)*2/3}px)`;
				dots[2].style.transform = `translateX(${(distance-20)*2/3}px)`;
			} else if (distance > 50) {
				dots[0].style.transform = `translateX(-20px)`;
				dots[2].style.transform = `translateX(20px)`;
			}

			e.preventDefault();
		}

		function endEvent() {
			//当拖动的相对值大于50时
			if (distance >= 50) {
				//可以触发下拉刷新
				dots[3].classList.add('loading')
				mainDom.style.transition = `all 0.2s`;
				mainDom.style.transform = `translateY(50px)`
				if (timerHandle) {
					clearTimeout(timerHandle)
				}
				timerHandle = setTimeout(() => {
					if (timerHandle) {
						clearTimeout(timerHandle)
					}
					removeEffect()
				}, 2000);
			} else {
				removeEffect()
			}

		}

		function removeEffect() {
			//清除过渡效果
			mainDom.style.transition = `all 0.2s`;
			mainDom.style = '';
			dots[3].classList.remove('loading')
		}


		function addTouchEvent() {
			/**
			 * 通过将`passive`设置为`false`,表示在触发`touchmove`事件时,事件处理函数可以调用`preventDefault()`来阻止默认行为。
			 * 这意味着在移动过程中,可以阻止浏览器执行默认的滚动行为。
			 */
			mainDom.addEventListener('touchstart', startEvent, {
				passive: false
			});
			mainDom.addEventListener("touchmove", moveEvent, {
				passive: false
			})
			mainDom.addEventListener('touchend', endEvent, {
				passive: false
			})
		}

		function removeTouchEvent() {
			mainDom.removeEventListener('touchstart', startEvent);
			mainDom.removeEventListener("touchmove", moveEvent)
			mainDom.removeEventListener('touchend', endEvent)
		}
	</script>
</html>

http://www.kler.cn/a/306573.html

相关文章:

  • 算法——长度最小的子数组(leetcode209)
  • Docker compose部署portainer
  • OceanStor Pacific系列 8.1.0 功能架构
  • 传奇996_21——龙岭事件
  • MoneyPrinterTurbo – 开源的AI短视频生成工具
  • docker镜像源,亲测可用,时间2024-11-14
  • 如何避免长距离遗忘问题
  • HarmonyOS NEXT 封装实现好用的网络模块(基于最新5.0的API12)
  • Android 12 Launcher3 去掉Hotseat
  • JVM 调优篇7 调优案例3- gc overhead limit exceed
  • ListBox显示最新数据、左移和右移操作
  • K8s中HPA自动扩缩容及hml
  • idea2024.2永久使用
  • MFC工控项目实例之十五定时刷新PC6325A模拟量输入
  • HTML添加文字
  • 【深度学习】Pytorch基础
  • 分享一些成功的 SQL 优化案例
  • 2024工业机器视觉产业现状
  • 多模态大语言模型综述(中)-算法实用指南
  • 如何在Django中创建新的模型实例
  • MFC工控项目实例之十六输入信号验证
  • app抓包 chrome://inspect/#devices
  • 2024.9.12(k8s环境搭建2)
  • WebSocket vs. Server-Sent Events:选择最适合你的实时数据流技术
  • VUE3中ref与reactive
  • Sentinel 安装