H5移动端,如何写一套自己的组件库,适配方法,less适配

一、无缝滑屏轮播组件(使用定位)

1、不是无缝的滑屏轮播

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<!-- <meta name="viewport" content="width=device-width,initial-scale=1.0" /> -->
		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
		<meta name="format-detection" content="telephone=no,email=no"/>
		<title></title>
		<style type="text/css">
			*{margin: 0;padding: 0;}
			html,body{height: 100%;overflow: hidden;}
			#wrap{height: 100%;overflow: hidden;}
			#wrap .carouse_wrap > .list{list-style: none;overflow: hidden;position: absolute;}
			#wrap .carouse_wrap > .list > li{float: left;}
			#wrap .carouse_wrap > .list > li > a,#wrap .carouse_wrap > .list > li > a > img{display: block;}
			#wrap .carouse_wrap > .list > li > a > img{width: 100%;}
		</style>
	</head>
	<body>
		<div id="wrap"><!-- 用来布局的,包裹轮播图,设置轮播图在页面位置 -->
			<div class="carouse_wrap"><!-- 轮播容器 -->
			</div>
		</div>
	</body>
	<script type="text/javascript">			
		window.onload=function(){
			/* 全局禁用默认事件触发 */
			document.addEventListener("touchstart",function(ev){
				ev=event||ev;
				ev.preventDefault();
			});
			
			/* 动态生成轮播图 */
			let arr = ["img/01.jpg","img/02.jpg","img/03.jpg","img/04.jpg","img/05.jpg"];//模拟从后台获取的轮播图列表
			
			let carouse_wrap = document.querySelector(".carouse_wrap");//获取轮播容器
			
			if(carouse_wrap){//如果轮播存在
				/* dom结点 */
				let ul = document.createElement("ul");		//创建一个ul结点
				let style = document.createElement("style");//创建一个style结点
				let head = document.querySelector("head");	//获取head结点
				
				ul.classList.add("list")					//给创建的ul的class列表添加一个.list样式
				
				for(let i = 0;i<arr.length;i++){//遍历数组,有多少图片就添加多少轮播结构
					ul.innerHTML+='<li><a href="javascript:;"><img src="'+arr[i]+'" ></a></li>'
				}
				
				carouse_wrap.appendChild(ul)				//把ul添加到容器中
				
				/* (重点)给style结点添加样式,首先
					我们应该先确定单张图片的大小,这里我就直接用百分比让图片填满屏幕了
					那么,我们应该让ul的宽度正好容纳这些轮播图片,比如5张图片就是500%
					
					那么5张图片,每张就占ul的20%,5*20%=100%,正好填满ul
				 */
				style.innerHTML="#wrap .carouse_wrap > .list{width: "+arr.length*100+"%;}#wrap .carouse_wrap > .list > li{width: "+100/arr.length+"%;}"
				
				head.appendChild(style)//将style结点添加到head中
				
				/* 最后,因为每个li都设置的定位,容器就没有东西撑开造成高度塌陷,我们只需要让其等于图片高度即可 */
				let img = document.querySelector("#wrap .carouse_wrap > .list > li:nth-of-type(1) > a > img");
				
				let timer=setTimeout(function(){/* 因为js代码执行很快,页面没渲染好就获取offsetHeight会获取不到,等100ms就可以了 */
					carouse_wrap.style.height=img.offsetHeight+"px"
				},100)
				clearTimeout(timer)//清除
				
				/* ==================创建轮播完================= */
				/* ==================滑屏======================= */
				let ElStartX = 0;	//元素当前位置
				let startX = 0;		//记录手点击起始位置
				let moveX = 0;		//记录手指滑动距离
				let endX = 0;		//记录手指抬起时位置
				let index = 0;		//记录当前轮播的下标
				/* 手指点击屏幕事件 获取手指和当前元素位置*/
				carouse_wrap.addEventListener("touchstart",function(ev){
					ev = event||ev;
					startX = ev.changedTouches[0].clientX;//获取手指点击位置
					
					ElStartX = ul.offsetLeft;//获取元素当前位置
					
				})
				/* 手指移动事件 让元素跟随手指移动*/
				carouse_wrap.addEventListener("touchmove",function(ev){
					ev = ev||event;
					ul.style.transition="none";					//清除过渡,在手指抬起事件中绑定,这里要清掉,因为影响滑屏体验
					let nowX = ev.changedTouches[0].clientX;	//获取滑动时的位置
					moveX = nowX - startX;						//获取滑动距离
					ul.style.left = ElStartX + moveX + "px";	//让ul跟随手指偏移
				})
				/* 手指抬起事件 判断移动距离,如果超过100px的距离,就让轮播跳转到下一张或上一张,第一张和最后一张怎么滑都会回到原来的位置*/
				carouse_wrap.addEventListener("touchend",function(ev){
					ev = ev||event;
					if(moveX > 0 && moveX >= 100){//>0表示向右滑动屏幕
						index===0?index=0:index--;		//如果index=0了就让index=4,否则就自减
					}else if(moveX < 0 && moveX <= -100){
						index===4?index=4:index++;
					}
					ul.style.transition="1s left";//设置动画,在手指抬起时才设置
					
					ul.style.left = -index * img.offsetWidth+"px";//让ul偏移当前图片下标*单张轮播宽度的距离
					
					/* 方式2
						let index = ul.offsetLeft/img.offsetWidth;//获取实时的位置,用ul的当前偏移/轮播宽度,就会得到一个数
						这个数如果你向右滑屏会得到一个正数,如果你刚好滑满一屏,就是1,否则是一个小数
						
						if(moveX > 0){
							index = Math.ceil(index);//返回大于或等于index的最小整数
						}else if(moveX < 0){
							index = Math.floor(index);//返回小于或等于index的最大整数
						}
						ul.style.left = index * img.offsetWidth+"px"
					 */
					
				})
			}
		}
	</script>
</html>

2、组件化无缝滑屏轮播(用户可以通过指定参数来决定是否需要无缝功能)

