Skip to content

11_移动端适配

移动端事件

  • 掌握 touchEvent
  • 实现移动端幻灯片
  • 初步认识 swiper

移动端 touch 事件

  • touchstart
  • touchmove
  • touchend
  • touch 事件 和 mouse 事件的区别

事件点透

  • 在移动端点击元素的时候,会立即执行元素身上的 touch 事件,同时记录点击坐标

  • 等 touch 事件执行完成之后,会在此坐标中,查找元素,并且执行元素身上的 mouse 事件

  • mouse 事件和 touch 事件可以不在同一个元素身上,只在乎这两个元素是否在同一个坐标

  • 解决:不要在移动端使用 mouse 事件

  • 延迟 touch 事件的执行内容

  • 阻止默认事件 ev.preventDefault(); 使用比较多

阻止默认事件

  • touch 事件不允许在 document、documentElement、body、window 等这些全局元素身上阻止默认事件
    • Adeventlistener 其实有第三个参数 : {passive:true} 值默认为 true 意为不允许,设为 false 则是允许阻止默认事件
  • 阻止 touchstart 全局默认事件带来的影响
    • 阻止所有的 mouse 事件
    • 阻止多指缩放
    • 阻止系统菜单
    • 阻止元素获得焦点
    • 阻止滚动条
    • 阻止内容选中
  • touchmove
    • 阻止多指缩放
    • 阻止滚动条
  • touchend
    • 阻止部分 mouse 事件
    • 阻止元素获得或者失去焦点

TouchEvent 对象详解

  • changedTouches 触发当前事件的手指列表

  • targetTouches 当前元素上的手指列表

  • Touches 当前屏幕中的手指列表

  • mousedown 鼠标在元素身上按下

  • mousemove 鼠标在元素身上移动(不管鼠标有没有按下,都能够触发)

  • mouseup 鼠标在元素身上抬起(不管鼠标有没有在元素身上按下)

  • touchstart 手指在元素身上按下

  • touchmove 手指在屏幕中移动(在此之前,手指必须在元素身上按下,不管移动的时候手指是否在元素身上)

  • touchend 手指在屏幕中抬起(在此之前,手指必须在元素身上按下)

例子

html
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<title>Title</title>
		<meta name="viewport" content="width=device-width" />
		<style>
			.box {
				width: 500px;
				height: 500px;
				background: #f1b0b7;
			}

			.link {
				width: 200px;
				height: 50px;
				line-height: 50px;
				text-align: center;
				display: inline-block;
				background: #0a0a0a;
				color: #fff;
			}
		</style>
	</head>
	<body>
		<div class="box"></div>
		<a class="link" href="https://www.baidu.com/">百度</a>

		<script>
			let box = document.querySelector(".box");

			// box.onmousedown = function(){
			//     console.log('down');
			// }
			//
			// box.onmousemove = function(){
			//     console.log('move');
			// }
			//
			// box.onmouseup = function(){
			//     console.log('mouseup');
			// }

			box.ontouchstart = function () {
				console.log("start");
			};

			box.ontouchmove = function () {
				console.log("move");
			};

			box.ontouchend = function () {
				console.log("end");
			};

			/*

    移动端也支持鼠标事件,但是鼠标事件的执行会被延迟一段时间

    移动端在点击元素的时候,会立即执行元素身上的touch事件,同时记录点击的坐标点
    等touch事件执行完成之后,会再一次在坐标中查找元素,并且执行元素身上的mouse事件  300ms
    mouse事件和touch事件可以不在同一个元素身上,只在乎这两个元素的位置是否相同

    */
			box.onclick = function () {
				console.log("down");
			};

			box.ontouchstart = function () {
				console.log("start");
			};

			/*

    移动端也支持鼠标事件,但是鼠标事件的执行会被延迟一段时间

    移动端在点击元素的时候,会立即执行元素身上的touch事件,同时记录点击的坐标点
    等touch事件执行完成之后,会再一次在坐标中查找元素,并且执行元素身上的mouse事件  300ms
    mouse事件和touch事件可以不在同一个元素身上,只在乎这两个元素的位置是否相同
    
    针对事件点透的解决方案
    1,尽量不要在移动端使用鼠标事件(包括a标签)用js做跳转
    2,延迟执行touch事件里面的代码
    3,阻止默认事件

    */
			// box.onclick = function(){
			//
			// }
			box.ontouchend = function (ev) {
				// this.style.display = 'none';
				setTimeout(() => {
					this.style.display = "none";
				}, 300);

				// ev.preventDefault();
			};

			// document.ontouchstart = function(ev){
			//     let target = ev.target;
			//     // console.log(target);
			//     let dataset = target.dataset;
			//     // console.log(dataset);
			//
			//     if(dataset.hasOwnProperty('href')){
			//         window.location.href = dataset.href;
			//     }
			// }
		</script>
	</body>
