惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - SKILL·NULL

如何为GIT设置全局勾子,为每次提交追加信息 - SKILL·NULL 一文了解大模型、小模型与各类神经网络的关系 如何在Mac上调整外星人鼠标AW720M的灯光颜色 Karabiner-Elements最常用配置 IndexedDB封装 echarts获取坐标上的点距离顶部底部高度 Let`s Encrypt 生成免费自动续签 HTTPS 证书 H5滚动截取长图 ReactNative常见问题及处理 根据.nvmrc自动切换项目所需node版本 Command PhaseScriptExecution failed with a nonzero exit code echarts双Y轴,实现均分为包含刻度0的指定段数,同时对齐刻度 env(safe-area-inset-bottom) 兼容写法 缩放实现0.5px JS 拦截浏览器返回 海康威视DS-IPC-E42H-IWPT监控画面竖线处理 Echarts 5 动态按需引入图表 React 18 自定义 Hook 获取 useState 最新值 处理报错 ResizeObserver loop completed with undelivered notifications.
禁止 IOS 橡皮筋效果
SKILL·NULL · 2024-12-20 · via 博客园 - SKILL·NULL

方法一:

首先,在拖动 div 时,判断当前容器 div 是否有滚动条,如果没有,则禁止整个 div 拖动,例:

const list_dom: any = document.querySelector(".list");
list_dom.addEventListener("touchmove",(ev) => {
  if (list_dom.scrollHeight <= list_dom.clientHeight &&list_dom.offsetHeight <= list_dom.clientHeight) {
    ev.preventDefault();
  }
},{ passive: false });

注:上述方法仅适用于 div 内没有其他内容滚动情形!如果内层有其他 div 滚动,则需要监听当前滑动区域是否在内层滚动 div 上,如果在对应滚动 div 上,则不调用 ev.preventDefault() 方法,否则则调用。

在配置上述方法同时,对相应存在滚动的 div 设置 css 属性:

overscroll-behavior: none;

使临近滚动区域不受到滚动链影响,滚动到边界后不会带动外层滚动。

方法二:

export const getClientHeight = () => {
	return (
		window.innerHeight ||
		document.documentElement.clientHeight ||
		document.body.clientHeight
	);
};

/*
 * @Function 处理touchmove, 将滚动条拖到边缘的时候,禁止橡皮筋效果
 */
class HandleTouchMove {
	startX;
	startY;

	constructor() {
		this.startX = 0;
		this.startY = 0;
		this.listenTouchstart = this.listenTouchstart.bind(this);
		this.listenTouchmove = this.listenTouchmove.bind(this);
	}

	listenTouchstart = (ev: any) => {
		this.startX = ev.changedTouches[0].pageX;
		this.startY = ev.changedTouches[0].pageY;
	};

	listenTouchmove = (ev: any, _dom: any) => {
		const dom = document.querySelector(_dom);
		const moveEndX = ev.changedTouches[0].pageX;
		const moveEndY = ev.changedTouches[0].pageY;
		const moveX = moveEndX - this.startX;
		const moveY = moveEndY - this.startY;
		if (Math.abs(moveX) > Math.abs(moveY) && moveX > 0) {
			// 向右拖拽
			if (dom?.scrollLeft === 0) {
				ev.cancelable && ev.preventDefault();
			}
		}
		if (Math.abs(moveX) > Math.abs(moveY) && moveX < 0) {
			// 向左拖拽
			if (
				dom?.scrollLeft + dom?.offsetWidth === dom?.scrollWidth &&
				dom?.scrollLeft + dom?.clientWidth === dom?.scrollWidth
			) {
				ev.cancelable && ev.preventDefault();
			}
		}
		if (Math.abs(moveY) > Math.abs(moveX) && moveY > 0) {
			// 向下拖拽
			if (dom?.scrollTop === 0) {
				ev.cancelable && ev.preventDefault();
			}
		}
		if (Math.abs(moveY) > Math.abs(moveX) && moveY < 0) {
			// 向上拖拽
			if (
				dom?.scrollHeight - (dom?.scrollTop + dom?.offsetHeight) <= 1 &&
				dom?.scrollHeight - (dom?.scrollTop + dom?.clientHeight) <= 1
			) {
				ev.cancelable && ev.preventDefault();
                                ev.stopPropagation();
			}
		}
	};
}

export const handleTouchmove = new HandleTouchMove();

调用示例:

<template>
	<div class="wrap" :style="{ height: client_height }">
		<div
			class="content"
			@touchstart="handleTouchmove.listenTouchstart"
			@touchmove="
				(ev) => handleTouchmove.listenTouchmove(ev, 'content')
			">
			<div style="height: 1000px">132</div>
		</div>
	</div>
</template>

<script lang="ts" setup>
	import { getClientHeight, handleTouchmove } from "@/components/Common/utils";
	import { onMounted, ref } from "vue";

	const client_height: any = ref("100vh");

	onMounted(() => {
		client_height.value = getClientHeight() + "px";
	});
</script>

<style lang="scss" scoped>
	.wrap {
		width: 100%;

		.content {
			height: 100%;
			overflow-y: auto;
			overscroll-behavior: none;
		}
	}

	@supports (padding-bottom: env(safe-area-inset-bottom)) or
		(padding-bottom: constant(safe-area-inset-bottom)) {
		.content {
			padding-bottom: constant(safe-area-inset-bottom); /* 兼容 iOS < 11.2 */
			padding-bottom: env(safe-area-inset-bottom); /* 兼容 iOS >= 11.2 */
		}
	}

	@supports not (padding-bottom: env(safe-area-inset-bottom)) {
		.content {
			padding-bottom: 20px;
		}
	}

	@supports not (padding-bottom: constant(safe-area-inset-bottom)) {
		.content {
			padding-bottom: 20px;
		}
	}
</style>