在这里插入图片描述在这里插入图片描述在这里插入图片描述在这里插入图片描述

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<!-- <meta name="viewport" content="width=device-width,initial-scale=1.0" /> -->
		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
		<meta name="format-detection" content="telephone=no,email=no"/>
		<title></title>
		<style type="text/css">
			*{margin: 0;padding: 0;}
			html,body{height: 100%;overflow: hidden;}
			#wrap{height: 100%;overflow: hidden;}
			#wrap .carouse_wrap > .list{list-style: none;overflow: hidden;position: absolute;}
			#wrap .carouse_wrap > .list > li{float: left;}
			#wrap .carouse_wrap > .list > li > a,#wrap .carouse_wrap > .list > li > a > img{display: block;}
			#wrap .carouse_wrap > .list > li > a > img{width: 100%;}
		</style>
	</head>
	<body>
		<div id="wrap"><!-- 用来布局的,包裹轮播图,设置轮播图在页面位置 -->
			<div class="carouse_wrap"  ><!-- 轮播容器 -->
			</div>
		</div>
	</body>
	<script type="text/javascript">			
		window.onload=function(){
			/* 全局禁用默认事件触发 */
			document.addEventListener("touchstart",function(ev){
				ev=event||ev;
				ev.preventDefault();
			});
			
			/* 动态生成轮播图 */
			let arr = ["img/01.jpg","img/02.jpg","img/03.jpg","img/04.jpg","img/05.jpg"];//模拟从后台获取的轮播图列表
			
			let carouse_wrap = document.querySelector(".carouse_wrap");//获取轮播容器
			
			if(carouse_wrap){//如果轮播存在
				
				/* 无缝1、复制数组 并确定用户是否需要无缝功能*/
				
				/* 
					看看<div class="carouse_wrap" needCarouse >,加没加needCarouse,如果加了,表示用户需要无缝功能,没加就是null表示不需要无缝
				 */
				let needCarouse = carouse_wrap.getAttribute("needCarouse");//判断用户是否需要无缝功能
				
				if(needCarouse!=null){/* 如果不是null,表示需要无缝功能 */
					let arrLength = arr.length;//保存当前数组的长度,因为复制数组会让数组长度改变
					
					arr = arr.concat(arr)//向arr数组后面添加数组arr,生成一个全新的数组,然后重新赋值给arr
				}

				/* dom结点 */
				let ul = document.createElement("ul");		//创建一个ul结点
				let style = document.createElement("style");//创建一个style结点
				let head = document.querySelector("head");	//获取head结点
				
				ul.classList.add("list")					//给创建的ul的class列表添加一个.list样式
				
				for(let i = 0;i<arr.length;i++){//遍历数组,有多少图片就添加多少轮播结构
					ul.innerHTML+='<li><a href="javascript:;"><img src="'+arr[i]+'" ></a></li>'
				}
				
				carouse_wrap.appendChild(ul)				//把ul添加到容器中
				
				/* (重点)给style结点添加样式,首先
					我们应该先确定单张图片的大小,这里我就直接用百分比让图片填满屏幕了
					那么,我们应该让ul的宽度正好容纳这些轮播图片,比如5张图片就是500%
					
					那么5张图片,每张就占ul的20%,5*20%=100%,正好填满ul
				 */
				style.innerHTML="#wrap .carouse_wrap > .list{width: "+arr.length*100+"%;}#wrap .carouse_wrap > .list > li{width: "+100/arr.length+"%;}"
				
				head.appendChild(style)//将style结点添加到head中
				
				/* 最后,因为每个li都设置的定位,容器就没有东西撑开造成高度塌陷,我们只需要让其等于图片高度即可 */
				let img = document.querySelector("#wrap .carouse_wrap > .list > li:nth-of-type(1) > a > img");
				
				let timer=setTimeout(function(){/* 因为js代码执行很快,页面没渲染好就获取offsetHeight会获取不到,等100ms就可以了 */
					carouse_wrap.style.height=img.offsetHeight+"px"
				},100)
				clearTimeout(timer)//清除
				
				/* ==================创建轮播完================= */
				/* ==================滑屏======================= */
				let ElStartX = 0;	//元素当前位置
				let startX = 0;		//记录手点击起始位置
				let moveX = 0;		//记录手指滑动距离
				let endX = 0;		//记录手指抬起时位置
				let index = 0;		//记录当前轮播的下标
				/* 手指点击屏幕事件 获取手指和当前元素位置*/
				carouse_wrap.addEventListener("touchstart",function(ev){
					ev = event||ev;
					ElStartX = ul.offsetLeft;//获取元素当前位置
					startX = ev.changedTouches[0].clientX;//获取手指点击位置
					ul.style.transition="none";					//清除过渡,在手指抬起事件中绑定,这里要清掉,因为影响滑屏体验
					
					/* ===========无缝滑屏2======== */
					if(needCarouse!=null){//如果不为null表示用户需要无缝轮播
						
						if(index===0){/* 如果是第一个数组第一张 */
							moveX = 0;										//重新定位需要清除刚刚算出来的滑动距离
							index=arr.length/2								//如果当前是第一张轮播图让index瞬间变为第二个数组的第一张
							ElStartX=-index * img.offsetWidth;				//起始位置变为第二个数组第一张
							ul.style.left = -index * img.offsetWidth+"px";	//ul偏移到第二个数组第一张
						}else if(index===(arr.length-1)){/* 如果是第二个数组最后一张 */					
							index=arr.length/2-1							//让index瞬间变为第一个数组最后一张
							ElStartX=-index * img.offsetWidth;				//起始位置变为第一个数组最后一张
							ul.style.left = -index * img.offsetWidth+"px";	//偏移到第一个数组最后一张
						}else{/* 如果不是第一和最后一张,普通的获取值即可 */
							ElStartX = ul.offsetLeft;//获取元素当前位置
						}
						
					}else{/* 是null表示不需要 */
						ElStartX = ul.offsetLeft;//获取元素当前位置
					}
					
					
				})
				/* 手指移动事件 让元素跟随手指移动*/
				carouse_wrap.addEventListener("touchmove",function(ev){
					ev = ev||event;
					let nowX = ev.changedTouches[0].clientX;	//获取滑动时的位置
					moveX = nowX - startX;						//获取滑动距离
					ul.style.left = ElStartX + moveX + "px";	//让ul跟随手指偏移
				})
				/* 手指抬起事件 判断移动距离,如果超过100px的距离,就让轮播跳转到下一张或上一张,第一张和最后一张怎么滑都会回到原来的位置*/
				carouse_wrap.addEventListener("touchend",function(ev){
					ev = ev||event;
					
					/* 无缝滑屏3,改改逻辑 */
					if(needCarouse!=null){//如果不为null表示用户需要无缝轮播
						if(moveX > 0 && moveX >= 100){//>0表示向右滑动屏幕
							index--;
						}else if(moveX < 0 && moveX <= -100){
							index++;
						}
					}else{
						if(moveX > 0 && moveX >= 100){//>0表示向右滑动屏幕
							index===0?index=0:index--;		//如果index=0了就让index=4,否则就自减
						}else if(moveX < 0 && moveX <= -100){
							index===4?index=4:index++;
						}
					}
					
					ul.style.transition="0.5s left";//设置动画,在手指抬起时才设置
					
					ul.style.left = -index * img.offsetWidth+"px";//让ul偏移当前图片下标*单张轮播宽度的距离
				})
			}
		}
	</script>
</html>

3、组件化自动轮播功能,用户可选功能