</html>

事件代理

html
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<title>Title</title>
	</head>
	<body>
		<div class="box" data-open="true" data-hide="true">点击</div>

		<script>
			class propEvent {
				constructor(option) {
					this.eventObj = option.obj;
					this.target = option.target;
					this.eventType = option.eventType || "click";
					this.bindEvent();
				}
				bindEvent() {
					let _this = this;
					this.target.addEventListener(this.eventType, function (ev) {
						let target = ev.target;
						let dataset = target.dataset;

						for (let a in dataset) {
							if (_this.eventObj.__proto__[a]) {
								let data = {
									target,
									ev,
									prop: a,
								};
								_this.eventObj.__proto__[a].call(_this.eventObj, data);
							}
						}
					});
				}
			}

			class handleElement {
				constructor(option) {
					this.target = document.querySelector(option);
					this.event = new propEvent({
						obj: this,
						target: this.target,
					});
				}
				open(option) {
					console.log("打开一个窗口");
				}
				hide() {
					console.log("隐藏方法");
				}
			}

			new handleElement(".box");
		</script>
	</body>
</html>

事件对象

html
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<title>Title</title>
		<meta name="viewport" content="width=device-width" />
		<style>
			.box {
				width: 500px;
				height: 500px;
				background: #f1b0b7;
			}
		</style>
	</head>
	<body>
		<div class="box"></div>

		<script>
			let box = document.querySelector(".box");

			/*

    changedTouches:[]  触发当前事件的手指列表
    targetTouches:[]   当前元素身上的手指列表
    touches:[]         当前屏幕中的手指列表


     */

			box.ontouchstart = function (ev) {
				console.log(ev.changedTouches[0]);
			};
		</script>
	</body>
</html>

拖拽和移动端拖拽

拖拽

html
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<title>Title</title>
		<style>
			body {
				margin: 0;
			}
			.box {
				width: 200px;
				height: 200px;
				background: #f1b0b7;
			}
		</style>
	</head>
	<body>
		<div class="box"></div>

		<script>
			let box = document.querySelector(".box");
			box.onmousedown = function (ev) {
				let oldX = ev.offsetX;
				let oldY = ev.offsetY;

				document.onmousemove = function (ev) {
					let nowX = ev.clientX - oldX;
					let nowY = ev.clientY - oldY;

					box.style.transform = `translate(${nowX}px,${nowY}px)`;
					ev.preventDefault();
				};

				box.onmouseup = function () {
					document.onmousemove = null;
				};
			};
		</script>
	</body>
</html>

移动端拖拽