在这里插入图片描述
在这里插入图片描述

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<!-- <meta name="viewport" content="width=device-width,initial-scale=1.0" /> -->
		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
		<meta name="format-detection" content="telephone=no,email=no"/>
		<title></title>
		<style type="text/css">
			*{margin: 0;padding: 0;}
			html,body{height: 100%;overflow: hidden;}
			#wrap{height: 100%;overflow: hidden;}
			#wrap .carouse_wrap > .list{list-style: none;overflow: hidden;position: absolute;}
			#wrap .carouse_wrap > .list > li{float: left;}
			#wrap .carouse_wrap > .list > li > a,#wrap .carouse_wrap > .list > li > a > img{display: block;}
			#wrap .carouse_wrap > .list > li > a > img{width: 100%;}
		</style>
	</head>
	<body>
		<div id="wrap"><!-- 用来布局的,包裹轮播图,设置轮播图在页面位置 -->
			<div class="carouse_wrap" needCarouse needAutoCarouse ><!-- 轮播容器 -->
			</div>
		</div>
	</body>
	<script type="text/javascript">			
		window.onload=function(){
			/* 全局禁用默认事件触发 */
			document.addEventListener("touchstart",function(ev){
				ev=event||ev;
				ev.preventDefault();
			});
			
			/* 动态生成轮播图 */
			let arr = ["img/01.jpg","img/02.jpg","img/03.jpg","img/04.jpg","img/05.jpg"];//模拟从后台获取的轮播图列表
			
			let carouse_wrap = document.querySelector(".carouse_wrap");//获取轮播容器
			
			if(carouse_wrap){//如果轮播存在
				
				/* 无缝1、复制数组 并确定用户是否需要无缝功能*/
				
				/* 
					看看<div class="carouse_wrap" needCarouse >,加没加needCarouse,如果加了,表示用户需要无缝功能,没加就是null表示不需要无缝
				 */
				let needCarouse = carouse_wrap.getAttribute("needCarouse");//判断用户是否需要无缝功能
				
				if(needCarouse!=null){/* 如果不是null,表示需要无缝功能 */
					let arrLength = arr.length;//保存当前数组的长度,因为复制数组会让数组长度改变
					
					arr = arr.concat(arr)//向arr数组后面添加数组arr,生成一个全新的数组,然后重新赋值给arr
				}
				
				/* &&&&&&&&&&&&&自动轮播1、&&&&&&&&&&&&&&&& */
				let needAutoCarouse = carouse_wrap.getAttribute("needAutoCarouse");/* 如果有此参数,表示用户开启自动轮播 */
				if(needAutoCarouse!=null){
					let AutoTimer = 0;//用来保存自动轮播时间函数id
					AutoCarouse();	  //自动轮播函数
				}
				
				/* dom结点 */
				let ul = document.createElement("ul");		//创建一个ul结点
				let style = document.createElement("style");//创建一个style结点
				let head = document.querySelector("head");	//获取head结点
				
				ul.classList.add("list")					//给创建的ul的class列表添加一个.list样式
				
				for(let i = 0;i<arr.length;i++){//遍历数组,有多少图片就添加多少轮播结构
					ul.innerHTML+='<li><a href="javascript:;"><img src="'+arr[i]+'" ></a></li>'
				}
				
				carouse_wrap.appendChild(ul)				//把ul添加到容器中
				
				/* (重点)给style结点添加样式,首先
					我们应该先确定单张图片的大小,这里我就直接用百分比让图片填满屏幕了
					那么,我们应该让ul的宽度正好容纳这些轮播图片,比如5张图片就是500%
					
					那么5张图片,每张就占ul的20%,5*20%=100%,正好填满ul
				 */
				style.innerHTML="#wrap .carouse_wrap > .list{width: "+arr.length*100+"%;}#wrap .carouse_wrap > .list > li{width: "+100/arr.length+"%;}"
				
				head.appendChild(style)//将style结点添加到head中
				
				/* 最后,因为每个li都设置的定位,容器就没有东西撑开造成高度塌陷,我们只需要让其等于图片高度即可 */
				let img = document.querySelector("#wrap .carouse_wrap > .list > li:nth-of-type(1) > a > img");
				
				let timer=setTimeout(function(){/* 因为js代码执行很快,页面没渲染好就获取offsetHeight会获取不到,等100ms就可以了 */
					carouse_wrap.style.height=img.offsetHeight+"px"
				},100)
				clearTimeout(timer)//清除
				
				/* ==================创建轮播完================= */
				/* ==================滑屏======================= */
				let ElStartX = 0;	//元素当前位置
				let startX = 0;		//记录手点击起始位置
				let moveX = 0;		//记录手指滑动距离
				let endX = 0;		//记录手指抬起时位置
				let index = 0;		//记录当前轮播的下标
				/* 手指点击屏幕事件 获取手指和当前元素位置*/
				carouse_wrap.addEventListener("touchstart",function(ev){
					ev = event||ev;
					/* &&&&&&&&&&&&自动轮播2&&&&&&&&&&&&&&& */
					if(needAutoCarouse!=null){
						clearInterval(AutoTimer)//点击时清除自动轮播
					}
					
					ElStartX = ul.offsetLeft;//获取元素当前位置
					startX = ev.changedTouches[0].clientX;//获取手指点击位置
					ul.style.transition="none";					//清除过渡,在手指抬起事件中绑定,这里要清掉,因为影响滑屏体验
					
					/* ===========无缝滑屏2======== */
					if(needCarouse!=null){//如果不为null表示用户需要无缝轮播
						moveX = 0;
						if(index===0){/* 如果是第一个数组第一张 */
							index=arr.length/2								//如果当前是第一张轮播图让index瞬间变为第二个数组的第一张
							ElStartX=-index * img.offsetWidth;				//起始位置变为第二个数组第一张
							ul.style.left = -index * img.offsetWidth+"px";	//ul偏移到第二个数组第一张
						}else if(index===(arr.length-1)){/* 如果是第二个数组最后一张 */					
							index=arr.length/2-1							//让index瞬间变为第一个数组最后一张
							ElStartX=-index * img.offsetWidth;				//起始位置变为第一个数组最后一张
							ul.style.left = -index * img.offsetWidth+"px";	//偏移到第一个数组最后一张
						}else{/* 如果不是第一和最后一张,普通的获取值即可 */
							ElStartX = ul.offsetLeft;//获取元素当前位置
						}
						
					}else{/* 是null表示不需要 */
						ElStartX = ul.offsetLeft;//获取元素当前位置
					}
					
					
				})
				/* 手指移动事件 让元素跟随手指移动*/
				carouse_wrap.addEventListener("touchmove",function(ev){
					ev = ev||event;
					let nowX = ev.changedTouches[0].clientX;	//获取滑动时的位置
					moveX = nowX - startX;						//获取滑动距离
					ul.style.left = ElStartX + moveX + "px";	//让ul跟随手指偏移
				})
				/* 手指抬起事件 判断移动距离,如果超过100px的距离,就让轮播跳转到下一张或上一张,第一张和最后一张怎么滑都会回到原来的位置*/
				carouse_wrap.addEventListener("touchend",function(ev){
					ev = ev||event;
					
					/* 无缝滑屏3,改改逻辑 */
					if(needCarouse!=null){//如果不为null表示用户需要无缝轮播
						if(moveX > 0 && moveX >= 100){//>0表示向右滑动屏幕
							index--;
						}else if(moveX < 0 && moveX <= -100){
							index++;
						}
					}else{
						if(moveX > 0 && moveX >= 100){//>0表示向右滑动屏幕
							index===0?index=0:index--;		//如果index=0了就让index=4,否则就自减
						}else if(moveX < 0 && moveX <= -100){
							index===4?index=4:index++;
						}
					}
					
					ul.style.transition="0.5s left";//设置动画,在手指抬起时才设置
					
					ul.style.left = -index * img.offsetWidth+"px";//让ul偏移当前图片下标*单张轮播宽度的距离
					
					/* &&&&&&&&&&&&&自动轮播3&&&&&&&&&&&&&&&& */
					if(needAutoCarouse!=null){
						AutoCarouse();//手指抬起时,重新启动自动轮播
					}
					
				})
				function AutoCarouse(){
					AutoTimer = setInterval(function(){
						if(needCarouse!=null){//如果不为null表示用户需要无缝轮播
							
							if(index===arr.length-1){/* 如果是第二个数组最后一张 */
								ul.style.transition="none";//设置动画,在手指抬起时才设置				
								index=arr.length/2-1							//让index瞬间变为第一个数组最后一张
								ul.style.left = -index * img.offsetWidth+"px";	//偏移到第一个数组最后一张
							}
							setTimeout(function(){
								index++
								ul.style.transition="0.5s left";//设置动画,在手指抬起时才设置
								ul.style.left = -index * img.offsetWidth+"px";//让ul偏移当前图片下标*单张轮播宽度的距离
							},500)
						}else{
								index===arr.length-1?index=0:index++;
								ul.style.transition="0.5s left";//设置动画,在手指抬起时才设置
								ul.style.left = -index * img.offsetWidth+"px";//让ul偏移当前图片下标*单张轮播宽度的距离
						}
					},1000)
				}
			}
		}
	</script>
</html>

二、使用less来rem适配

首先你得了解如何适配
设计稿尺寸为1080

在这里插入图片描述
在这里插入图片描述

1、新建less文件使用考拉打包

在这里插入图片描述

//css reset
html,body,h1,h2,h3,h4,h5,p,a,img,span,div,input,form,ul{margin: 0;padding: 0;}
html,body{height: 100%;overflow: hidden;}
ul{list-style: none;}
a{text-decoration: none;display: block;}
img{display: block;}
a,input,button{-webkit-tap-highlight-color: rgba(0,0,0,0);outline: none;border:0;}//禁用这3个元素的选中高亮显示
button{-webkit-appearance: none;}//禁用button的特殊样式

//首先,我们font-size的值是动态的那么1rem也是动态的,我这里通常1rem就是视图尺寸的1/16
//所以我们只需要让设计图尺寸1080/16rem,就可以得到设计图对应当前手机的rem尺寸,
//16rem是当前屏幕的像素大小,1080是设计图大小,1080/16rem,就可以获取到设计图对应到当前屏幕的一个比例
@rem:1080/16rem;
#wrap{
	height: 100%;
	overflow: auto;
	.head{
		position: absolute;
		width: 100%;
		height: 100px;
		background-color: pink;
		.logo {
			img{
				/* 	方法一
					适配logo大小,首先我们将屏幕分成了16rem,
					而设计图大小为1080,logo大小240,240/1080=0.222222
					0.222222*16rem=3.555555555555556rem
				 */
				// width: 3.555555555555556rem; 很麻烦有没有
				
				/* 方法2
					图片尺寸240,@rem是当前设计图占多少份rem
					240/@rem=相应适配的rem值
				 */
				width:240/@rem;/* 240/67.5个rem,就是当前屏幕适配的rem */
			}
		}
	}
}

2、页面引入

在这里插入图片描述

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
		<title></title>
		<link rel="stylesheet" type="text/css" href="assets/css/index.css"/>
	</head>
	<body>
		<div id="wrap">
			<div class="head"><!-- 头部组件 -->
				<div class="head-top"><!-- 头部组件的上面部分 -->
					<h1 class="logo">
						<a href="javascript:;">
							<img src="assets/img/logo.png" >
						</a>
					</h1>
				</div>
				<div class="head-bottom"><!-- 头部组件下面的导航部分 -->
					
				</div>
			</div>
				
		</div>
	</body>
	<script type="text/javascript">
		window.onload=function(){
			/* 全局禁用默认事件 */
			document.addEventListener("touchstart",function(ev){
				ev = ev||event;
				ev.preventDefault();
			});
			/* 获取适配 */
			(function(){
				let style = document.createElement("style");//创建style结点
				let width = document.documentElement.clientWidth/16;//让widht为视口的16分之一
				style.innerHTML="html{font-size:"+width+"px !important}";//设置根标签字体大小
				document.head.appendChild(style);//将其添加到head
			})();
		}
	</script>