html
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<title>Title</title>
		<meta name="viewport" content="width=device-width" />
		<style>
			body {
				margin: 0;
			}
			.box {
				width: 200px;
				height: 200px;
				background: #f1b0b7;
			}
		</style>
	</head>
	<body>
		<div class="box"></div>

		<script>
			let box = document.querySelector(".box");

			let startX,
				startY,
				oldX,
				oldY = 0;

			box.ontouchstart = function (ev) {
				let info = box.getBoundingClientRect();
				startX = info.left;
				startY = info.top;

				let touch = ev.changedTouches[0];
				oldX = touch.pageX;
				oldY = touch.pageY;
			};

			box.ontouchmove = function (ev) {
				let touch = ev.changedTouches[0];
				let nowX = touch.pageX - oldX + startX;
				let nowY = touch.pageY - oldY + startY;

				box.style.transform = `translate(${nowX}px,${nowY}px)`;
				ev.preventDefault();
			};

			// box.onmousedown = function(ev){
			//     let oldX = ev.offsetX;
			//     let oldY = ev.offsetY;
			//
			//     document.onmousemove = function(ev){
			//         let nowX = ev.clientX - oldX;
			//         let nowY = ev.clientY - oldY;
			//
			//         box.style.transform = `translate(${nowX}px,${nowY}px)`;
			//         ev.preventDefault();
			//     }
			//
			//     box.onmouseup = function(){
			//         document.onmousemove = null;
			//     }
			// }
		</script>
	</body>
</html>

案例:移动端滑屏切换的幻灯片

html
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<title>Title</title>
		<meta name="viewport" content="width=device-width" />
		<link rel="stylesheet" href="css/style.css" />
	</head>
	<body>
		<div class="box">
			<ul class="list">
				<li><img src="img/img01.png" alt="" /></li>
				<li><img src="img/img02.png" alt="" /></li>
				<li><img src="img/img03.png" alt="" /></li>
				<li><img src="img/img04.png" alt="" /></li>
				<li><img src="img/img05.png" alt="" /></li>
			</ul>
		</div>

		<script>
			let list = document.querySelector(".list");

			let startPoint = 0; //手指按下时手指的位置
			let transX = 0; //手指移动的距离
			let startX = 0; //手指按下时元素的位置
			let lastX = 0; //移动过后,元素的位置

			let viewWidth = window.innerWidth;
			let prop = 0.25;
			let now = 0;

			list.ontouchstart = function (ev) {
				let touch = ev.changedTouches[0];
				startPoint = touch.pageX;
				startX = lastX;
			};

			list.ontouchmove = function (ev) {
				let touch = ev.changedTouches[0];
				transX = touch.pageX - startPoint;
				lastX = startX + transX;

				list.style.transition = "none";
				list.style.transform = `translateX(${lastX}px)`;
				ev.preventDefault();
			};

			list.ontouchend = function () {
				if (Math.abs(transX) > viewWidth * prop) {
					now -= transX / Math.abs(transX);
				}
				lastX = -now * viewWidth;
				list.style.transition = "0.5s";
				list.style.transform = `translateX(${lastX}px)`;
				transX = 0;
			};
		</script>
	</body>
</html>

幻灯片无缝滚动

html
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<title>Title</title>
		<meta name="viewport" content="width=device-width" />
		<link rel="stylesheet" href="css/style.css" />
	</head>
	<body>
		<div class="box">
			<ul class="list">
				<li><img src="img/img01.png" alt="" /></li>
				<li><img src="img/img02.png" alt="" /></li>
				<li><img src="img/img03.png" alt="" /></li>
				<li><img src="img/img04.png" alt="" /></li>
				<li><img src="img/img05.png" alt="" /></li>
			</ul>
		</div>

		<script>
			let list = document.querySelector(".list");
			let item = list.querySelectorAll("li");
			list.innerHTML += list.innerHTML;

			console.log(item.length);

			let startPoint = 0; //手指按下时手指的位置
			let transX = 0; //手指移动的距离
			let startX = 0; //手指按下时元素的位置
			let lastX = 0; //移动过后,元素的位置

			let viewWidth = window.innerWidth;
			let prop = 0.25;
			let now = 0;

			list.ontouchstart = function (ev) {
				let touch = ev.changedTouches[0];
				startPoint = touch.pageX;

				if (now === 0) {
					now = item.length;
				} else if (now === item.length * 2 - 1) {
					now = item.length - 1;
				}
				lastX = -now * viewWidth;
				list.style.transition = "none";
				list.style.transform = `translateX(${lastX}px)`;
				startX = lastX;
			};

			list.ontouchmove = function (ev) {
				let touch = ev.changedTouches[0];
				transX = touch.pageX - startPoint;
				lastX = startX + transX;

				list.style.transition = "none";
				list.style.transform = `translateX(${lastX}px)`;
				ev.preventDefault();
			};

			list.ontouchend = function () {
				if (Math.abs(transX) > viewWidth * prop) {
					now -= transX / Math.abs(transX);
				}
				lastX = -now * viewWidth;
				list.style.transition = "0.5s";
				list.style.transform = `translateX(${lastX}px)`;
				transX = 0;
			};
		</script>
	</body>