</html>

在这里插入图片描述在这里插入图片描述

三、尚硅谷谷粒音乐实战,b站搜就有视频和配套资源

1、工具类

/* 专门用来给node节点改变className属性的 */
(function(w){
	w.tools={};//暴露此对象,给window,同此对象来调用方法
	
	tools.addClass=function(node,className){
		let reg = new RegExp("\\b"+className+"\\b");//正则表达式,匹配所有className
		if(!reg.test(node.className)){
			node.className+=(" "+className);
		}
	}
	tools.removeClass=function(node,className){
		if(node.className){
			let reg = new RegExp("\\b"+className+"\\b");
			let classes = node.className;
			node.className = classes.replace(reg,"");
			if(/^\s*$/g.test(node.className)){
				node.removeAttribute("class");
			}
		}else{
			node.removeAttribute("class")
		}
	}
})(window)

2、无缝轮播

/* 动态生成轮播图 */
(function(w){
	w.carouse={};
	carouse.initCarouse=function(a){
		let arr = a;//模拟从后台获取的轮播图列表
		
		let carouse_wrap = document.querySelector(".carouse_wrap");//获取轮播容器
		
		if(carouse_wrap){//如果轮播存在
			
			/* 无缝1、复制数组 并确定用户是否需要无缝功能*/
			
			/* 
				看看<div class="carouse_wrap" needCarouse >,加没加needCarouse,如果加了,表示用户需要无缝功能,没加就是null表示不需要无缝
			 */
			let needCarouse = carouse_wrap.getAttribute("needCarouse");//判断用户是否需要无缝功能
			
			if(needCarouse!=null){/* 如果不是null,表示需要无缝功能 */
				let arrLength = arr.length;//保存当前数组的长度,因为复制数组会让数组长度改变
				
				arr = arr.concat(arr)//向arr数组后面添加数组arr,生成一个全新的数组,然后重新赋值给arr
			}
			
			/* &&&&&&&&&&&&&自动轮播1、&&&&&&&&&&&&&&&& */
			let needAutoCarouse = carouse_wrap.getAttribute("needAutoCarouse");/* 如果有此参数,表示用户开启自动轮播 */
			if(needAutoCarouse!=null){
				let AutoTimer = 0;//用来保存自动轮播时间函数id
				AutoCarouse();	  //自动轮播函数
			}
			
			/* dom结点 */
			let ul = document.createElement("ul");		//创建一个ul结点
			let style = document.createElement("style");//创建一个style结点
			let head = document.querySelector("head");	//获取head结点
			
			ul.classList.add("list")					//给创建的ul的class列表添加一个.list样式
			ul.style.transform="translateZ(0)";			//开启3d硬件加速,只要开启3d就会跳过浏览器,使用硬件加载
			for(let i = 0;i<arr.length;i++){//遍历数组,有多少图片就添加多少轮播结构
				ul.innerHTML+='<li><a href="javascript:;"><img src="'+arr[i]+'" ></a></li>'
			}
			
			carouse_wrap.appendChild(ul)				//把ul添加到容器中
			
			/* (重点)给style结点添加样式,首先
				我们应该先确定单张图片的大小,这里我就直接用百分比让图片填满屏幕了
				那么,我们应该让ul的宽度正好容纳这些轮播图片,比如5张图片就是500%
				
				那么5张图片,每张就占ul的20%,5*20%=100%,正好填满ul
			 */
			style.innerHTML="#wrap .carouse_wrap > .list{width: "+arr.length*100+"%;}#wrap .carouse_wrap > .list > li{width: "+100/arr.length+"%;}"
			
			head.appendChild(style)//将style结点添加到head中
			
			/* 最后,因为每个li都设置的定位,容器就没有东西撑开造成高度塌陷,我们只需要让其等于图片高度即可 */
			let img = document.querySelector("#wrap .carouse_wrap > .list > li:nth-of-type(1) > a > img");
			
			let timer=setTimeout(function(){/* 因为js代码执行很快,页面没渲染好就获取offsetHeight会获取不到,等100ms就可以了 */
				carouse_wrap.style.height=img.offsetHeight+"px"
			},100)
			clearTimeout(timer)//清除
			
			/* ==================创建轮播完================= */
			/* ==================滑屏======================= */
			let ElStartX = 0;	//元素当前位置
			let startX = 0;		//记录手点击起始位置
			let moveX = 0;		//记录手指滑动距离
			let endX = 0;		//记录手指抬起时位置
			let index = 0;		//记录当前轮播的下标
			/* 防抖动
				判断用户首次滑屏方向
					x轴
						不管用户怎么滑都会抖
					y轴
						不管用户怎么滑都不会抖
			 */
			let startY = 0;		//记录y轴,用来防抖动
			let moveY = 0;		//防抖动
			let XOrY = true;//true表示x轴,false表示y轴
			let first = true;//true表示首次滑,false表示不是首次滑
			
			/* 手指点击屏幕事件 获取手指和当前元素位置*/
			carouse_wrap.addEventListener("touchstart",function(ev){
				ev = event||ev;
				/* &&&&&&&&&&&&自动轮播2&&&&&&&&&&&&&&& */
				if(needAutoCarouse!=null){
					clearInterval(AutoTimer)//点击时清除自动轮播
				}
				
				ElStartX = ul.offsetLeft;//获取元素当前位置
				startX = ev.changedTouches[0].clientX;//获取手指点击位置
				startY = ev.changedTouches[0].clientY;//获取y轴位置,防抖动
				ul.style.transition="none";					//清除过渡,在手指抬起事件中绑定,这里要清掉,因为影响滑屏体验
				
				/* ===========无缝滑屏2======== */
				if(needCarouse!=null){//如果不为null表示用户需要无缝轮播
					moveX = 0;
					if(index===0){/* 如果是第一个数组第一张 */
						index=arr.length/2								//如果当前是第一张轮播图让index瞬间变为第二个数组的第一张
						ElStartX=-index * img.offsetWidth;				//起始位置变为第二个数组第一张
						ul.style.left = -index * img.offsetWidth+"px";	//ul偏移到第二个数组第一张
					}else if(index===(arr.length-1)){/* 如果是第二个数组最后一张 */					
						index=arr.length/2-1							//让index瞬间变为第一个数组最后一张
						ElStartX=-index * img.offsetWidth;				//起始位置变为第一个数组最后一张
						ul.style.left = -index * img.offsetWidth+"px";	//偏移到第一个数组最后一张
					}else{/* 如果不是第一和最后一张,普通的获取值即可 */
						ElStartX = ul.offsetLeft;//获取元素当前位置
					}
					
				}else{/* 是null表示不需要 */
					ElStartX = ul.offsetLeft;//获取元素当前位置
				}
				
				
			})
			/* 手指移动事件 让元素跟随手指移动*/
			carouse_wrap.addEventListener("touchmove",function(ev){
				ev = ev||event;
				
				if(!XOrY){//放抖动=========如果首次在y轴滑,不执行下面逻辑
					return;
				}
				
				let nowX = ev.changedTouches[0].clientX;	//获取滑动时的位置
				let nowY  = ev.changedTouches[0].clientY;	//防抖动,获取当前y轴位置
				
				moveX = nowX - startX;						//获取滑动距离
				moveY = nowY - startY;						//获取y轴滑动距离
				
				/* 防抖动
					判断用户首次滑屏方向
						x轴
							不管用户怎么滑都会抖
						y轴
							不管用户怎么滑都不会抖
				 */
				if(first){//如果是首次滑屏,判断是x轴滑还是y轴滑,不是首次就不在进行下面的判断
					//让first = false;表示不是首次滑动了
					first = false;
					if(Math.abs(moveY)>Math.abs(moveX)){//如果y滑动距离比x大,说明是上下滑不是左右滑
						XOrY = false;//表示首次滑屏为y轴
						return;//如果是y轴,就不让它执行下面的偏移
					}
				}
				ul.style.left = ElStartX + moveX + "px";	//让ul跟随手指偏移
				
			})
			/* 手指抬起事件 判断移动距离,如果超过100px的距离,就让轮播跳转到下一张或上一张,第一张和最后一张怎么滑都会回到原来的位置*/
			carouse_wrap.addEventListener("touchend",function(ev){
				ev = ev||event;
				/* 防抖动 让XOrY重新置为true,first也变为true表示首次默认x轴 */
				XOrY = true;
				first = true;
				/* 无缝滑屏3,改改逻辑 */
				if(needCarouse!=null){//如果不为null表示用户需要无缝轮播
					if(moveX > 0 && moveX >= 100){//>0表示向右滑动屏幕
						index--;
					}else if(moveX < 0 && moveX <= -100){
						index++;
					}
				}else{
					if(moveX > 0 && moveX >= 100){//>0表示向右滑动屏幕
						index===0?index=0:index--;		//如果index=0了就让index=4,否则就自减
					}else if(moveX < 0 && moveX <= -100){
						index===4?index=4:index++;
					}
				}
				
				ul.style.transition="0.5s left";//设置动画,在手指抬起时才设置
				
				ul.style.left = -index * img.offsetWidth+"px";//让ul偏移当前图片下标*单张轮播宽度的距离
				
				/* &&&&&&&&&&&&&自动轮播3&&&&&&&&&&&&&&&& */
				if(needAutoCarouse!=null){
					AutoCarouse();//手指抬起时,重新启动自动轮播
				}
				
			})
			function AutoCarouse(){
				AutoTimer = setInterval(function(){
					if(needCarouse!=null){//如果不为null表示用户需要无缝轮播
						if(index===arr.length-1){/* 如果是第二个数组最后一张 */
							ul.style.transition="none";//设置动画,在手指抬起时才设置				
							index=arr.length/2-1							//让index瞬间变为第一个数组最后一张
							ul.style.left = -index * img.offsetWidth+"px";	//偏移到第一个数组最后一张
						}
						setTimeout(function(){
							index++
							ul.style.transition="0.5s left";//设置动画,在手指抬起时才设置
							ul.style.left = -index * img.offsetWidth+"px";//让ul偏移当前图片下标*单张轮播宽度的距离
						},500)
					}else{
							index===arr.length-1?index=0:index++;
							ul.style.transition="0.5s left";//设置动画,在手指抬起时才设置
							ul.style.left = -index * img.offsetWidth+"px";//让ul偏移当前图片下标*单张轮播宽度的距离
					}
				},1000)
			}
		}
	}
})(window)