</html>

3D 圆环

html
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<title>Title</title>
		<style>
			html,
			body {
				height: 100%;
			}
			body {
				margin: 0;
				display: flex;
				justify-content: center;
				align-items: center;
				perspective: 3000px;
			}
			.list {
				width: 500px;
				height: 260px;
				background: #f1b0b7;
				position: relative;
				transform-style: preserve-3d;
				transition: 5s;
			}

			/*.list:hover{*/
			/*    transform: rotateY(230deg) rotateX(50deg);*/
			/*}*/

			.item {
				width: 500px;
				height: 260px;
				background: #000;
				position: absolute;
				left: 0;
				top: 0;
				font: 50px/260px "";
				color: #fff;
				text-align: center;
			}

			/*.item:nth-child(1){*/
			/*    transform:  rotateY(0deg) translateZ(400px);*/
			/*}*/
			/*.item:nth-child(2){*/
			/*    transform:  rotateY(72deg) translateZ(400px);*/
			/*}*/
			/*.item:nth-child(3){*/
			/*    transform: rotateY(144deg) translateZ(400px);*/
			/*}*/
			/*.item:nth-child(4){*/
			/*    transform: rotateY(219deg) translateZ(400px);*/
			/*}*/
			/*.item:nth-child(5){*/
			/*    transform: rotateY(288deg) translateZ(400px);*/
			/*}*/
		</style>
	</head>
	<body>
		<div class="list">
			<div class="item">1</div>
			<div class="item">2</div>
			<div class="item">3</div>
			<div class="item">4</div>
			<div class="item">5</div>
		</div>

		<!--
    半径的计算公式: 周长/ 2PI
-->

		<script>
			let list = document.querySelector(".list");
			list.innerHTML += list.innerHTML;
			let item = list.querySelectorAll(".item");
			console.log(item);

			let startPoint = 0; //手指按下时手指的位置
			let transX = 0; //手指移动的距离
			let startX = 0; //手指按下时元素的位置
			let lastX = 0; //移动过后,元素的位置

			let angle = 360 / 10;
			let radius = (500 * item.length) / (2 * Math.PI);
			console.log(radius);

			Array.from(item).forEach((item, index) => {
				item.style.transform = `rotateY(${
					angle * index
				}deg) translateZ(${radius}px)`;
			});

			let prop = 0.25;
			let now = 0;

			list.ontouchstart = function (ev) {
				let touch = ev.changedTouches[0];
				startPoint = touch.pageX;
				startX = lastX;
				console.log(startX);
			};

			list.ontouchmove = function (ev) {
				let touch = ev.changedTouches[0];
				transX = (touch.pageX - startPoint) / 3;
				lastX = startX + transX;

				console.log(transX);

				list.style.transition = "none";
				list.style.transform = `rotateY(${lastX}deg)`;
				ev.preventDefault();
			};

			list.ontouchend = function () {
				if (Math.abs(transX) > viewWidth * prop) {
					now -= transX / Math.abs(transX);
				}
				lastX = -now * viewWidth;
				list.style.transition = "0.5s";
				list.style.transform = `rotateY(${lastX}deg)`;
				transX = 0;
			};
		</script>
	</body>
</html>

Swiper 使用

html
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<title>Title</title>
		<link rel="stylesheet" href="css/style.css" />
		<script src="js/swiper.min.js"></script>
	</head>
	<body>
		<div class="box swiper-container">
			<ul class="list swiper-wrapper">
				<li class="swiper-slide"><img src="img/img01.png" alt="" /></li>
				<li class="swiper-slide"><img src="img/img02.png" alt="" /></li>
				<li class="swiper-slide"><img src="img/img03.png" alt="" /></li>
				<li class="swiper-slide"><img src="img/img04.png" alt="" /></li>
				<li class="swiper-slide"><img src="img/img05.png" alt="" /></li>
			</ul>
		</div>

		<script>
			var swiper = new Swiper(".swiper-container", {
				// direction : 'vertical',
				loop: true,
				autoplay: true,
			});
		</script>
	</body>
</html>

移动端单位适配

视口相关

width 设置的是视口的宽度

user-scalable 是否允许用户进行缩放的设置

手机浏览器,如果不做任何调整,所有手机得到的默认宽度都是 980px

为什么要设置视口

viewport 的设置不会对 PC 页面产生影响,但对于移动页面却很重要

  1. 媒体查询 @media 响应式布局中,会根据媒体查询功能来适配多端布局,必须对 viewport 进行设置,否则根据查询到的尺寸无法正确匹配视觉宽度而导致布局混乱。如不设置 viewport 参数,多说移动端媒体查询的结果将是 980px 这个节点布局的参数,而非我们通常设置的 768px 范围内的这个布局参数

像素比

物理像素/逻辑像素. 1

1920*1080 物理像素(一个个的发光二极管)

1660*900 逻辑像素 (用多个发光二极管显示一个像素的内容)

1440 * 800 逻辑像素

  1. 由于目前多数手机的 dpr 都不再是 1,为了产出高保真页面,我们一般会给出 750px 的设计稿,那么就需要通过设置 viewport 的参数来进行整体换算,而不是在每次设置尺寸时进行长度的换算。

适配?

  1. 如何在移动端实现一个宽度 50%的元素
  2. 如何保证这个元素在任何地方任何位置都是 50%

唯一参考值 rem

                Html  font-size

5rem 207px 41.4px 6plus 414px

5rem 160px 32px 5s 320px

1rem 屏幕宽度的 1/10

像素?

物理像素(physical pixel)

手机屏幕上显示的最小单元,该最小单元具有颜色及亮度的属性可供设置。(屏幕上有多少个发光二极管)

设备独立像素(density-indenpendent pixel)

此为逻辑像素,计算机设备中的一个点,css 中设置的像素指的就是该像素。老早在没有 retina 屏之前,设备独立像素与物理像素是相等的。

设备像素比(device pixel ratio)

设备像素比(dpr) = 物理像素/设备独立像素。如 iphone 6、7、8 的 dpr 为 2,那么一个设备独立像素便为 4 个物理像素,因此在 css 上设置的 1px 在其屏幕上占据的是 2 个物理像素,0.5px 对应的才是其所能展示的最小单位。这就是 1px 在 retina 屏上变粗的原因,目前有很多办法来解决这一问题。

flex

作用在父级身上的属性

css
flex-direction: row | row-reverse | column | column-reverse;
/*用来控制子项整体布局方向,是从左往右还是从右往左,是从上往下还是从下往上。*/
flex-wrap: nowrap | wrap | wrap-reverse;
/*用来控制子项整体单行显示还是换行显示,如果换行,则下面一行是否反方向显示。*/
flex-flow: <‘flex-direction> || <‘flex-wrap>
/*是flex-direction和flex-wrap的缩写*/
justify-content: flex-start | flex-end | center | space-between | space-around | space-evenly;
/*属性决定了水平方向子项的对齐和分布方式*/
align-items: stretch | flex-start | flex-end | center | baseline;
/*子项们相对于flex容器在垂直方向上的对齐方式*/
align-content: stretch | flex-start | flex-end | center | space-between | space-around | space-evenly;
/*针对多行子项们相对于flex容器在垂直方向上的对齐方式*/