3、用来继承的less

.clearfix{
	*zoom: 1;
	&:after{
		content: "";
		display: block;
		clear: both;
	}
}

4、混合less

.1-px(top,@color:black){
	position: relative;
	&::before{
		position: absolute;
		content: "";
		display: block;
		top: 0;
		width: 100%;
		height: 1px;
		background: @color;
		@media only screen and (-webkit-device-pixel-ratio:2){
			transform: scaleY(.5);
		}
		@media only screen and (-webkit-device-pixel-ratio:3){
			transform: scaleY(.33333333);
		}
	}
}
.1-px(bottom,@color:black){
	position: relative;
	&::before{
		position: absolute;
		content: "";
		display: block;
		bottom: 0;
		width: 100%;
		height: 1px;
		background: @color;
		@media only screen and (-webkit-device-pixel-ratio:2){
			transform: scaleY(.5);
		}
		@media only screen and (-webkit-device-pixel-ratio:3){
			transform: scaleY(.33333333);
		}
	}
}

5、轮播图less

#wrap{
	.carouse_wrap{
		> .list{
			list-style: none;
			overflow: hidden;
			position: relative;
			> li{
				float: left;
				> a{
					display: block;
					> img{
						display: block;
						width: 100%;
					}
				}
			}
		}
	} 
}

6、主体less

//css reset
html,body,h1,h2,h3,h4,h5,p,a,img,span,div,input,form,ul{margin: 0;padding: 0;}
html,body{height: 100%;overflow: hidden;}
ul{list-style: none;}
a{text-decoration: none;display: block;}
img{display: block;}
a,input,button{-webkit-tap-highlight-color: rgba(0,0,0,0);outline: none;border: 0;}//禁用这3个元素的选中高亮显示
button{-webkit-appearance: none;}//禁用button的特殊样式
.txt {/* 禁用长按文字选中功能 */
    -webkit-touch-callout:none;
    -webkit-user-select:none;
    -khtml-user-select:none;
    -moz-user-select:none;
    -ms-user-select:none;
    user-select:none;
}
//首先,我们font-size的值是动态的那么1rem也是动态的,我这里通常1rem就是视图尺寸的1/16
//所以我们只需要让设计图尺寸1080/16rem,就可以得到设计图对应当前手机的rem尺寸,
//16rem是当前屏幕的像素大小,1080是设计图大小,1080/16rem,就可以获取到设计图对应到当前屏幕的一个比例
@rem:1080/16rem;
@import 'mixin/1-px';
@import 'extend/clearfix';//清除浮动
#wrap{
	height: 100%;
	overflow: auto;
	background-color: #EEEEEE;
	.head{
		position: relative;
		width: 100%;
		height: 270/@rem;
		background-color: #232323;
		.head-top{
			height: 135/@rem;
			.logo {
				float: left;
				img{
					width:240/@rem;
					height: 88/@rem;
					padding: 26/@rem 17/@rem 21/@rem 17/@rem;//上右下左
					
				}
			}
			.menuBtn{
				float: left;
				width: 129/@rem;
				height: 135/@rem;
				background: url(../img/menuBtn.png) no-repeat;
				background-size: 82/@rem 233/@rem;
				background-position: center 16/@rem;
				&.active{
					background-position: center -120/@rem;
				}
			}
			.buttons{
				float: right;
				padding-top:21/@rem;
				a{
					float: left;
					width: 111/@rem;
					height: 78/@rem;
					line-height: 78/@rem;
					background-color: #690;
					color: #ccc;
					margin-right: 15/@rem;
					font-size: 42/@rem;
					text-align: center;
					border-radius: 8/@rem;
					&.search{
						width: 130/@rem;
						height: 88/@rem;
						color: #fff;
						margin-right: 30/@rem;
						margin-top: 3/@rem;
						font-weight: bold;
						border-radius:10/@rem;
					}
				}
			}
		}
		.head-bottom{
			height: 103/@rem;
			padding: 16/@rem;
			.search{
				input[type="text"]{
					box-sizing: border-box;
					width: 829/@rem;
					height: 103/@rem;
					background-color: #999;
					padding: 5/@rem 10/@rem;
					border:1px solid #5a5a5a;
					font-size: 41/@rem;
					color: #333;
					border-radius: 15/@rem 0 0 15/@rem;
				}
				input[type="button"]{
					box-sizing: border-box;
					width: 190/@rem;
					height: 103/@rem;
					background-color: #414040;
					font-size: 41/@rem;
					color: #fff;
					border-radius: 15/@rem;
				}
			}
		}
		.mask{
			.1-px(top,#6a6a6a);
			position: absolute;
			z-index: 2;
			top: 135/@rem;
			width: 100%;
			padding: 10/@rem 0;
			display: none;
			background-color: rgba(0,0,0,0.8);
			> li{
				float: left;
				width: 22.5%;
				height: 135/@rem;
				line-height: 135/@rem;
				font-size: 54/@rem;
				text-align: center;
				> a{
					color: white;
				}
			}
		}
	}
	.content{
		overflow-x:hidden ;
		overflow-y: scroll;
		// background: pink;
		position: absolute;
		top: 270/@rem;
		bottom: 0;
		left: 0;
		right: 0;
		.nav{
			.1-px(bottom);
			width: 100%;
			height: 177/@rem;
			box-sizing: border-box;
			background: #EEEEEE;
			padding: 31/@rem 0 14/@rem 0;
			.list{
				position: absolute;
				font-size: 0;
				white-space: nowrap;/* 重点,让宽度不一样的元素排成一行规范,让元素不换行 */
				float: left;/* 重点,让宽度不一样的元素排成一行规范,浮动起来才能让容器被不换行的元素撑开 */
				> li{
					display: inline-block;/* 重点,让宽度不一样元素排成一行,float不能用,容器宽度不够会自动换行 */
					height: 129/@rem;
					line-height: 129/@rem;
					padding: 0 38/@rem;
					font-size: 1rem;
					a{
						color: #020202;
					}
					&.active{
						background: #690;
						a{
							color: #fff;
						}
					}
				}
			}
		}
		.tap_wrap{
			width: 1046/@rem;
			background: #FFFFFF;
			overflow: hidden;
			margin: 0 auto;
			.tap_head{
				height: 135/@rem;
				line-height: 135/@rem;
				h2{
					float: left;
					font-size: 1rem;
				}
				span{
					float: right;
					font-size: 0.7rem;
				}
			}
			.tap_nav{
				position: relative;
				height: 105/@rem;
				line-height: 105/@rem;
				a{
					float: left;
					height: 105/@rem;
					width:  120/@rem;
					font-size: 44/@rem;
					text-align: center;
					color: #6b6b6b;
				}
				.smallG{
					position: absolute;
					left: 0;
					bottom: 10/@rem;
					width:120/@rem;
					height:9/@rem;
					background: #6f900d;
				}
			}
			.tap_content{
				&:extend(.clearfix all);
				width: 300%;
				position: relative;
				ul{
					float: left;
					&:extend(.clearfix all);//使用继承样式
					width: 33.3333333%;
					li{
						box-sizing: border-box;
						float: left;
						width: 506/@rem;
						margin: 8/@rem;
						padding: 5/@rem;
						font-size: 40/@rem;
						background-color: #efefef;
						color: #000;
						overflow: hidden;
						a{
							img{
								width: 100%;
							}
							span{
								display: block;
								overflow: hidden;
								text-overflow:ellipsis;
								white-space: nowrap;
							}
						}
						.tap_discuss{
							.right{
								float: left;
								margin-right: 30/@rem;
								vertical-align: middle;
								span:nth-child(1){
									vertical-align: middle;
									display: inline-block;
									height: .6rem;
									width: .8rem;
									background: url(../img/ice.png) no-repeat;
									margin-right: 5/@rem;
								}
							}
							.left{
								float: left;
								vertical-align: middle;
								span:nth-child(1){
									vertical-align: middle;
									display: inline-block;
									width: .8rem;
									height: .6rem;
									background: url(../img/ice.png) no-repeat;
									background-position:0rem -60/@rem;
									margin-right: 5/@rem;
								}
							}
						}
						
					}
				}
				.tap_loding{
					background: url(../img/loading.gif) no-repeat;
					height: 10rem;
					background-position: center;
				}
			}
		}
	}
}

7、页面

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
		<title></title>
		<link rel="stylesheet" type="text/css" href="assets/css/index.css"/>
		<link rel="stylesheet" type="text/css" href="assets/css/carouse/carouse.css"/>
	</head>
	<body>
		<div id="wrap">
			<div class="head"><!-- 头部组件 -->
				<div class="head-top"><!-- 头部组件的上面部分 -->
					<h1 class="logo"><!-- logo -->
						<a href="javascript:;">
							<img src="assets/img/logo.png" >
						</a>
					</h1>
					<a href="javascript:;" class="menuBtn"><!-- 面包屑导航 -->
					</a>
					<div class="buttons">
						<a href="javascript:;" class="search">搜索</a>
						<a href="javascript:;">登陆</a>
						<a href="javascript:;">注册</a>
					</div>
				</div>
				<div class="head-bottom"><!-- 头部组件下面的导航部分 -->
					<div class="search">
						<input type="text" placeholder="点我" />
						<input type="button" value="搜索" />
					</div>
				</div>
				<ul class="mask">
					<li>
						<a href="javascript:;">首页</a>
					</li>
					<li>
						<a href="javascript:;">MV</a>
					</li>
					<li>
						<a href="javascript:;">约旦</a>
					</li>
					
					<li>
						<a href="javascript:;">v榜</a>
					</li>
					<li>
						<a href="javascript:;">音乐</a>
					</li>
					
					<li>
						<a href="javascript:;">商城</a>
					</li>
					<li>
						<a href="javascript:;">节目</a>
					</li>
					
					<li>
						<a href="javascript:;">饭团</a>
					</li>
					<li>
						<a href="javascript:;">咨询</a>
					</li>
					
					<li>
						<a href="javascript:;">我的家</a>
					</li>
					<li>
						<a href="javascript:;">APP下载</a>
					</li>
					<li>
						<a href="javascript:;">热门引用</a>
					</li>
				</ul>
			</div>
			<div class="content">
				<div class="nav">
					<ul class="list txt">
						<li class="active">
							<a href="javascript:;">首页</a>
						</li>
						<li>
							<a href="javascript:;">MV</a>
						</li>
						<li>
							<a href="javascript:;">约旦</a>
						</li>
						
						<li>
							<a href="javascript:;">v榜</a>
						</li>
						<li>
							<a href="javascript:;">音乐</a>
						</li>
						
						<li>
							<a href="javascript:;">商城</a>
						</li>
						<li>
							<a href="javascript:;">节目</a>
						</li>
						
						<li>
							<a href="javascript:;">饭团</a>
						</li>
						<li>
							<a href="javascript:;">咨询</a>
						</li>
						
						<li>
							<a href="javascript:;">我的家</a>
						</li>
						<li>
							<a href="javascript:;">APP下载</a>
						</li>
						<li>
							<a href="javascript:;">热门引用</a>
						</li>
					</ul>
				</div>
				<div class="carouse_wrap" needCarouse needAutoCarouse ><!-- 轮播容器 -->
				</div>
				<div class="tap_wrap"><!-- tap选项卡 -->
					<div class="tap_head"><!-- tap头信息 -->
						<h2>MV主播</h2>
						<span>更多&gt;</span>
					</div>
					<div class="tap_nav"><!-- tap导航 -->
						<a href="javascript:;">全部</a>
						<a href="javascript:;">内地</a>
						<a href="javascript:;">港台</a>
						<a href="javascript:;">欧美</a>
						<a href="javascript:;">韩国</a>
						<a href="javascript:;">日本</a>
						<span class="smallG"></span>
					</div>
					<div class="tap_content"><!-- tap内容 -->
						<ul class="tap_loding"></ul>
						<ul>
							<li>
								<a href="javascript:;">
									<img src="assets/img/a.jpg" />
									<span>安联大厦块级父垃圾广告士大夫</span>
								</a>
								<div class="tap_discuss">
									<div class="right">
										<span></span>
										<span>2000</span>
									</div>
									<div class="left">
										<span></span>
										<span>6</span>
									</div>
								</div>
							</li>
							<li>
								<a href="javascript:;">
									<img src="assets/img/b.jpg" />
									<span>安联大厦块级父垃圾广告士大夫</span>
								</a>
								<div class="tap_discuss">
									<div class="right">
										<span></span>
										<span>2000</span>
									</div>
									<div class="left">
										<span></span>
										<span>6</span>
									</div>
								</div>
							</li>
							<li>
								<a href="javascript:;">
									<img src="assets/img/c.jpg" />
									<span>安联大厦块级父垃圾广告士大夫</span>
								</a>
								<div class="tap_discuss">
									<div class="right">
										<span></span>
										<span>2000</span>
									</div>
									<div class="left">
										<span></span>
										<span>6</span>
									</div>
								</div>
							</li>
							<li>
								<a href="javascript:;">
									<img src="assets/img/d.jpg" />
									<span>安联大厦块级父垃圾广告士大夫</span>
								</a>
								<div class="tap_discuss">
									<div class="right">
										<span></span>
										<span>2000</span>
									</div>
									<div class="left">
										<span></span>
										<span>6</span>
									</div>
								</div>
							</li>
							<li>
								<a href="javascript:;">
									<img src="assets/img/e.jpg" />
									<span>安联大厦块级父垃圾广告士大夫</span>
								</a>
								<div class="tap_discuss">
									<div class="right">
										<span></span>
										<span>2000</span>
									</div>
									<div class="left">
										<span></span>
										<span>6</span>
									</div>
								</div>
							</li>
							<li>
								<a href="javascript:;">
									<img src="assets/img/f.jpg" />
									<span>安联大厦块级父垃圾广告士大夫</span>
								</a>
								<div class="tap_discuss">
									<div class="right">
										<span></span>
										<span>2000</span>
									</div>
									<div class="left">
										<span></span>
										<span>6</span>
									</div>
								</div>
							</li>
						</ul>
						<ul class="tap_loding"></ul>
					</div>
				</div>
				<div class="tap_wrap"><!-- tap选项卡 -->
					<div class="tap_head"><!-- tap头信息 -->
						<h2>MV主播</h2>
						<span>更多&gt;</span>
					</div>
					<div class="tap_nav"><!-- tap导航 -->
						<a href="javascript:;">全部</a>
						<a href="javascript:;">内地</a>
						<a href="javascript:;">港台</a>
						<a href="javascript:;">欧美</a>
						<a href="javascript:;">韩国</a>
						<a href="javascript:;">日本</a>
						<span class="smallG"></span>
					</div>
					<div class="tap_content"><!-- tap内容 -->
						<ul class="tap_loding"></ul>
						<ul>
							<li>
								<a href="javascript:;">
									<img src="assets/img/a.jpg" />
									<span>安联大厦块级父垃圾广告士大夫</span>
								</a>
								<div class="tap_discuss">
									<div class="right">
										<span></span>
										<span>2000</span>
									</div>
									<div class="left">
										<span></span>
										<span>6</span>
									</div>
								</div>
							</li>
							<li>
								<a href="javascript:;">
									<img src="assets/img/b.jpg" />
									<span>安联大厦块级父垃圾广告士大夫</span>
								</a>
								<div class="tap_discuss">
									<div class="right">
										<span></span>
										<span>2000</span>
									</div>
									<div class="left">
										<span></span>
										<span>6</span>
									</div>
								</div>
							</li>
							<li>
								<a href="javascript:;">
									<img src="assets/img/c.jpg" />
									<span>安联大厦块级父垃圾广告士大夫</span>
								</a>
								<div class="tap_discuss">
									<div class="right">
										<span></span>
										<span>2000</span>
									</div>
									<div class="left">
										<span></span>
										<span>6</span>
									</div>
								</div>
							</li>
							<li>
								<a href="javascript:;">
									<img src="assets/img/d.jpg" />
									<span>安联大厦块级父垃圾广告士大夫</span>
								</a>
								<div class="tap_discuss">
									<div class="right">
										<span></span>
										<span>2000</span>
									</div>
									<div class="left">
										<span></span>
										<span>6</span>
									</div>
								</div>
							</li>
							<li>
								<a href="javascript:;">
									<img src="assets/img/e.jpg" />
									<span>安联大厦块级父垃圾广告士大夫</span>
								</a>
								<div class="tap_discuss">
									<div class="right">
										<span></span>
										<span>2000</span>
									</div>
									<div class="left">
										<span></span>
										<span>6</span>
									</div>
								</div>
							</li>
							<li>
								<a href="javascript:;">
									<img src="assets/img/f.jpg" />
									<span>安联大厦块级父垃圾广告士大夫</span>
								</a>
								<div class="tap_discuss">
									<div class="right">
										<span></span>
										<span>2000</span>
									</div>
									<div class="left">
										<span></span>
										<span>6</span>
									</div>
								</div>
							</li>
						</ul>
						<ul class="tap_loding"></ul>
					</div>
				</div>
			</div>	
		</div>
	</body>
	<script src="assets/js/tools.js" type="text/javascript" charset="utf-8"></script><!-- 操作ClassName -->
	<script src="assets/js/Carouse.js" type="text/javascript" charset="utf-8"></script><!-- 无缝滑屏轮播 -->
	<script type="text/javascript">
		window.onload=function(){
			/* 全局禁用默认事件 */
			document.addEventListener("touchstart",function(ev){
				ev = ev||event;
				ev.preventDefault();
			});
			
			/* 无缝轮播 */
			carouse.initCarouse(["assets/img/1.jpg","assets/img/2.jpg","assets/img/3.jpg","assets/img/4.jpg","assets/img/5.jpg"]);
			
			/* 获取适配 */
			(function(){
				let style = document.createElement("style");//创建style结点
				let width = document.documentElement.clientWidth/16;//让widht为视口的16分之一
				style.innerHTML="html{font-size:"+width+"px !important}";//设置根标签字体大小
				document.head.appendChild(style);//将其添加到head
			})();
			
			/* ===================遮罩js=================== */
			
			let mask = document.querySelector("#wrap .head .mask");	
			let menuBtn = document.querySelector("#wrap .head .head-top .menuBtn");
			let flag = false;//用来标识遮罩按钮的状态
			CMCFMenuBtn();
			function CMCFMenuBtn(){
				menuBtn.addEventListener("touchstart",function(ev){
					ev= ev||event;
					flag = !flag;
					if(flag){
						tools.addClass(menuBtn,"active")//给menuBtn的className+上一个active
						mask.style.display="block";//菜单显示
					}else{
						tools.removeClass(menuBtn,"active");//移除active
						mask.style.display="none";//菜单隐藏
					}
					
					ev.stopPropagation();	//取消事件冒泡,避免点击menuBtn触发touchstart事件的时候,
											//触发下面document的touchstart事件
					ev.preventDefault();//记住每次阻止冒泡要重新禁用默认事件,因为全局的阻止默认事件,被阻止冒泡了
				})
				mask.addEventListener("touchstart",function(ev){
					ev = ev||event;
					ev.stopPropagation();/* 取消事件冒泡,避免点击遮罩的时候触发下面document的事件 */
					ev.preventDefault();
				})
				document.addEventListener("touchstart",function(ev){
					ev = ev||event;
					if(flag){
						mask.style.display="none";//菜单隐藏
						flag=!flag;
						tools.removeClass(menuBtn,"active");//移除active
					}			
				})
			}
			/* ==================表单js======================= */
			/* 实现点击文本框,让手机弹出输入法 */
			changeFocus();
			function changeFocus(){
				let inputText = document.querySelector("#wrap .head .head-bottom .search input[type='text']");
				inputText.addEventListener("touchstart",function(ev){
					ev= ev||event;
					inputText.focus();//让文本框获取焦点,输入法会弹出来
					ev.stopPropagation();//不要让事件穿透
					ev.preventDefault();
				})
				/* 点击空白区,让输入法收回 */
				document.addEventListener("touchstart",function(){
					inputText.blur();//移除当前元素所获得的键盘焦点
				})
			}
			/* =====================拖动导航js======================= */
			dragNav();
			function dragNav(){
				//滑屏区域
				let navArea = document.querySelector("#wrap .content .nav");
				//滑屏元素
				let nav_list = document.querySelector("#wrap .content .nav .list");
				let startX = 0;		//手指按下的位置
				let endX = 0;		//手指移开的位置
				let moveX = 0;		//手指移动的距离
				let ElStartX = 0;	//元素一开始的位置
				let transformX = 0;	//元素跟随手指移动的距离
				//元素最后的位置,用滑屏区域-滑屏元素
				let ElEndX = navArea.clientWidth-nav_list.offsetWidth;
				
				/* 快速滑屏需要的参数,实现用户突然加速滑动的良好体验
					通过判断用户是否在短时间内滑动一定量的距离,如果符合,进行快速滑屏
				 */
				let lastTime = 0;	//上次点击的时间
				let nowTime = 0;	//现在的时间
				let lastPoint = 0;	//上次手指位置(不是上次滑屏位置)
				let nowPoint = 0;	//现在位置
				let differenceTime = 0;//上次点击时间与当前时间的差
				let differencePoint = 0;//手指上次位置与当前位置的差
				navArea.addEventListener("touchstart",function(ev){
					ev = ev||event;
					let touchC=ev.changedTouches[0];
					
					nav_list.style.transition="none";//每次点击时清除动画
					startX = touchC.clientX;		 //获取手指初始位置
					ElStartX = nav_list.offsetLeft;	 //获取元素初始位置
					
					/* 快速滑屏 */
					lastTime = new Date().getTime();//设置上传点击时间为当前时间
					lastPoint = startX;				//设置上次点击位置为当前位置
					
					differencePoint = 0;
				})
				navArea.addEventListener("touchmove",function(ev){
					ev = ev||event;
					let touchC = ev.changedTouches[0];
					
					let nowX = touchC.clientX;			//获取当前手指位置
					moveX = nowX-startX;				//获取移动距离
					transformX = ElStartX + moveX;  //元素跟随手指移动距离
					
					
					/* 橡皮筋效果 */
					if(nav_list.offsetLeft>=0){//如果要小于元素最后的位置,就不要让元素继续走,有橡皮筋效果
						/* scale用来保存一个比例,实现我越滑,比例越小,移动距离越短,越难滑的效果
							document.documentElement.clientWidth为视口宽度
							transformX是手指滑动距离 两个值加起来就会越来越大
							clientWidth/(clientWidth+transformX)这个比例就会越来越小,如果给(clientWidth+transformX)*2就更小了
							
							这时让元素移动的距离*这个比例,就会越滑,移动距离越短
						 */
						let scale = document.documentElement.clientWidth/((document.documentElement.clientWidth+transformX)*2);
						transformX = ElStartX + moveX*scale;
					}else if(nav_list.offsetLeft<=ElEndX){//大于0就不要让其往前滑屏,有橡皮筋效果
						let scale = document.documentElement.clientWidth/(document.documentElement.clientWidth+transformX);
						transformX = ElStartX - moveX*scale;
					}
					
					//让元素跟随手指移动
					nav_list.style.left=transformX+'px';
					
					/* 快速滑屏 */
					nowTime = new Date().getTime();	//设置当前时间
					nowPoint = nowX;				//设置当前位置
					
					differencePoint = nowPoint - lastPoint;
					differenceTime = nowTime - lastTime;
					
					lastPoint = nowPoint;
					lastTime = nowTime;
				})
				navArea.addEventListener("touchend",function(ev){
					ev=ev||event;
					/* 快速滑屏 */
					let speed = differencePoint/differenceTime;//距离/时间=速度
					let targetX = transformX + speed*differencePoint;	   //快速滑屏偏移,让当前偏移+速度的50倍
					
					let time = Math.abs(speed)*0.2;				//保存时间,用于设置动画的时间
					time = time<1?1:time;						//让时间不能少于1
					
					if(Math.abs(speed)<0.1){//如果速度小于1
						time = 0;								//让time=0,轻轻滑动不需要动画
						targetX = transformX;					//targetX无需加快速滑屏偏移
					}
					
					let bsr="";//保存贝塞尔曲线
					/* 橡皮筋效果 */
					if(nav_list.offsetLeft>0 || differencePoint>10 ){//如果当前元素偏移>0,或者距离差>10
						targetX = 0;//让targetX=0
						bsr="cubic-bezier(.01,1.36,.46,1.46)";//设置一个贝塞尔曲线
					}else if(nav_list.offsetLeft <= ElEndX ||differencePoint<-10 ){//如果当前元素偏移<元素最后位置,或者距离差<-10
						targetX = ElEndX;//让偏移位置为最后位置
						bsr="cubic-bezier(.01,1.36,.46,1.46)";//设置贝塞尔曲线
					}
					nav_list.style.transition=time+"s "+bsr+" left";//放开一瞬间给贝塞尔曲线动画效果
					
					if(differencePoint!=0){/* 如果=0表示只是点击没有移动,不需要偏移 */
						nav_list.style.left=targetX+'px';//偏移targetX
					}
					
				})
			}
			/* ======================tap选项卡js===================== */
			tap();
			function tap(){
				let tap_wrap = document.querySelector("#wrap .content .tap_wrap");
				let tap_content_ul_all = document.querySelectorAll("#wrap .content .tap_wrap .tap_content");
				let tap_content_smallG_all = document.querySelectorAll("#wrap .content .tap_wrap .tap_nav .smallG");
				let arr=tap_wrap.querySelectorAll("#wrap .content .tap_wrap .tap_nav > a");//获取选项卡下所有导航
				for(let i = 0;i < tap_content_ul_all.length;i++){
					move(tap_content_ul_all[i],tap_content_smallG_all[i],arr.length);//给每个选项卡和对应小绿条添加移动逻辑
				}
				
				function move(content,smallG,length){
					content.style.left = -tap_wrap.offsetWidth+"px";//默认偏移

					let start = {x:0,y:0};//初始手指位置
					let ElStart = {x:0,y:0};//元素初始位置
					let xOrY = true;		//true表示为X轴滑动
					let first = true;		//判断用户是否第一次滑,true表示第一次
					let stop = false;		//决定用户当前能否触发事件
					let isFlag = true;		//判断用户是否划过2分之一
					smallG.index=0;			//初始化小绿下标
					
					content.addEventListener("touchstart",function(ev){
						ev = ev||event;
						xOrY = true;
						isFlag = true;
						if(stop){return;}
						touchC = ev.changedTouches[0];
						start.x = touchC.clientX;
						start.y = touchC.clientY;
						ElStart.x = content.offsetLeft;
						ElStart.y = content.offsetTop;
						stop = false;
						
						content.style.transition = "none";//清除动画效果
					})
					
					content.addEventListener("touchmove",function(ev){
						ev = ev||event;
						if(stop){return;}
						/* 防抖1,如果首次滑为y轴,不执行滑屏逻辑 */
						if(!xOrY){
							return;
						}
						
						touchC = ev.changedTouches[0];
						let now = {x:0,y:0};
						now.x = touchC.clientX;
						now.y = touchC.clientY;
						let difference = {x:now.x - start.x,y:now.y - start.y}//距离
						/* 防抖2,如果是首次就判断是滑的哪个轴 */
						if(first){
							first = false;//变为false表示不再是第一次滑
							if(Math.abs(difference.x) < Math.abs(difference.y)){//如果x的差<y的差,表示y轴滑
								xOrY = false;//false表示y轴
								return;//直接终止本次
							}
						}
						if(Math.abs(difference.x) >= tap_wrap.offsetWidth*1/3){//如果移屏超过2分之一就偏移到过渡动画
							let left = difference.x<0?-2:0;//如果difference.x<0表示左滑>0表示右滑
							content.style.transition = "1s left";
							content.style.left = left*tap_wrap.offsetWidth+"px";
							isFlag = false;//进入2分之一
							
							/* 过渡动画执行完毕,发送请求 */
							stop = true;//阻止用户的触屏事件逻辑
							content.addEventListener("transitionend",endFn);
							content.addEventListener("webkitTransitionEnd",endFn);
							/* 小绿条 */
							smallGMove(left);
						}else{
							content.style.left = ElStart.x + difference.x +"px";
						}
					})
					
					/* 小绿条移动 */
					function smallGMove(left){
						smallG.style.transition = "1s left";
						smallG.lastIndex = smallG.index;//记录当前索引
						if(left === 0 ){//等于0表示右滑
						
							if(smallG.index === 0){//如果等于0,就让小绿条去最后面
								smallG.index = length-1;
							}else{//不等于0就减一
								smallG.index--;
							}
						}else{//左滑
						
							if(smallG.index === length-1){//小绿条在最后面就去最前面
								smallG.index=0;
							}else{
								smallG.index++;
							}
						}
						
						smallG.style.left = smallG.index*smallG.offsetWidth+"px";
					}
					/* 动画执行完毕后,发送请求 */
					function endFn(){
						/* 先解绑事件 */
						content.removeEventListener("transitionend",endFn);
						content.removeEventListener("webkitTransitionEnd",endFn);
						let flag = "";//这个应该是全局的,代表当前请求回来的数据
						let timer = setTimeout(function(){
							flag =  "";/* 将你请求回来的数据替换 ,因为没有后端,就假装模拟一下*/
							
							if(Math.floor((Math.random()*3+1))===2){//有3分之1几率请求失败
								content.style.left = -1*tap_wrap.offsetWidth+"px";
								alert("请求失败");
								/* 小绿条回到上次位置 */
								smallG.index= smallG.lastIndex;
								smallG.style.left = smallG.index*smallG.offsetWidth+"px";
								stop = false;
							}else{//请求成功
								content.style.transition = "none";
								content.style.left = -1*tap_wrap.offsetWidth+"px";
								stop = false;
							}
						clearTimeout(timer)
						},100)
						
					}
					
					content.addEventListener("touchend",function(ev){
						ev = ev||event;
						if(stop){return;}
						touchC = ev.changedTouches[0];
						if(isFlag){//如果是true表示还得回到当前屏
							content.style.transition = "2s left";
							content.style.left = -tap_wrap.offsetWidth+"px";
							//如果回到当前屏依然可以让用户进行下次滑屏
						}else{//如果为false,表示已经滑屏成功,进入加载动画,不准继续滑屏
							stop = true;
							console.log(1)
						}
						xOrY = true;
						first = true;
						isFlag = true;
						// stop = false;
					})
				}
			}
		}
	</script>
</html>

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

殷丿grd_志鹏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值