作用在子级身上的属性

css
order: <integer>;
flex-grow: <number>;/* 数值,默认值是 1 */
/*flex-grow属性中的grow是扩展的意思,扩展的就是flex子项所占据的宽度,扩展所侵占的空间就是除去元素外的剩余的空白间隙。*/
flex-shrink: <number>; /* 数值,默认值是 1 */
/*shrink是“收缩”的意思,flex-shrink主要处理当flex容器空间不足时候,单个元素的收缩比例。*/
flex-basis: <length> | auto; /* 默认值是 auto */
/*定义了在分配剩余空间之前元素的默认大小。相当于对浏览器提前告知我要占据这么大的空间,提前帮我预留好。*/
flex: none | auto | [ <'flex-grow'> <'flex-shrink'>? || <'flex-basis'> ]
/*flex属性是flex-grow,flex-shrink和flex-basis的缩写。*/
align-self: auto | flex-start | flex-end | center | baseline | stretch;

在 Flex 布局中,flex 子元素的设置floatclear以及vertical-align属性都是没有用的。

vw vh
px/rpx/upx
媒体查询

flexible

文字大小用 em/rem/px,但 rem 逐渐被淘汰,现在比较多的是使用 viewport:

html
<meta name="viewport" content="width=device-width, initial-scale=1.0" />

除文字外 其他容器尺寸 元素尺寸全部用 px

vmin/vmax:横屏适配:全部的 vw 替换成 vmin

  • vmin: 的取值为  vw  和  vh  中较小的那个
  • vmax: 的取值为  vw  和  vh  中较大的那个

前端开发常用单位-vminvmax - BNTang - 博客园 (cnblogs.com)

响应式和屏幕适配的概念

屏幕适配:文字图标图片等等资源等比放大或者缩小

响应式:是不同屏幕下的布局,字体设置不一样


移动端适配文章:

2021.10.13 五种移动端前端适配方案【移动端】一只白猫罢了的博客-CSDN 博客前端移动端适配

前端解决移动端适配的五种方法 - 轻舟经年 - 博客园 (cnblogs.com)

前端移动端的适配 - 走看看 (zoukankan.com)

超详细讲解 H5 移动端适配 - 前端南玖 - 博客园 (cnblogs.com)

前端解决移动端适配大全!!Li Derong 的博客-CSDN 博客前端移动端适配

前端开发移动端的适配方案推荐? - 知乎 (zhihu.com)

前端移动端适配 - 媒体查询适配方案(个人笔记) - 知乎 (zhihu.com)

前端移动端适配总结 (sohu.com)


css3 新单位:

css3 新单位 vw、vh、vmin、vmax 的使用介绍 - 走看看 (zoukankan.com)

px、%、em、vw、vh、vmax、vmin、rem 区别_七月星辰的博客-CSDN 博客_vmin

CSS3 新单位 vw、vh、vmin、vmax 使用详解 - 哔哩哔哩 (bilibili.com)

移动端功能

10,加速度监测.html

html
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<title>Title</title>
		<meta name="viewport" content="width=device-width" />
		<style></style>
	</head>
	<body>
		<div class="box"></div>

		<script>
			let box = document.querySelector(".box");

			window.addEventListener("devicemotion", function (ev) {
				let motion = ev.acceleration; //当前手机的加速度;
				let { x, y, z } = motion;
				box.innerText = `
            x轴:${x.toFixed(2)}
            y轴:${y.toFixed(2)}
            z轴:${z.toFixed(2)}
        `;
			});
		</script>

		<!--
先保证手机和电脑处于同一个局域网:(windows电脑需要关闭防火墙)
    anywhere : npm install anywhere -g
-->
	</body>
</html>

11,重力加速度监测.html

html
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<title>Title</title>
		<meta name="viewport" content="width=device-width" />
		<style></style>
	</head>
	<body>
		<div class="box"></div>

		<script>
			let box = document.querySelector(".box");

			window.addEventListener("devicemotion", function (ev) {
				let motion = ev.acceleration; //当前手机的加速度;
				let gravity = ev.accelerationIncludingGravity; //重力加速度
				let { x, y, z } = motion;
				let { x: a, y: b, z: c } = gravity;

				box.innerText = `
            x轴:${a.toFixed(2)}
            y轴:${b.toFixed(2)}
            z轴:${c.toFixed(2)}
        `;
			});
		</script>

		<!--
先保证手机和电脑处于同一个局域网:(windows电脑需要关闭防火墙)
    anywhere : npm install anywhere -g

    地球重力加速度  9.8
-->
	</body>
</html>

防抖函数

html
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<title>Title</title>
		<style>
			.box {
				width: 500px;
				height: 500px;
				background: #f1b0b7;
			}
		</style>
	</head>
	<body>
		<div class="box"></div>

		<script>
			let box = document.querySelector(".box");

			// let timmer = null;
			// box.onmousemove = function(){
			//     // move()
			//     clearTimeout(timmer);
			//
			//     timmer = setTimeout(()=>{
			//         move()
			//     },200);
			// }

			box.onmousemove = debounce(move);

			function move() {
				console.log(this);
			}

			function debounce(fn, delay = 200, isStart = true) {
				let timmer = null;
				let isEnd = true;
				return function (...arg) {
					clearTimeout(timmer);
					// console.log(this,arg);

					if (isStart) {
						isEnd && fn.apply(this, arg);
						isEnd = false;
					}

					timmer = setTimeout(() => {
						!isStart && fn.apply(this, arg);
						isEnd = true;
					}, delay);
				};
			}
		</script>
	</body>
</html>

节流函数

html
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<title>Title</title>
		<style>
			.box {
				width: 500px;
				height: 500px;
				background: #f1b0b7;
			}
		</style>
	</head>
	<body>
		<div class="box"></div>

		<script>
			let box = document.querySelector(".box");

			// let timmer = null;
			// box.onmousemove = function(){
			//     // move()
			//     clearTimeout(timmer);
			//
			//     timmer = setTimeout(()=>{
			//         move()
			//     },200);
			// }

			box.onmousemove = throttle(move);

			function move() {
				console.log(this);
			}

			function throttle(fn, delay = 500) {
				let timmer = null;
				return function (...arg) {
					if (timmer) {
						return;
					}

					timmer = setTimeout(() => {
						fn.apply(this, arg);
						timmer = null;
					}, delay);
				};
			}
		</script>
	</body>
</html>

9.js 判断横竖屏.html

html
<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8" />
		<title>Title</title>
		<meta name="viewport" content="width=device-width" />
		<style>
			body {
				margin: 0;
			}
			.box {
				width: 90vw;
				height: 80vh;
				background: #f1b0b7;
				position: absolute;
				left: 0;
				top: 0;
				right: 0;
				bottom: 0;
				margin: auto;
			}

			.active {
				background: #0a0a0a;
			}
		</style>
	</head>
	<body>
		<div class="box" id="box"></div>

		<script>
			window.addEventListener("orientationchange", function () {
				handleScreen(window.orientation);
			});

			handleScreen(window.orientation);
			function handleScreen(deg) {
				switch (deg) {
					case 90:
					case -90:
						box.classList.add("active");
						break;
					default:
						box.classList.remove("active");
				}
			}
		</script>
	</body>
</html>

Released under the MIT License.