Dom详细讲解

2023-11-09

1.Dom的基本介绍

1.1 什么是DOM

文档对象模型,英文全称为Document Object Model,它提供了对文档的结构化的表述,并定义了一种方式可以使从程序中对该结构进行访问,从而改变文档的结构,样式和内容。

D:Document,文档,表示的整个Html的网页文档

O:Object, 对象,将网页的每一部分(标签)转换为每一个对象

M:Model,模型,使用模型来表示对象之间的关系,方便我们获取。

DOM 将文档解析为一个由节点和对象(包含属性和方法的对象)组成的结构集合。简言之,它会将web页面和脚本或程序语言连接起来,让脚本来操作页面,使用js代码将页面的样式,内容,结构修改。

通过一些js的方法来获取标签的对象(documet.getElementById()),然后调用属性和方法修改原来标签的样式和内容,结构。

1.2 DOM树

  • 将HTMl文档以树状结构直观的表现出来,我们称之为文档树DOM树
  • 作用:文档树直观的体现了标签与标签之间的关系
document 文档 html页面代码 所有的html结构
object 对象 将html中每一个标签 都变成一个对象
model 模型 用另一种形式展示
  • window是浏览器窗口对象,所有东西都被当作是window的子对象

  • 文档对象document 是window下的一个属性 代表整个DOM文档对象

  • 根元素(root) html标签

  • 文档树(dom树) 以HTML为根节点 形成的一棵倒立的树状结构,我们称作DOM树;这个树上所有的东西都叫节点,节点有很多类(节点共12类)

    • 元素节点 标签

    • 属性节点 属性

    • 文本节点 内容

    • 注释节点 注释

      这些节点如果我们通过DOM方法去获取或者其它的操作去使用的话,就叫DOM对象

1.3 DOM对象如何创建的?

  • 浏览器根据html标签生成的 JS 对象 (DOM对象)
  • DOM的核心就是把内容当**对象**来处理

1.4 Dom0,Dom1,Dom2,Dom3区别

前言:DOM(Document Object Model,文档对象模型)是针对HTML文档和XML(可扩展的标记语言)文档的一个API。DOM描绘了一个层次化的节点树,允许开发人员添加、移出和修改页面的某一部分,DOM脱胎于Netscape及微软公司创始的DHTML(动态HTML)。但现在它已经成为表现和操作页面标记的真正跨平台、语言中立的方式。

  • Dom0
    • Dom0级事件具有极好的跨浏览器优势,会以最快的速度绑定。
    • 为某一个元素的同一个行为绑定不同的方法在行内会分别执行
    • 为某一个元素的同一个行为绑定不同的方法在script标签中后面的方法会覆盖前面的方法
    • 删除Dom0事件处理程序,只要将对应事件的属性设置为null即可
  • Dom1
    • Dom1一般只有设计规范没有具体实现,企业级应用无
  • Dom2
    • Dom2级事件是通过addEventListener绑定的事件,IE下的Dom2事件通过attachEvent绑定
    • 可以给某个元素的同一个行为绑定不同的方法在行内会分别执行
    • 删除Dom2事件处理程序通过removeEventListener
  • Dom3
    • Dom3级事件在Dom2级事件的基础上添加了更多的事件类型
    • 允许开发人员自定义一些事件

2. Dom0事件绑定和解绑

  • 不可以同时添加同一类事件多次,如果添加后面覆盖前面

  • dom0事件解绑 本质上就是把事件回调函数和事件对象的事件属性断开指向

    box.οnclick= null

3. Dom2事件绑定和解绑

前言:dom2事件添加和解绑高低浏览器使用的方法是不同的

高级浏览器才可以使用

  • 事件的解绑

    dom2事件解绑的时候,参数必须和绑定的时候一模一样

    box.addEventListener('click',fn);			
    btn.onclick = function(){
    box.removeEventListener('click',fn);
    }
    
  • 低级浏览器

    • 添加事件监听1

      box.attachEvent('onclick',function(){})				
      //如果添加多个时间,那么也会依次执行,只不过执行顺序和高级浏览器相反
      }
      
    • 添加事件监听2

      function fn1(){
      	console.log('嘿嘿');
      }
      box.attachEvent('onclick',fn1);
      
    • 解绑方式

      function fn1(){
      	console.log('嘿嘿');
      }
      box.attachEvent('onclick',fn1);
      btn.onclick = function(){
      		box.detachEvent('onclick',fn1);
      }
      
  • 封装绑定事件

    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="UTF-8">
    		<title></title>
    		<style>
    			*{
    				margin: 0;
    				padding: 0;
    			}
    			#box{
    				width: 200px;
    				height: 200px;
    				background-color: red;
    			}
    		</style>
    	</head>
    	<body>
    		<div id="box"></div>
    		<button id="btn">点击解绑</button>
    		<script type="text/javascript">
    			window.onload = function(){
    				var box = document.getElementById('box');
    				var btn = document.getElementById('btn');
    				//兼容封装高低浏览器添加事件绑定
    				//dom2事件高级浏览器用的是高级浏览器的添加方式
    				//低级浏览器用的是低级浏览器的添加方式	
    				function addEvent(node,eventType,callBack){
    					if(node.addEventListener){
    						//高级浏览器node.addEventListener值是一个函数数据
    						node.addEventListener(eventType,callBack);
    					}else{
    						//低级浏览器node.addEventListener值是一个undefined
    						node.attachEvent('on' + eventType,callBack);
    					}
    					
    				}
    				function fn2(){
    					console.log('兼容成功');
    				}
    				addEvent(box,'click',fn2);
    			}
    		</script>
    	</body>
    </html>
    
  • 练习:封装解绑事件

4. 事件流

事件流:发生了事件之后的各个盒子的顺序

  • 捕获事件流(网景) 最终很少用几乎不用
  • 冒泡事件流(ie) 最终我们所用的事件传播都是冒泡
  • 标准DOM事件流 这个是我们现用的标准事件流,里面包含三个阶段: 有捕获 再去获取目标元素 最后冒泡,这个三个阶段当中的捕获和冒泡可以由程序员自己选择。但是通常情况我们都是使用默认 (冒泡)

4.1 Dom0事件的事件流

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			.laoda{
				position: relative;
				width: 500px;
				height: 500px;
				background-color: red;
			}
			.laoer{
				position: absolute;
				/*left: 0;
				right: 0;
				bottom: 0;
				top: 0;
				margin: auto;*/
				
				left: 50%;
				top: 50%;
				transform: translate(-50%,-50%);
				
				/*left: 50%;
				top: 50%;
				margin-left: -150px;
				margin-top: -150px;*/
				
				width: 300px;
				height: 300px;
				background-color: green;
			}
			.laomo{
				position: absolute;
				left: 50%;
				top: 50%;
				transform: translate(-50%,-50%);
				width: 100px;
				height: 100px;
				background-color: blue;
			}
		</style>
	</head>
	<body>
		<div class="laoda">
			<div class="laoer">
				<div class="laomo">
					
				</div>
			</div>
		</div>
		
		<script type="text/javascript">
			window.onload = function(){
				var laoda = document.querySelector('.laoda');
				var laoer = document.querySelector('.laoer');
				var laomo = document.querySelector('.laomo');
				//dom0事件的事件流都是冒泡,没有捕获
				//事件的事件流是客观存在的,和事件监听没关系;
				laoda.onclick = function(){
					console.log('我是老大');
				};
				laoer.onclick = function(){
					console.log('我是老二');
				};
				laomo.onclick = function(){
					console.log('我是老末');
				};
			}
		</script>
	</body>
</html>

4.2 事件流整体流程

window.onload = function(){
				var laoda = document.querySelector('.laoda');
				var laoer = document.querySelector('.laoer');
				var laomo = document.querySelector('.laomo');
				//dom0事件的事件流都是冒泡,没有捕获
				//事件的事件流是客观存在的,和事件监听没关系;
				laoda.onclick = function(){
					console.log('我是老大');
				};
				laoer.onclick = function(){
					console.log('我是老二');
				};
				laomo.onclick = function(event){
					console.log('我是老末');
				};
				
				document.body.onclick = function(){
					console.log('我是body');
				};
				document.documentElement.onclick = function(){
					console.log('我是html');
				};
				document.onclick = function(){
					console.log('我是祖宗');
				}
}

4.3 Dom2事件的事件流

Dom2事件冒泡

  • 高级浏览器:
window.onload = function(){
				var laoda = document.querySelector('.laoda');
				var laoer = document.querySelector('.laoer');
				var laomo = document.querySelector('.laomo');
				laoda.addEventListener('click',function(){
					console.log('我是老大');
				},false);
				
				laoer.addEventListener('click',function(){
					console.log('我是老二');
				},false);
				
				laomo.addEventListener('click',function(){
					console.log('我是老末');
				},false);
}
  • 低级浏览器
    • 样式有的版本会丢失,暂时不做过多关注
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			#laoda{
				position: relative;
				width: 500px;
				height: 500px;
				background-color: red;
			}
			#laoer{
				position: absolute;
				/*left: 0;
				right: 0;
				bottom: 0;
				top: 0;
				margin: auto;*/
				
				left: 50%;
				top: 50%;
				transform: translate(-50%,-50%);
				
				/*left: 50%;
				top: 50%;
				margin-left: -150px;
				margin-top: -150px;*/
				
				width: 300px;
				height: 300px;
				background-color: green;
			}
			#laomo{
				position: absolute;
				left: 50%;
				top: 50%;
				transform: translate(-50%,-50%);
				width: 100px;
				height: 100px;
				background-color: blue;
			}
		</style>
	</head>
	<body>
		<div id="laoda">
			<div id="laoer">
				<div id="laomo">

				</div>
			</div>
		</div>

		<script type="text/javascript">
			window.onload = function() {
				var laoda = document.getElementById('laoda');
				var laoer = document.getElementById('laoer');
				var laomo = document.getElementById('laomo');

				laoda.attachEvent('onclick', function() {
					console.log('laoda');
				});

				laoer.attachEvent('onclick', function() {
					console.log('laoer');
				});

				laomo.attachEvent('onclick', function() {
					console.log('laomo');
				})
			}
		</script>
	</body>
</html>

Dom2事件捕获

window.onload = function(){
				var laoda = document.querySelector('.laoda');
				var laoer = document.querySelector('.laoer');
				var laomo = document.querySelector('.laomo');
				laoda.addEventListener('click',function(){
					console.log('我是老大');
				},true);
				
				laoer.addEventListener('click',function(){
					console.log('我是老二');
				},true);
				
				laomo.addEventListener('click',function(){
					console.log('我是老末');
				},true);
}

总结:dom0事件及低级浏览器的dom2事件(没有第三个参数)都是只有冒泡,以后我们用的最多的也是冒泡,捕获几乎不用,高级浏览器的dom2事件可以根据第三个参数选择是捕获还是冒泡,一般我们都不写,默认是冒泡

4.4 阻止冒泡

  • Dom0阻止冒泡
<script type="text/javascript">
			window.onload = function(){
				var laoda = document.querySelector('.laoda');
				var laoer = document.querySelector('.laoer');
				var laomo = document.querySelector('.laomo');
				//dom0事件的事件流都是冒泡,没有捕获
				//事件的事件流是客观存在的,和事件监听没关系;
				laoda.onclick = function(e){
					console.log('我是老大');
					e.stopPropagation();
				};
				laoer.onclick = function(e){
					console.log('我是老二');
					e.stopPropagation();
				};
				laomo.onclick = function(e){
					console.log('我是老末');
					e.stopPropagation();
				};
			}
</script>
  • Dom2高级浏览器阻止冒泡
window.onload = function() {
				var laoda = document.querySelector('.laoda');
				var laoer = document.querySelector('.laoer');
				var laomo = document.querySelector('.laomo');
				laoda.addEventListener('click', function(e) {
					console.log('我是老大');
					e.stopPropagation();
				}, false);

				laoer.addEventListener('click', function(e) {
					console.log('我是老二');
					e.stopPropagation();
				}, false);

				laomo.addEventListener('click', function(e) {
					console.log('我是老末');
					e.stopPropagation();
				}, false);
			}
  • Dom2低级浏览器阻止冒泡
<script type="text/javascript">
					window.onload = function(){
						var laoda = document.getElementById('laoda');
						var laoer = document.getElementById('laoer');
						var laomo = document.getElementById('laomo');
						
						laoda.attachEvent('onclick',function(e){
							console.log('laoda');
							// e.stopPropagation();
							e.cancelBubble = true;
						});
						
						laoer.attachEvent('onclick',function(e){
							console.log('laoer');
							// e.stopPropagation();
							e.cancelBubble = true;
						});
						
						laomo.attachEvent('onclick',function(e){
							console.log('laomo');
							// e.stopPropagation();
							e.cancelBubble = true;
						})	
					}
</script>

5. 事件委派

5.1 什么是事件委派

  • 事件委派过程当中依赖了事件冒泡
  • 事件冒泡的好处就是可以进行事件委派(事件委托,事件代理);把子元素的事件监听添加给父(祖先)元素,把子元素发生的事件委托给父元素进行处理

5.2 事件委派用法

  • 什么时候用?

    • 当一个元素内部子元素(儿子)很多,并且每个子元素(儿子)都要添加相同的事件的时候,我们可以使用事件委派来提高效率
    • 出现新添加的东西,并且新添加的东西要和老的拥有同样的行为;此时我们就想事件委派;不用事件委派,老的身上会有想要的行为,而新添加的没有
  • 用法?

    • 事件委派的做法: 给父元素添加事件监听,不给元素本身添加,事件发生后通过event的target属性去找真正发生事件的目标元素进行处理
  • 好处?

    • 事件委派的好处:可以大大降低内存的占用,并且可以提高效率。
  • 总结

    事件委派其实是借用事件冒泡去做的,因为事件冒泡导致内部所有的元素发生事件都会冒泡到祖先身上,我们不在子元素身上去添加事件监听和处理,而是在共同的祖先身上去添加,让祖先去处理子元素发生的事件;祖先去处理其实就是通过事件对象当中的target 去获取到真正发生事件的子元素;对子元素进行处理

  • 事件委派1

    • 普通移入变色
    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="UTF-8">
    		<title></title>
    	</head>
    	<body>
    		<ul>
    			<li>我是列表项1</li>
    			<li>我是列表项2</li>
    			<li>我是列表项3</li>
    			<li>我是列表项4</li>
    			<li>我是列表项5</li>
    			<li>我是列表项6</li>
    			<li>我是列表项7</li>
    			<li>我是列表项8</li>
    		</ul>
    		<script type="text/javascript">
    			window.onload = function() {
    				var liNodes = document.querySelectorAll('li');
    				for (var i = 0; i < liNodes.length; i++) {
    					liNodes[i].onmouseover = function() {
    						this.style.backgroundColor = 'hotpink';
    					};
    					liNodes[i].onmouseout = function() {
    						this.style.backgroundColor = 'white';
    					};
    				}
    			}
    		</script>
    	</body>
    </html>
    
    • 事件委派变色
    window.onload = function(){
    				//2、事件委派写法(子元素(儿子)很多)
    				//事件监听添加给共有的父(祖先)元素
    				//事件发生在子元素(儿子)身上的时候,会自动冒泡到父元素(爹)身上
    				//父元素(爹)感受到事件发生后,再回过头去找到发生事件的子元素(儿子)
    				// 进行处理
    				var ulNode = document.querySelector('ul');
    				ulNode.onmouseover = function(e){
    					//找到真正发生事件的儿子     目标元素
    					//目标元素是藏在事件对象当中的
    					//事件对象当中target属性就是发生事件的目标元素
    					// (代表的是最内部的一个)
    					console.log(e);
    					if(e.target.nodeName === 'LI'){//不加if有可能拿到的就是爹
    						//这个判断事件委派一般都会有,为了确保目标元素是我们找到的那个元素
    						e.target.style.backgroundColor = 'hotpink';
    					}
    				};		
    				ulNode.onmouseout = function(e){
    					if(e.target.nodeName === 'LI'){
    						e.target.style.backgroundColor = 'white';
    					}
    				};
    			}
    
    • 移入标签不是最内层标签
    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="UTF-8">
    		<title></title>
    	</head>
    	<body>
    		<ul>
    			<li>我是列表项1</li>
    			<li>我是列表项2</li>
    			<li>我是列表项3</li>
    			<li>我是列表项4</li>
    			<li>我是列表项5</li>
    			<li>我是列表项6</li>
    			<li>我是列表项7</li>
    			<li><span>我是列表项8</span></li>
    		</ul>
    	
    		
    		<script type="text/javascript">
    			window.onload = function(){
    				var ulNode = document.querySelector('ul');
    				ulNode.onmouseover = function(e){
    					//找到真正发生事件的儿子     目标元素
    					//目标元素是藏在事件对象当中的
    					//事件对象当中target属性就是发生事件的目标元素(代表的是最内部的一个)
    					console.log(e);
    					if(e.target.nodeName === 'LI'){//不加if有可能拿到的就是爹
    						//这个判断事件委派一般都会有,为了确保目标元素是我们找到的那个元素
    						e.target.style.backgroundColor = 'hotpink';
    					}else if(e.target.parentElement.nodeName === 'LI'){
    						e.target.parentElement.style.backgroundColor = 'hotpink';
    					}
    					
    				};
    				
    				ulNode.onmouseout = function(e){
    					if(e.target.nodeName === 'LI'){
    						e.target.style.backgroundColor = 'white';
    					}else if(e.target.parentElement.nodeName === 'LI'){
    						e.target.parentElement.style.backgroundColor = 'white';
    					}
    				};
    			}
    		</script>
    	</body>
    </html>
    
  • 事件委派2

    • 普通使用
    <!DOCTYPE html>
    <html>
    	<head>
    		<meta charset="UTF-8">
    		<title></title>
    	</head>
    	<body>
    		<ul>
    			<li>我是列表项1</li>
    			<li>我是列表项2</li>
    			<li>我是列表项3</li>
    			<li>我是列表项4</li>
    			<li>我是列表项5</li>
    			<li>我是列表项6</li>
    			<li>我是列表项7</li>
    			<li>我是列表项8</li>
    		</ul>
    		
    		<button>点击添加</button>
    		
    		<script type="text/javascript">
    			window.onload = function(){
    				//本来有一些,然后还可能去动态添加一些新的
    				//老的和新的都要有相同的行为效果
    				//此时就想事件委派
    //				//1、先让原来的li可以移入变色
    				var liNodes = document.querySelectorAll('li');
    				var btn = document.querySelector('button');
    				var ulNode = document.querySelector('ul');
    				
    				for(var i = 0; i < liNodes.length; i++){
    					liNodes[i].onmouseover = function(){
    						this.style.backgroundColor = 'hotpink';
    					};
    					
    					liNodes[i].onmouseout = function(){
    						this.style.backgroundColor = 'white';
    					};
    				}
    				
    				//2、点击按钮添加新的
    				btn.onclick = function(){
    					var liNode = document.createElement('li');
    					liNode.innerHTML = '我是新的';
    					ulNode.appendChild(liNode);
    					liNode.onmouseover = function(){
    						this.style.backgroundColor = 'hotpink';
    					};
    					liNode.onmouseout = function(){
    						this.style.backgroundColor = 'white';
    					};
    				}
    			}
    		</script>
    	</body>
    </html>
    
    
    • 事件委派
    
    		<script type="text/javascript">
    			window.onload = function(){
    				//本来有一些,然后还可能去动态添加一些新的
    				//老的和新的都要有相同的行为效果
    				//此时就想事件委派
    //				//1、先让老的可以移入变色
    				var liNodes = document.querySelectorAll('li');
    				var btn = document.querySelector('button');
    				var ulNode = document.querySelector('ul');
    				//事件委派的写法
    				btn.onclick = function(){
    					var liNode = document.createElement('li');
    					liNode.innerHTML = '我是新的';
    					ulNode.appendChild(liNode);
    				}
    				
    				ulNode.onmouseover= function(e){
    					if(e.target.nodeName === 'LI'){
    						e.target.style.backgroundColor = 'hotpink';
    					}
    				};
    				
    				ulNode.onmouseout = function(e){
    					if(e.target.nodeName === 'LI'){
    						e.target.style.backgroundColor = 'white';
    					}
    				};
    			}
    		</script>
    

6. 两对移入移出区别

  • onmouseover/onmouseout 如果涉及到事件切换或者冒泡必须使用双o

    如果是一个父子元素模型,对父元素添加移入和移出,当鼠标移入父元素里面的子元素的时候,事件会移出然后再移入。也就是说事件元素会有切换;事件委派的时候,必须使用这一对,大部分的时候我们使用的事件流都是冒泡,冒泡一定会涉及到事件的切换,所以我们常用双o事件;

  • onmouseenter/onmouseleave

    如果是一个父子元素模型,对父元素添加移入和移出,当鼠标移入父元素里面的子元素的时候,
    事件并没有移出然后再移入。也就是说事件元素没有切换;

  • 企业级开发中大部分使用的是onmouseenter/onmouseleave 因为不会发生事件切换 不会影响动态效果

    使用双o在部分浏览器下会发生卡顿现象。如果使用冒泡必须使用双o

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			
			#box{
				width: 300px;
				height: 300px;
				background-color: red;
			}
			#box1{
				width: 150px;
				height: 150px;
				background-color: green;
			}
		</style>
	</head>
	<body>
		<div id="box">
			<div id="box1"></div>
		</div>
		
		<script type="text/javascript">
			window.onload = function(){
				var box = document.getElementById('box');
				//如果从外部元素移入到内部元素有事件切换,可以区分出不同元素的
//				box.onmouseover = function(){
//					console.log('移入')
//				};
//				
//				box.οnmοuseοut= function(){
//					console.log('移出')
//				};
				
				//如果从外部元素移入到内部元素没有事件切换,认为内部元素和外部元素就是同一个
				box.onmouseenter = function(){
					console.log('移入')
				};
				
				box.onmouseleave= function(){
					console.log('移出')
				};
			}
		</script>
	</body>
</html>

2. Dom的基本使用

2.1 window.onload

window.onload window.onload是一个事件,在文档加载完成后能立即触发

window.onload = function () {
  var div = document.getElementById("d");
  div.style.color = "red";
};

2.2 事件三要素

事件源 事件的源头 是由谁触发的 btn
事件类型 发生了什么事情 onclick
事件的回调函数 函数没有调用就执行了 我们称之为回调函数 function

事件三要素

  • 事件源 (承受事件的对象)
  • 事件类型onclick
  • 事件处理回调函数 回调函数就是不需要调用就自己执行的函数

事件处理三大步

  • 获取事件源DOM对象
  • 添加对应事件监听(onclick)
  • 书写处理回调

事件写好之后可以重复触发执行;

2.3 获取DOM对象的6种方式

2.3.1 返回一个对象

  • document.getElementById
  • document.querySelector

2.3.2 返回多个对象

  • document.getElementsByTagName
  • document.getElementsByClassName
  • document.getElementsByName
  • document.querySelectorAll

2.3.3 className

className 可以用来获取/修改类名

<p class="p1" id="pp">雨下整夜,我的爱如溢出就像雨水</p>
<button id="btn">按钮</button>
var pp = document.getElementById("pp");
  var btn = document.getElementById("btn");
  btn.onclick = function () {
    pp.className = "p2";
  };

2.3.4 checked (disabled)

<!-- 默认情况下是不选中 -->
<input type="checkbox" id="inp" />
<input type="checkbox" checked="checked" />
<input type="checkbox" checked="a" /> -->
<button id="btn">按钮</button>
<script>
  var btn = document.getElementById("btn");
  btn.onclick = function () {
    // 当属性名字和属性值一致的时候  我们有很多种写的方式
    // 所以呢为了规范书写
    // 当属姓名和属性值一致的时候  eg: checked = "checked"
    // 我们使用true和false的boolean来定义
    var inp = document.getElementById("inp");
    inp.checked = true;    // 选中用true,不选中用false
  };

disabled设置禁用(btn.disabled = “”)设置为空字符串 , 如果不设置(任意字符都可以)

2.4 innerHtml&&innerText&&textContent

修改文本的三个属性

element.textContent 获取或修改元素中的文本内容

  • 获取的是标签中的内容,不会考虑css样式 可以获取隐藏的内容
  • 低级浏览器返回undefined

innerText获取内容时,会考虑css样式

  • 通过innerText去读取CSS样式,会触发网页的重排(计算CSS样式)
  • 当字符串中有标签时,会自动对标签进行转义
  • --> \<li\>
  • 低级浏览器也会正常显示

element.innerHTML 获取或修改元素中的html代码

可以直接向元素中添加html代码

innerHTML插入内容时,有被xss注入的风险

2.4.1 封装innerText&&textContent

// innerText
// textContent
function getOrsetContent(node, content) {
  if (arguments.length == 1) {
    return node.textContent || node.innerText;
  } else if (arguments.length == 2) {
    return node.textContent
      ? (node.textContent = content)
      : (node.innerText = content);
  }
}
var p = document.getElementById("pp");
getOrsetContent(p);

2.5 排他思想

2.5.1 解决策略1

<ul>
      <li>重庆</li>
      <li>成都</li>
      <li>武汉</li>
      <li>长沙</li>
      <li>南京</li>
      <li>杭州</li>
    </ul>
var li_list = document.querySelectorAll("li");
// console.log(li_list);
// li_list.forEach((item, index, arr) => {
//   item.addEventListener("click", function () {
//     arr.forEach((item) => (item.innerHTML = "嘿嘿"));
//     this.innerHTML = "哈哈";
//   });
// });
for (var i = 0; i < li_list.length; i++) {
  li_list[i].onclick = function () {
    li_list.forEach((item) => (item.innerHTML = "嘿嘿"));
    li_list[i].innerHTML = "哈哈";
  };
}

2.5.2 解决策略2

<ul>
  <li>哈哈1</li>
  <li>哈哈2</li>
  <li>哈哈3</li>
  <li>哈哈4</li>
  <li>哈哈5</li>
  <li>哈哈6</li>
</ul>
var li_list = document.querySelectorAll("ul li");
for (var i = 0; i < li_list.length; i++) {
  // 给每一个对象都添加一个属性
  // 属性的名字叫做index  属性的值是i
  li_list[i].index = i;
  li_list[i].onclick = function () {
    for (var j = 0; j < li_list.length; j++) {
      li_list[j].innerHTML = "嘿嘿";
    }
    // 如果想在点击事件内部使用时间外部的i
    // 那就可以使用这种策略
    li_list[this.index].innerHTML = "666";
  };
}

2.6 开关思想

使用flag,赋一个布尔值来改变 true | false

div {
  width: 200px;
  height: 200px;
  margin: 100px auto;
  border-radius: 50%;
  border: 1px solid yellowgreen;
}
var flag = true;
var div = document.querySelector("div");
div.onclick = function () {
  if (flag) {
    this.style.backgroundColor = "yellow";
  } else {
    this.style.backgroundColor = "white";
  }
  flag = !flag;
};

2.7 鼠标事件

  • onclick
  • ondblclick
  • oncontextmenu
  • onmousemove
  • onmouseover/onmouseout
  • onmouseenter/onmouseleave
  • onmousedown/onmouseup

2.8 键盘事件

  • onkeyup
  • onkeydown
  • onfocus
  • onblur

2.9 事件对象

event 事件

​ 事件对象

  • 事件对象是有浏览器在事件触发时所创建的对象,这个对象中封装了事件相关的各种信息
  • 通过事件对象可以获取到事件的详细信息 比如:鼠标的坐标、键盘的按键…
  • 浏览器在创建事件对象后,会将事件对象作为响应函数的参数传递, 所以我们可以在事件的回调函数中定义一个形参来接收事件对象
const box1 = document.getElementById("box1")
// box1.onmousemove = event => {
//     console.log(event)
// }
box1.addEventListener("mousemove", event => {
    console.log(event.clientX, event.clientY)               // 获取鼠标坐标
    box1.textContent = event.clientX + "," + event.clientY
})

2.10 冒泡

在DOM中存在着多种不同类型的事件对象

  • 多种事件对象有一个共同的祖先 Event

    • event.target 触发事件的对象

    • event.currentTarget 绑定事件的对象(同this)

    • event.stopPropagation() 停止事件的传导

    • event.preventDefault() 取消默认行为

  • 事件的冒泡(bubble)
    - 事件的冒泡就是指事件的向上传到
    - 当元素上的某个事件被触发后,其祖先元素上的相同事件也会同时被触发
    - 冒泡的存在大大的简化了代码的编写,但是在一些场景下我们并不希望冒泡存在
    不希望事件冒泡时,可以通过事件对象来取消冒泡

<div id="box1"></div>
<div id="box2"></div>
#box1 {
    width: 100px;
    height: 100px;
    background-color: greenyellow;
    border-radius: 50%;
    position: absolute;
}
#box2 {
    width: 500px;
    height: 500px;
    background-color: orange;
}
/* 使小绿球可以跟随鼠标一起移动
 事件的冒泡和元素的样式无关,之和结构相关  */
const box1 = document.getElementById("box1")
const box2 = document.getElementById("box2")
document.addEventListener("mousemove", (event) => {
    box1.style.left = event.x + "px"                    // 注意拼接单位
    box1.style.top = event.y + "px"
})
box2.addEventListener("mousemove", event => {
    event.stopPropagation()
})

3. Dom节点操作

3.1 节点的概念

  • 什么是节点

    文档树所有包含的东西都可以称作节点;最关注的节点是元素(就是我们平时所说的标签)节点(head body title hr td tr。。)

  • 常用的节点分类

    • 元素节点–标签
    • 文本节点–标签的内容
    • 属性节点–标签的属性
    • 注释节点–注释

3.2 节点类型

							nodeType   nodeName   nodeValue
	文本节点                    3         #text       文本内容
	元素节点                    1         元素名大写   null
	注释节点                    8         #comment    注释内容

3.2.1 子节点和子元素节点

  • childNodes 拿到的是某个元素的子节点:包括子元素节点和文本子节点,如果有注释还有注释节点;

  • children 拿到的是某个元素的子元素节点

  • 子节点:childNodes (儿子节点):

    • 高级浏览器: 元素,文本(文本,空格,换行),注释
    • 低版本浏览器: 元素,文本(不包括空格和换行),注释 (注释前后的空格是计算的,最后标签和结束标签之间的空格)
  • 子元素节点: children(儿子元素):

    • 高级浏览器:元素
    • 低版本浏览器:元素,注释

3.3 获取节点的方式

<ul>
  <li></li>
  <li id='single'></li>
  <li></li>
<ul>
let ul = document.querSelector('ul');

父子关系

  1. 获取ul内部的所有子节点

    console.log(ul.childNodes);//拿到ul所有的子节点 (文本  元素 注释)
    
  2. 获取ul内部的所有子元素节点

    console.log(u.children);//拿到ul所有的子元素节点,低级浏览器还包含注释
    
  3. 获取ul的第一个子节点

    console.log(ul.firstChild);
    
  4. 获取ul的第一个子元素节点,但是只有高级浏览器认识

    console.log(ul.firstElementChild);
    
  5. 获取ul的最后一个子节点

    console.log(ul.lastChild);
    
  6. 获取ul的最后一个子元素节点,但是只有高级浏览器认识

    console.log(ul.lastElementChild);
    

兄弟关系

let liNode = document.quersalary(‘#single’)

  1. 获取li的上一个兄弟节点

    console.log(liNode.previousSibling);
    
  2. 获取li的上一个兄弟元素节点,但是只有高级浏览器认识

    console.log(liNode.previousElementSibling);
    
  3. 获取li的下一个兄弟节点

    console.log(liNode.nextSibling);
    
  4. 获取li的下一个兄弟元素节点,但是只有高级浏览器认识

    console.log(liNode.nextElementSibling);
    

兼容性封装函数

兼容性封装函数 实现获取ul元素的第一个子元素节点

高级浏览器可以正常使用firstElementChild

低级浏览器想办法去使用别的方式拿到

function getFirstElementChild(node){
		//如果有子元素节点就找到这个子元素节点,如果没有就返回null
		if(node.firstElementChild){
			//高级
			return node.firstElementChild;
		}else{
			//低级
			var result = node.firstChild;
			while(result !== null &&  result.nodeType !== 1){
				//如果前面不去判断null,result如果拿到是一个null,result.nodeType就会报错
				result = result.nextSibling;//如果找到最后都没找到,会返回一个null
			}
		return result;
		}
}
console.log(getFirstElementChild(ulNode));

3.4 二级菜单

* {
  margin: 0;
  padding: 0;
}
li {
  list-style: none;
}
a {
  text-decoration: none;
  color: #666;
}
.list {
  position: relative;
  width: 200px;
  height: 150px;
  border: 1px solid #000;
  margin: 100px;
}
.list > li {
  width: 200px;
  height: 50px;
  line-height: 50px;
  text-align: center;
  background-color: aquamarine;
}
.list > li:nth-child(2n) {
  border-bottom: 1px solid #000;
  border-top: 1px solid #000;
  box-sizing: border-box;
}
.list .listIn {
  display: none;
}
.listIn {
  position: absolute;
  width: 200px;
  height: 150px;
  border: 1px solid #000;
  left: 200px;
  top: -1px;
}
.listIn li {
  width: 200px;
  height: 50px;
  background-color: skyblue;
}
.listIn li:nth-child(2n) {
  border-bottom: 1px solid #000;
  border-top: 1px solid #000;
  box-sizing: border-box;
}
.ling {
  position: absolute;
  left: 200px;
  top: 0;
  display: none;
}
<ul class="list">
  <li>
    <a href="#">男歌手</a>
    <ul class="listIn">
      <li>
        <a href="#">汪苏泷</a>
        <ul class="ling">
          <li>123</li>
          <li>123</li>
          <li>123</li>
        </ul>
      </li>
      <li><a href="#">李易峰</a></li>
      <li><a href="#">林俊杰</a></li>
    </ul>
  </li>
  <li>
    <a href="#">女歌手</a>
    <ul class="listIn">
      <li><a href="#">ci_ci</a></li>
      <li><a href="#">旺仔小乔</a></li>
      <li><a href="#">王心凌</a></li>
    </ul>
  </li>
  <li>
    <a href="#">组合</a>
    <ul class="listIn">
      <li><a href="#">牛奶咖啡</a></li>
      <li><a href="#">。。。</a></li>
      <li><a href="#">。。。</a></li>
    </ul>
  </li>
</ul>
let list = document.querySelectorAll(".list > li");
let listIn_list = document.querySelectorAll(".list .listIn");
let ling_list = document.querySelectorAll('.listIn .ling');
for (var i = 0; i < list.length; i++) {
  list[i].index = i;
  list[i].onmouseenter = function () {
    listIn_list[this.index].style.display = "block";
  };
  list[i].onmouseleave = function () {
    listIn_list[this.index].style.display = "none";
  };
}
for(var i = 0; i < ling_list.length; i++) {
  listIn_list[i].index = i;
  listIn_list[i].onmouseenter = function() {
    console.log(ling_list[this.index]);
    ling_list[this.index].style.display = 'block';
  }
}

3.5 创建节点的三种方式

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
	</head>
	<body>
		<p>我是一个段落</p>
		<button>添加h1</button>
	</body>
</html>

3.5.1 动态添加节点

<script type="text/javascript">
			window.onload = function(){
				var btn = document.querySelector('button');
				btn.onclick = function(){
					//第一种动态添加节点,元素的方式,以后不用,因为会覆盖原本有的元素
					document.write('<h1>我是标题</h1>');		
				}
			}
</script>

3.5.2 使用innerHTML

说明:几个特殊元素的获取方式

1、html document.documentElement

2、body document.body

3、head document.head

//直接写=会发生覆盖,因为它是把body里面的 内容修改为'<h1>我是标题</h1>'
//如果不想修改,必须使用+=才能添加元素   
document.body.innerHTML += '<h1>我是标题</h1>';
document.body.innerHTML = document.body.innerHTML + '<h1>我是标题</h1>'

3.5.3 使用方法创建节点

//1、创建一个你想添加的元素   dom对象,但是创建好的这个对象并不在页面上
var h1Node = document.createElement('h1');
//2、把创建好的h1标签写内容
h1Node.innerHTML = '我是标题';
//3、经历完前两步,h1标签就已经准备好了,然后页面上想要看到,必须把h1添加给页面上已经存在的元素
document.body.appendChild(h1Node);//追加的意思就是末尾加

3.6 创建列表添加

3.6.1 获取列表渲染页面1

let arr = ["孙悟空", "猪八戒", "沙和尚", "白骨精", "唐僧", "玉兔公主"];
let str = "<ul>";
  for (let i = 0; i < arr.length; i++) {
  str += "<li>" + arr[i] + "</li>";
  }
document.body.innerHTML = str;

3.6.2 获取列表渲染页面2

let arr = ["孙悟空", "猪八戒", "沙和尚", "白骨精", "唐僧", "玉兔公主"];
let ul = document.createElement('ul');
  for(let i = 0; i < arr.length; i++) {
    let li = document.createElement('li');
    li.innerHTML = arr[i];
    ul.append(li);
  }
                           
 document.body.append(ul);

3.7 节点的增删改

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
	</head>
	<body>
		<ul>
			<li>战狼2</li>
			<li>黑客帝国</li>
			<li>变形金刚</li>
			<li>金刚狼</li>
			<li>蜘蛛侠</li>
		</ul>
	</body>
</html>

3.7.1 添加

//从末尾加   追加
var ulNode = document.querySelector('ul');
var liNode = document.createElement('li');
liNode.innerHTML = '上海堡垒';
ulNode.appendChild(liNode);
				
//从其他位置加
var ulNode = document.querySelector('ul');
var liNode = document.createElement('li');
liNode.innerHTML = '上海堡垒';
var liNodeOld = document.querySelector('li:nth-child(4)');
ulNode.insertBefore(liNode,liNodeOld);

3.7.2 修改

var ulNode = document.querySelector('ul');
var liNodeOld = document.querySelector('li:nth-child(4)');
var liNode = document.createElement('li');
liNode.innerHTML = '钢铁侠';
ulNode.replaceChild(liNode,liNodeOld);

3.7.3 删除

//删除节点
var ulNode = document.querySelector('ul');
var liNodeOld = document.querySelector('li:nth-child(4)');
ulNode.removeChild(liNodeOld);
				
//删除整个ul  下面两种方式都可以
document.body.removeChild(ulNode);
ulNode.parentNode.removeChild(ulNode);

3.8 克隆

cloneNode() 方法对节点进行复制时,它会复制节点的所有特点包括各种属性

这个方法默认只会复制当前节点,而不会复制节点的子节点
可以传递一个 true 作为参数,这样该方法也会将元素的子节点一起复制

/* 点击按钮后,将id为l1的元素添加list2中 */
const list2 = document.getElementById("list2")
const l1 = document.getElementById("l1")
const btn01 = document.getElementById("btn01")
btn01.onclick = function () {
    const newL1 = l1.cloneNode(true) // 用来对节点进行复制的
    /* 
        使用 cloneNode() 方法对节点进行复制时,它会复制节点的所有特点包括各种属性
            这个方法默认只会复制当前节点,而不会复制节点的子节点
            可以传递一个true作为参数,这样该方法也会将元素的子节点一起复制
    
    */
    newL1.id = "newL1"
    list2.appendChild(newL1)
}

3.9 元素 css属性的操作

3.9.1 获取css属性

getComputedStyle 返回的结果都是带单位的,要修改需要使用parseInt或Number把单位去掉

const btn = document.getElementById("btn")
const box1 = document.querySelector(".box1")
btn.onclick = function () {
    /* 
        getComputedStyle()
            - 它会返回一个对象,这个对象中包含了当前元素所有的生效的样式
            - 参数:
                1. 要获取样式的对象
                2. 要获取的伪元素
            - 返回值:
                返回的一个对象,对象中存储了当前元素的样式
            - 注意:
                样式对象中返回的样式值,不一定能来拿来直接计算
                    所以使用时,一定要确保值是可以计算的才去计算
    */
    const styleObj = getComputedStyle(box1)
    console.log(styleObj.width)
    console.log(styleObj.left)
    // console.log(parseInt(styleObj.width) + 100)
    // box1.style.width = parseInt(styleObj.width) + 100 + "px"
    // console.log(styleObj.backgroundColor)
    const beforeStyle = getComputedStyle(box1, "::before")         // 伪类需要使用两个参数的写法
    // console.log(beforeStyle.color)
    console.log(box1.firstElementChild)
}

最为常用的获取样式方法

clientHeight clientWidth 获取元素内部的宽度和高度(包括内容区和内边距)

offsetHeight offsetWidth 获取元素的可见框的大小(包括内容区、内边距和边框)

offsetLeft offsetTop 获取元素相对于其定位父元素的偏移量

offsetParent 获取元素的定位父元素 如果所有的元素都没有开启定位则返回body

scrollWidth scrollHeight 获取元素滚动区域的大小(一般是子盒子超出父盒子出现了滚动条,获取父元素的scrollWidth属性来获取滚动区域的大小)

scrollLeft scrollTop 获取或设置元素滚动条的偏移量

const btn = document.getElementById("btn");
const box1 = document.getElementById("box1");
btn.onclick = function () {
  // console.log(box2.clientWidth);
  // console.log(box2.clientHeight);
  // console.log(box2.offsetWidth);
  // console.log(box2.offsetHeight);
  // console.log(box2.scrollWidth);
  // console.log(box2.scrollHeight);

  // console.log(box1.clientWidth);
  // console.log(box1.clientHeight);
  // console.log(box1.offsetWidth);
  // console.log(box1.offsetHeight);
  // console.log(box1.scrollHeight)
  // console.log(box1.scrollWidth)
  // console.log(box1.offsetParent)
  // console.log(box1.offsetLeft);
  // console.log(box1.offsetTop)
  // console.log(box1.scrollTop)
};

3.9.2 修改css属性

  1. 第一种 直接通过元素的 style 来修改
const btn = document.getElementById("btn")
const box1 = document.querySelector(".box1")
btn.onclick = function () {
    box1.className += " one"    // 注意类名前面的空格,因为一个元素类与类之间有一个空格  <div class="one two"></div>
}
  1. 第二种 通过 classList (推荐)

classList

  • add 添加
  • remove 移除
  • toggle 切换 (无则加,有则删)
  • replace 替换
  • contains 判断是否包含
let div = document.querySelector(".one");
let btn = document.querySelector('#btn');
btn.addEventListener('click', function() {
  // div.className += ' two';
  // div.classList.add('two');                    // 添加
  // div.classList.toggle('two');                 // 切换
  // div.classList.remove('one');                 // 删除
  // div.classList.replace('one', 'three');       // 替换
  // console.log(div.classList.contains('one'));  // 判断是否包含
})

3.10 综合案例

触发回车之后,把表单的内容动态创建li标签,所有的li标签移入变色

<input type="text" id="inp" />
let inp = document.querySelector("#inp");
function AddColor() {
  this.style.backgroundColor = "pink";
}
function RemoveColor() {
  this.style.backgroundColor = "";
}
inp.onkeyup = function (event) {
  if (event.keyCode == 13) {
    if (this.value.trim()) {
      var ul = document.createElement("ul");
      var li = document.createElement("li");
      li.onmouseenter = AddColor;
      li.onmouseleave = RemoveColor;
      li.textContent = this.value;
      ul.append(li);
      document.body.append(ul);
    }
  }
};

4. event对象

onclick 鼠标事件
ondbclick 左键双击
oncontextmenu 右键单机
onmousemove 鼠标移动
onmouseenter 鼠标移入
onmouseleave 鼠标移出
onmouseover 鼠标移入
onmouseout 鼠标移出
onmousedown 按下
oncroll 滚轮

4.1 event概念,作用

系统给我们封装的,任何事件都会有这个event对象,这个对象当中封装了和这个事件相关的一切信息

4.2 event兼容性处理

如果是高级浏览器去调用函数的回调函数,它会把事件对象封装好传给回调函数的第一个形参;

如果是低版本浏览器去调用,它会把事件对象封装好作为window的一个属性 window.event;所以我们在去拿事件对象的时候,要兼容性去拿

event = event || window.event;

4.3 目标元素节点兼容处理

event.target|| event.srcElement

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
	</head>
	<body>
		<ul>
			<li>我是列表项1</li>
			<li>我是列表项2</li>
			<li>我是列表项3</li>
			<li>我是列表项4</li>
			<li>我是列表项5</li>
			<li>我是列表项6</li>
			<li>我是列表项7</li>
			<li><span>我是列表项8</span></li>
		</ul>
	
		
		<script type="text/javascript">
			window.onload = function(){
				var ulNode = document.querySelector('ul');
				ulNode.onmouseover = function(e){
					e = e || window.event;//兼容高低浏览器事件对象写法
					var target = e.target || e.srcElement;
					if(target.nodeName === 'LI'){//不加if有可能拿到的就是爹
						target.style.backgroundColor = 'hotpink';
					}else if(target.parentElement.nodeName === 'LI'){
						target.parentElement.style.backgroundColor = 'hotpink';
					}
					
				};
				
				ulNode.onmouseout = function(e){
					e = e || window.event;
					var target = e.target || e.srcElement;
					if(target.nodeName === 'LI'){
						target.style.backgroundColor = 'white';
					}else if(target.parentElement.nodeName === 'LI'){
						target.parentElement.style.backgroundColor = 'white';
					}
				};
			}
		</script>
	</body>
</html>

5. 鼠标的三种位置

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			
			#box{
				width: 300px;
				height: 300px;
				margin: 50px;
				background-color: red;
			}
			body{
				height: 4000px;
			}
		</style>
	</head>
	<body>
		<div id="box">
		</div>
		<script type="text/javascript">
			var box = document.getElementById('box');
			box.onclick = function(e) {
				//鼠标的位置也是存在于事件对象当中
				e = e || window.event;
				console.log(e);
			}
		</script>
	</body>
</html>

总结:

  • offsetX offsetY

    拿的是鼠标相对自身元素的水平距离和垂直距离 相对的是自身元素左上角(以自身元素左上角为原点)

  • clientX& clientY

    拿的是鼠标相对视口的 水平距离和垂直距离 相对的是视口的左上角(以视口左上角为原点)

  • pageX pageY

    拿的是鼠标相对**页面(第一屏)**的水平距离和垂直距离 相对的是页面的左上角(以页面左上角为原点)

6. 鼠标跟随移动

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			
			img{
				position: absolute;
				left: 0;
				top: 0;
				display: block;
				width: 100px;
				height: 50px;
			}
			
		</style>
	</head>
	<body>
		<img src="img/1.jpg" alt="" />
		<script type="text/javascript">
			window.onload = function(){
				//鼠标移动事件,移动一下,移动事件触发的次数是n次
				//必须通过console打印去确定事件触发了多少次
				var imgNode = document.querySelector('img');
				document.onmousemove = function(e){
//					console.log('移动')
//                  鼠标的位置和图片定位相对的都是视口的原点位置
					//拿到鼠标的位置,就是图片要移动的位置
					e = e || window.event;
					imgNode.style.left = e.clientX + 'px';
					imgNode.style.top = e.clientY + 'px';
				}
			}
		</script>
	</body>
</html>

7. 定时器

  • 单次定时器(延迟定时)

    一般用来做延迟效果 定时炸弹

    • 案例:求出结果延迟5秒打印
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
	</head>
	<body>	
		<button>点击清除定时器</button>
		
		<script type="text/javascript">
			window.onload = function(){
				//延迟定时器就是用来做延迟效果的
				var a = 10;
				var b = 20;
				var c = a + b;
	//			console.log(c);			
				//5秒之后再去打印这个结果			
				//设置延迟定时器
				var timer = setTimeout(function(){
					console.log(c);
				},5000);//延迟的时间以毫秒为单位,定时器返回的都是定时器设置的编号,这个编号对清除定时器有用
					
//				console.log(timer);
				//清除延迟定时器
				var btn = document.querySelector('button');
				btn.onclick = function(){
					clearTimeout(timer);//参数代表的是设置定时器返回的定时器编号
				}				
			}
		</script>
	</body>
</html>
  • 循环定时器的设置和删除

    和循环类似都是为了重复去做一件事 闹钟

    • 案例:每隔3秒打印 老马

      <!DOCTYPE html>
      <html>
      	<head>
      		<meta charset="UTF-8">
      		<title></title>
      	</head>
      	<body>
      		<button>点击清除</button>
      		<script type="text/javascript">
      			var timer = setInterval(function(){
      				console.log('i love you~');
      			},2000);
      					
      			//循环定时器清除
      			var btn = document.querySelector('button');
      			btn.onclick = function(){
      				clearInterval(timer);
      			}
      			//无论是延迟定时器还是循环定时器,清除的时候都需要保存设置定时器的编号
      			//定义保存定时器的编号的变量,一定要定义成全局变量
      			//定时器编号的变量必须是全局变量,否则某些场合没办法清除定时器	
      		</script>
      	</body>
      </html>
      
      
    • 案例2:打印10次大哥之后清除定时器

      <!DOCTYPE html>
      <html>
      	<head>
      		<meta charset="UTF-8">
      		<title></title>
      	</head>
      	<body>
      		<button>点击清除</button>
      		<script type="text/javascript">
      			//设置循环定时器
      			//当打印次数10次,然后就不打印了
      			var n = 0;
      			var timer = null;
      			
      			timer = setInterval(function(){
      				console.log('老马~');
      				n++;
      				if(n === 10){
      					clearInterval(timer);
      				}
      			},2000);
      		</script>
      	</body>
      </html>
      
  • 万年历

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
	</head>
	<body>
		<span></span>
		<script type="text/javascript">
			window.onload = function(){
				function getDateAndTimeNow(){
					var date = new Date();
					var year = date.getFullYear();
					var month = date.getMonth() + 1;
					var day = date.getDate();
					var time = date.toLocaleTimeString();
					return '现在是:' + year + '年' + month + '月' + day + '日 '+ time;
				}
				var spanNode = document.querySelector('span');
				setInterval(function(){
					spanNode.innerHTML = getDateAndTimeNow();
				},1000);
			}
		</script>
	</body>
</html>

  • 阅读协议
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
	</head>
	<body>
		<input type="button" value="确认(5s)"  disabled="disabled"/>
		
		<script type="text/javascript">
			window.onload = function(){
				var n = 5;
				var inputNode = document.querySelector('input');
				var timer = null;
				timer = setInterval(function(){
					n--;
					if(n <= 0){
						clearInterval(timer);
						inputNode.value = '确认';
						inputNode.disabled = false;
					}else{
						inputNode.value = '确认('+ n +'s)';
					}
				},1000);
			}
		</script>
	</body>
</html>
  • 定时器有时候是不准的(同步和异步)
    • 单线程
      • JavaScript是一门单线程的语言,因此,JavaScript在同一个时间只能做一件事,单线程意味着,如果在同个时间有多个任务的话,这些任务就需要进行排队,前一个任务执行完,才会执行下一个任务
    • 为什么js设计是单线程
      • JavaScript的单线程,与它的用途是有很大关系,我们都知道,JavaScript作为浏览器的脚本语言,主要用来实现与用户的交互,利用JavaScript,我们可以实现对DOM的各种各样的操作,如果JavaScript是多线程的话,一个线程在一个DOM节点中增加内容,另一个线程要删除这个DOM节点,那么这个DOM节点究竟是要增加内容还是删除呢?这会带来很复杂的同步问题,因此,JavaScript是单线程的
    • 同步任务
      • 同步任务是指在主线程上排队执行的任务,只有前一个任务执行完毕,才能继续执行下一个任务,当我们打开网站时,网站的渲染过程,比如元素的渲染,其实就是一个同步任务
    • 异步任务
      • 异步任务是指不进入主线程,而进入任务队列的任务,只有任务队列通知主线程,某个异步任务可以执行了,该任务才会进入主线程,当我们打开网站时,像图片的加载,音乐的加载,其实就是一个异步任务
    • 定时器管理模块
    • 队列
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
	</head>
	<body>
		<script type="text/javascript">			
			var a = 100;		
			console.log('赛马');
			
			setTimeout(function(){
				console.log('老马');
			},4000)
			
			for(var i = 0; i < 50000; i++){
				for(var j = 0; j < 50000; j++){
					a++;
				}
			}
		</script>
	</body>
</html>

面试题:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
	</head>
	<body>
		<script type="text/javascript">
			var a = 100;
			console.log('赛马');
			
			setTimeout(function(){
				console.log('老马');
			},4000)
			
			setTimeout(function(){
				console.log('中马');
			},2000)
			
			for(var i = 0; i < 50000; i++){
				for(var j = 0; j < 50000; j++){
					a++;
				}
			}
		</script>
	</body>
</html>

4 js获取style中的样式

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<title></title>
		<style type="text/css">
			#box {
				position: absolute;
				left: 100px;
				top: 100px;
				width: 200px;
				height: 200px;
				background-color: red;
			}
		</style>
	</head>
	<body>
		<div id="box">
		</div>
		<script>
			var d = document.getElementById('box');
			console.log(d.style.width);
			console.log(d.style.backgroundColor);
		</script>
	</body>
</html>

4.1 Client系列 只读

  • **clientWidth **拿的是盒子 内容 + padding的宽
  • clientHeight拿的是盒子 内容 + padding的高
  • clientLeft 拿的是盒子左边框大小
  • clientTop 拿的是盒子上边框大小

4.2 Offset系列 只读

  • offsetWidth
    • 拿的是盒子 内容 + padding + border的宽
  • offsetHeight
    • 拿的是盒子 内容 + padding + border的高
  • offsetLeft
    • 拿的是元素的偏移量:可以认为就是拿的绝对定位left值
    • 切记如果进行offsetLeft的值进行加法运算不允许添加px
  • offsetTop
    • 拿的是元素的偏移量:可以认为就是拿的绝对定位top值

4.3 Scroll系列

  • scrollWidth 只读
    • 当内容比盒子小的时候,拿的是盒子的clientWidth
    • 当内容比盒子大的时候,拿的是内容的offsetWidth + 盒子的一侧内边距
    • document.documentElement.scrollWidth
  • scrollHeight 只读
    • 当内容比盒子小的时候,拿的是盒子的clientHeight
    • 当内容比盒子大的时候,拿的是内容的offsetHeight + 盒子的一侧内边距
    • document.documentElement.scrollHeight
  • scrollTop可读可写
    • 拿的是盒子内容向上滚动的距离
    • document.documentElement.scrollTop
  • scrollLeft可读可写
    • 拿的是盒子内容向左滚动的距离
    • document.documentElement.scrollLeft

4.4 总结

  1. 元素的大小:宽和高的获取:以后我们拿元素的宽和高,先看元素有没有边框,如果没有边框,那么

    clientWidth和offsetWidth是一样的,如果有边框,看你需要不,需要的话就用offsetWidth

    不需要就用clientWidth; scrollWidth几乎不用

  2. 元素的位置(偏移量)的获取:以后需要获取元素的位置直接通过offsetLeft和offsetTop去获取,但是注意相对的参照元素是谁;(和绝对定位参照类似)

  3. 视口宽高求法(固定的)

    1. document.documentElement.clientWidth
    2. document.documentElement.clientHeight

4.5 案例

  • 导航栏跟随
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			
			#box{
				width: 100%;
				height: 60px;
				background-color: red;
			}
			body{
				height: 4000px;
			}
		</style>
	</head>
	<body>
		<div id="box"></div>
		
		<script type="text/javascript">
			window.onload = function(){
				var box = document.getElementById('box');
				window.onscroll = function(){
					//系统滚动的事件
					//求视口的高度
					//求内容往上滚动的距离
					var H = document.documentElement.clientHeight;//求出视口的高度
				//系统的内容滚动,有些浏览器认为滚动的是html的内容,有些浏览器认为滚动的是body的内容
					//这里我们要兼容写法
					var scrollDis = document.documentElement.scrollTop || document.body.scrollTop;
					
					if(scrollDis >= H){
						//如果内容滚动的距离大于等于视口的高度,那么就跟随
						box.style.position = 'fixed';
						box.style.left = 0;
						box.style.top = 0;
					}else{
						//如果不大于就不跟随
						box.style.position = 'static';
						box.style.left = 0;
						box.style.top = 0;
					}		
				}
			}
		</script>
	</body>
</html>

  • 盒子来回移动
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			
			#box{
				position: absolute;
				left: 0;
				top: 0;
				width: 100px;
				height: 80px;
				background-color: red;
			}
		</style>
	</head>
	<body>
		<div id="box"></div>
		
		<script type="text/javascript">
			//求出盒子最新的位置,设置给盒子的left 就能让盒子动
			// 盒子的新位置  = 盒子的原始位置  + 盒子要移动的距离差
			
			var box = document.getElementById('box');
//			setTimeout(function(){
//				//第一步:拿到盒子原来的位置
//				var eleX = box.offsetLeft;
//				//第二步:求出现在准备要走的位置
//				var lastX = eleX + 50;
//				//第三步:把算出来的位置设置给box
//				box.style.left = lastX + 'px';
//				
//			},3000)

			var step = 3;
			setInterval(function(){
				//第一步:拿到盒子原来的位置
				var eleX = box.offsetLeft;
				//第二步:求出现在准备要走的位置
				var lastX = eleX + step;
				
				//在判定临界值,当达到左右临界的时候,往相反方向去走
				if(lastX > document.documentElement.clientWidth - box.offsetWidth){
					lastX = document.documentElement.clientWidth - box.offsetWidth;
					step = -3;
				}else if(lastX < 0){
					lastX = 0;
					step = 3;
				}
				
				
				//第三步:把算出来的位置设置给box
				box.style.left = lastX + 'px';
			},16)	
		</script>
	</body>
</html>

5. 初始包含块

页面的第一屏

  • 思考:子绝父不相的结果? body? html? 视口?
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			#box{
				position: absolute;
				left: 0;
				top: 0;
				width: 200px;
				height: 200px;
				background-color: blue;
			}
		</style>
	</head>
	<body>
		<div id="box"></div>
	</body>
</html>
  • 思考:html的某些特殊属性作用的位置
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			html{
				width: 500px;
				height: 500px;
				margin-left: 100px;
				border: 10px solid black;
				background-color: red;
				/*html比较特殊,特殊原因它的部分属性作用的不是自己 而是document*/
				/*doucument是网页最外层的元素,html文档当中没有任何标签表示它*/
			}
		</style>
	</head>
	<body>
		<div id="box"></div>
	</body>
</html>

  • 思考:body某些特殊属性作用的位置
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			
			html{
				width: 500px;
				height: 500px;
				margin-left: 100px;
				/* background-color: red; */
				/*html比较特殊,特殊原因它的部分属性作用的不是自己 而是document*/
				/*doucument是网页最外层的元素,html文档当中没有任何标签标示它*/
			}
			
			body{
				
				width: 300px;
				height: 3000px;
				border: 10px solid yellow;
				background-color: red;
				/*body比较特殊,单独的给Body设置某些属性,作用的不是自己 而是document*/
				/*doucument是网页最外层的元素,html文档当中没有任何标签表示它*/
			}
		</style>
	</head>
	<body>
		<div id="box"></div>
	</body>
</html>
  • html和body同时拥有backgroundColor的时候
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			html{
				width: 500px;
				height: 500px;
				margin-left: 100px;
				border: 10px solid black;
				background-color: red;
				/*html比较特殊,特殊原因它的部分属性作用的不是自己 而是document*/
				/*doucument是网页最外层的元素,html文档当中没有任何标签标示它*/
			}
			
			body{	
				width: 300px;
				height: 3000px;
				border: 10px solid yellow;
				background-color: blue;
				/*body比较特殊,单独的给Body设置某些属性,作用的不是自己 而是document
              	如果html和body都设置了,那么html作用在document上,body作用自己身上
                */
				/*doucument是网页最外层的元素,html文档当中没有任何标签标示它*/
			}
		</style>
	</head>
	<body>
		<div id="box"></div>
	</body>
</html>

  • 观察初始包含块
    • 初始包含块相对于浏览器第一屏大小一致的块状结构
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			
			html{
				width: 500px;
				height: 500px;
				margin-left: 100px;
				border: 10px solid black;
				background-color: red;
				/*html比较特殊,特殊原因它的部分属性作用的不是自己 而是document*/
				/*doucument是网页最外层的元素,html文档当中没有任何标签标示它*/
			}
			
			body{
				width: 300px;
				height: 3000px;
				border: 10px solid yellow;
				background-color: blue;
				/*body比较特殊,单独的给Body设置某些属性,作用的不是自己 而是document*/
				/*doucument是网页最外层的元素,html文档当中没有任何标签标示它*/
			}
					
			#box{
				position: absolute;
				left: 0;
				top: 0;
				width: 200px;
				height: 200px;
				background-color: red;
			}
			
			/*初始包含块:和浏览器第一屏大小一致的一个块状结构,称作初始包含块,元素子绝父不相的时候
			 其实相对的是初始包含块去做的定位,不是body也不是html也不是视口
			 * */
			
			/*
			 以后,打开浏览器最外层的结构,首先是document,接着是初始包含块 , HTML , body
			 
			 */
		</style>
	</head>
	<body>
		<div id="box"></div>
	</body>
</html>

6. 系统滚动条的控制

html和body这两个元素overflow的scroll属性,控制着系统的滚动条,系统的滚动条有两个,一个是body身上的,一个是document身上的。我们平时看到的那个滚动条是document身上的。如果我们想要控制系统滚动条哪个显示哪个关闭分以下情况:

  • 单独的给body或者html 设置overflow:scroll 滚动条打开的全部都是document的
  • 如果两个元素同时设置overflow属性,body设置的是scroll,html设置是hidden,那么document的滚动条被关闭,body身上的滚动条会打开,相反,body身上被关闭,document身上的被打开
  • 如果两个元素同时设置overflow:hidden;那么系统的两个滚动条全部被关闭
  • 如果两个都设置overflow:scroll,那么html会打开document身上的,而body会打开自己身上的滚动条
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			
			html{
				width: 500px;
				height: 500px;
				border: 10px solid black;
				overflow: scroll;
			}
			
			body{
				width: 300px;
				height: 300000px;
				border: 10px solid blue;
				overflow: scroll;
			}
			/* 企业级开发中常用写法
			 html,body{
			 		height:100%;    
					overflow:hidden; 			
			 }
			 */
		</style>
	</head>
	<body>
		<div id="box">
			<div id="box1"></div>
		</div>
	</body>
</html>

7. 鼠标拖拽基础

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			
			#box{
				position: absolute;
				left: 0;
				top: 0;
				width: 150px;
				height: 80px;
				background-color: red;
			}
		</style>
	</head>
	<body>
		<div id="box"></div>
		
		<script type="text/javascript">
			window.onload = function(){
				var box = document.getElementById('box');
				
				box.onmousedown = function(e){
					e = e || window.event;
					//按下的时候获取元素的初始位置和鼠标的初始位置
					var eleX = box.offsetLeft;
					var eleY = box.offsetTop;
					
					var startX = e.clientX;
					var startY = e.clientY;
					
					box.onmousemove = function(e){
						e = e || window.event;
						//可以获取鼠标的结束位置
						var endX = e.clientX;
						var endY = e.clientY;
						//求出鼠标的距离差
						var disX = endX - startX;
						var disY = endY - startY;
						//求出元素移动的最终位置  =  元素的初始位置  + 鼠标的距离差
						var lastX = eleX + disX;
						var lastY = eleY + disY;
						//把求出来的最终位置设置给元素
						box.style.left = lastX + 'px';
						box.style.top = lastY + 'px';
					};
					
					box.onmouseup = function(){
						box.onmousemove = box.onmouseup = null;
					}
					
				}
				
			}
		</script>
	</body>
</html>

基础拖拽问题:

  • 鼠标拖动过快,会跑出元素,元素就不动

​ 因为计算机跟不上你的速度,跑出盒子,盒子不动,因为事件添加在盒子身上,跑出去后事件就不在盒子身上触发了。包括在外部鼠标抬起,也是解绑不了盒子上的事件的,因为鼠标抬起也是在盒子身上添加的;解决:移动事件和抬起事件,最好添加给document

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			
			#box{
				position: absolute;
				left: 0;
				top: 0;
				width: 150px;
				height: 80px;
				background-color: red;
			}
		</style>
	</head>
	<body>
		<div id="box"></div>
		
		<script type="text/javascript">
			window.onload = function(){
				var box = document.getElementById('box');
				
				box.onmousedown = function(e){
					e = e || window.event;
					//按下的时候获取元素的初始位置和鼠标的初始位置
					var eleX = box.offsetLeft;
					var eleY = box.offsetTop;
					
					var startX = e.clientX;
					var startY = e.clientY;
					
					document.onmousemove = function(e){
						e = e || window.event;
						//可以获取鼠标的结束位置
						var endX = e.clientX;
						var endY = e.clientY;
						//求出鼠标的距离差
						var disX = endX - startX;
						var disY = endY - startY;
						//求出元素移动的最终位置  =  元素的初始位置  + 鼠标的距离差
						var lastX = eleX + disX;
						var lastY = eleY + disY;
						//把求出来的最终位置设置给元素
						box.style.left = lastX + 'px';
						box.style.top = lastY + 'px';
					};
					
					document.onmouseup = function(){
						box.onmousemove = box.onmouseup = null;
					}				
				}	
			}
		</script>
	</body>
</html>
  • 在盒子当中写上文字,拖拽先选中文字,在拖拽,文字跟着走,盒子不动,放手盒子会瞬间到放手的位置

    因为浏览器有默认行为,拖拽文字就是一个默认行为。解决:取消浏览器的默认行为

    取消浏览器默认行为根据事件添加方式不同而不同

    • dom0事件,那么在事件回调当中写上return false;
    • dom2事件, 在事件回调当中添加e.preventDefault();
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			
			#box{
				position: absolute;
				left: 0;
				top: 0;
				width: 150px;
				height: 80px;
				background-color: red;
			}
		</style>
	</head>
	<body>
		<div id="box">张三</div>
		
		<script type="text/javascript">
			window.onload = function(){
				var box = document.getElementById('box');
				
				box.onmousedown = function(e){
					e = e || window.event;
					//按下的时候获取元素的初始位置和鼠标的初始位置
					var eleX = box.offsetLeft;
					var eleY = box.offsetTop;
					
					var startX = e.clientX;
					var startY = e.clientY;
					
					document.onmousemove = function(e){
						e = e || window.event;
						//可以获取鼠标的结束位置
						var endX = e.clientX;
						var endY = e.clientY;
						//求出鼠标的距离差
						var disX = endX - startX;
						var disY = endY - startY;
						//求出元素移动的最终位置  =  元素的初始位置  + 鼠标的距离差
						var lastX = eleX + disX;
						var lastY = eleY + disY;
						//把求出来的最终位置设置给元素
						box.style.left = lastX + 'px';
						box.style.top = lastY + 'px';
					};				
					document.onmouseup = function(){
						box.onmousemove = box.onmouseup = null;
					}
					return false;
				}	
			}
		</script>
	</body>
</html>
  • 在低版本浏览器当中在盒子当中写上文字,拖拽先选中文字,在拖拽会出现禁止拖拽的现象

    因为低版本浏览器专门有这样的行为,禁止拖拽是低版本浏览器专属,解决:使用全局捕获,把鼠标后续的事件,强制拉回作用在元素身上,以后鼠标就只能作用在元素身上了,全局捕获有捕获就有释放,否则后果自负

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			
			#box{
				position: absolute;
				left: 0;
				top: 0;
				width: 150px;
				height: 80px;
				background-color: red;
			}
			
			
		</style>
	</head>
	<body>
		<div id="box">张三丰</div>
		
		<script type="text/javascript">
			window.onload = function(){
				var box = document.getElementById('box');
				box.onmousedown = function(e){
					e = e || window.event;
					//按下的时候获取元素的初始位置和鼠标的初始位置
					var eleX = box.offsetLeft;
					var eleY = box.offsetTop;
					var startX = e.clientX;
					var startY = e.clientY;
					//全局捕获
					box.setCapture&&box.setCapture();//只有低版本浏览器才会用到全局捕获
					document.onmousemove = function(e){
						e = e || window.event;
						//可以获取鼠标的结束位置
						var endX = e.clientX;
						var endY = e.clientY;
						//求出鼠标的距离差
						var disX = endX - startX;
						var disY = endY - startY;
						//求出元素移动的最终位置  =  元素的初始位置  + 鼠标的距离差
						var lastX = eleX + disX;
						var lastY = eleY + disY;
						//把求出来的最终位置设置给元素
						box.style.left = lastX + 'px';
						box.style.top = lastY + 'px';
					};
					document.onmouseup = function(){
						document.onmousemove = document.onmouseup = null;
						box.releaseCapture&&box.releaseCapture();//低版本浏览器释放全局捕获					
					}
					return false;
				}
			}
		</script>
	</body>
</html>

7.1. 鼠标拖拽添加临界值

window.onload = function(){
				var box = document.getElementById('box');
				box.onmousedown = function(e){
					e = e || window.event;
					//按下的时候获取元素的初始位置和鼠标的初始位置
					var eleX = box.offsetLeft;
					var eleY = box.offsetTop;
					var startX = e.clientX;
					var startY = e.clientY;
					//全局捕获
					box.setCapture&&box.setCapture();//只有低版本浏览器才会用到全局捕获
					document.onmousemove = function(e){
						e = e || window.event;
						//可以获取鼠标的结束位置
						var endX = e.clientX;
						var endY = e.clientY;
						//求出鼠标的距离差
						var disX = endX - startX;
						var disY = endY - startY;
						//求出元素移动的最终位置  =  元素的初始位置  + 鼠标的距离差
						var lastX = eleX + disX;
						var lastY = eleY + disY;
						
						
						//添加临界值
						if(lastX > document.documentElement.clientWidth - box.offsetWidth){
							lastX = document.documentElement.clientWidth - box.offsetWidth
						}else if(lastX < 0){
							lastX = 0;
						}
						
						if(lastY > document.documentElement.clientHeight - box.offsetHeight){
							lastY = document.documentElement.clientHeight - box.offsetHeight
						}else if(lastY < 0){
							lastY = 0;
						}
						
						//把求出来的最终位置设置给元素
						box.style.left = lastX + 'px';
						box.style.top = lastY + 'px';
					};
					document.onmouseup = function(){
						document.onmousemove = document.onmouseup = null;
						box.releaseCapture&&box.releaseCapture();//低版本浏览器释放全局捕获
						
					}
					return false;
				}
			}

7.2 鼠标拖拽吸附效果

window.onload = function(){
				var box = document.getElementById('box');
				box.onmousedown = function(e){
					e = e || window.event;
					//按下的时候获取元素的初始位置和鼠标的初始位置
					var eleX = box.offsetLeft;
					var eleY = box.offsetTop;
					var startX = e.clientX;
					var startY = e.clientY;
					//全局捕获
					box.setCapture&&box.setCapture();//只有低版本浏览器才会用到全局捕获
					document.onmousemove = function(e){
						e = e || window.event;
						//可以获取鼠标的结束位置
						var endX = e.clientX;
						var endY = e.clientY;
						//求出鼠标的距离差
						var disX = endX - startX;
						var disY = endY - startY;
						//求出元素移动的最终位置  =  元素的初始位置  + 鼠标的距离差
						var lastX = eleX + disX;
						var lastY = eleY + disY;
						
						
						//添加临界值
						if(lastX > document.documentElement.clientWidth - box.offsetWidth - 50){
							lastX = document.documentElement.clientWidth - box.offsetWidth
						}else if(lastX < 50){
							lastX = 0;
						}
						
						if(lastY > document.documentElement.clientHeight - box.offsetHeight - 50){
							lastY = document.documentElement.clientHeight - box.offsetHeight
						}else if(lastY < 50){
							lastY = 0;
						}
						
						//把求出来的最终位置设置给元素
						box.style.left = lastX + 'px';
						box.style.top = lastY + 'px';
					};
					document.onmouseup = function(){
						document.onmousemove = document.onmouseup = null;
						box.releaseCapture&&box.releaseCapture();//低版本浏览器释放全局捕获
						
					}
					return false;
				}
			}

7.3 添加碰撞效果

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			
			#box{
				position: absolute;
				left: 0;
				top: 0;
				width: 150px;
				height: 80px;
				background-color: red;
			}
			
			img{
				position: absolute;
				left: 0;
				top: 0;
				bottom: 0;
				right: 0;
				margin: auto;
				width: 200px;
				height: 100px;
			}
		</style>
	</head>
	<body>
		<div id="box">老马</div>
		<img src="img/1.jpg" alt="" />
		<script type="text/javascript">
			window.onload = function(){
				var box = document.getElementById('box');
				var imgNode = document.querySelector('img');
				box.onmousedown = function(e){
					e = e || window.event;
					//按下的时候获取元素的初始位置和鼠标的初始位置
					var eleX = box.offsetLeft;
					var eleY = box.offsetTop;
					var startX = e.clientX;
					var startY = e.clientY;
					//全局捕获
					box.setCapture&&box.setCapture();//只有低版本浏览器才会用到全局捕获
					document.onmousemove = function(e){
						e = e || window.event;
						//可以获取鼠标的结束位置
						var endX = e.clientX;
						var endY = e.clientY;
						//求出鼠标的距离差
						var disX = endX - startX;
						var disY = endY - startY;
						//求出元素移动的最终位置  =  元素的初始位置  + 鼠标的距离差
						var lastX = eleX + disX;
						var lastY = eleY + disY;
						
						
						//添加临界值
						if(lastX > document.documentElement.clientWidth - box.offsetWidth - 50){
							lastX = document.documentElement.clientWidth - box.offsetWidth
						}else if(lastX < 50){
							lastX = 0;
						}
						
						if(lastY > document.documentElement.clientHeight - box.offsetHeight - 50){
							lastY = document.documentElement.clientHeight - box.offsetHeight
						}else if(lastY < 50){
							lastY = 0;
						}
						
						//把求出来的最终位置设置给元素
						box.style.left = lastX + 'px';
						box.style.top = lastY + 'px';
						
						//设置元素位置之后,然后判断是否发生碰撞
						var boxL = lastX + box.offsetWidth;//求盒子在图片左侧的位置+自身宽度
						var imgL = imgNode.getBoundingClientRect().left;//专门求元素相对视口的位置
                      
						var boxT = lastY + box.offsetHeight;
						var imgT = imgNode.getBoundingClientRect().top;
                      
						var boxR = lastX;
						var imgR = imgNode.getBoundingClientRect().left + imgNode.offsetWidth;
                      
						var boxB = lastY;
						var imgB = imgNode.getBoundingClientRect().top + imgNode.offsetHeight;
						
						if(boxL < imgL || boxT < imgT || boxR > imgR  || boxB > imgB){
							//碰不到
							imgNode.src = 'img/1.jpg';
						}else{
							//碰到了
							imgNode.src = 'img/2.jpg';
						}
						
					};
					document.onmouseup = function(){
						document.onmousemove = document.onmouseup = null;
						box.releaseCapture&&box.releaseCapture();//低版本浏览器释放全局捕获
						
					}
					return false;
				}
			}
		</script>
	</body>
</html>

7.4 添加自定义滚动条

我们的页面架构首先要清楚

​ 页面的最外层是document,紧接着是初始包含块,html, body,其次是我们的元素,我们禁止了系统的滚动条,(因为各大浏览器的系统滚动条风格不一,有可能会影响我们的页面布局),所以在body当中我们一般会有最外的一个盒子模拟body区域,在这个盒子的右侧会定位一个盒子模拟滚动条

  • 原始页面
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			
			html,body{
				height: 100%;
				overflow: hidden;
			}
			
			#wrap{
				position: relative;
				width: 100%;
				height: 100%;
				overflow: hidden;
			}
			
			#wrap .scrollBar{
				position: absolute;
				right: 0;
				top: 0;
				width: 30px;
				height: 100%;
				background-color: hotpink;
				border-left: 1px solid greenyellow;
				border-right: 1px solid greenyellow;
			}
			
			#wrap .scrollBar .scrollIn{
				position: absolute;
				left: 50%;
				transform: translateX(-50%);
				top: 0;
				width: 26px;
				height: 100px;
				background-color: deepskyblue;
			}
		</style>
	</head>
	<body>
		<div id="wrap">
			<div class="scrollBar">
				<div class="scrollIn"></div>
			</div>
		</div>
		<script type="text/javascript">
		</script>
	</body>
</html>
  • js实现
	<script type="text/javascript">
			//让滚动条滑块先动起来
			window.onload = function(){
				var scrollIn = document.querySelector('#wrap .scrollBar .scrollIn');
				scrollIn.onmousedown = function(e){
					e = e || window.event;
					//按下的时候获取元素的初始位置和鼠标的初始位置
					var eleY = scrollIn.offsetTop;
					var startY = e.clientY;
					//全局捕获
					scrollIn.setCapture&&scrollIn.setCapture();//只有低版本浏览器才会用到全局捕获
					document.onmousemove = function(e){
						e = e || window.event;
						//可以获取鼠标的结束位置
						var endY = e.clientY;
						//求出鼠标的距离差
						var disY = endY - startY;
						//求出元素移动的最终位置  =  元素的初始位置  + 鼠标的距离差
						var lastY = eleY + disY;
						
						//添加临界值
						if(lastY > document.documentElement.clientHeight -scrollIn.offsetHeight){
							lastY = document.documentElement.clientHeight - scrollIn.offsetHeight
						}else if(lastY < 0){
							lastY = 0;
						}
						//把求出来的最终位置设置给元素
						scrollIn.style.top = lastY + 'px';
					};
					document.onmouseup = function(){
						document.onmousemove = document.onmouseup = null;
						scrollIn.releaseCapture&&scrollIn.releaseCapture();//低版本浏览器释放全局捕获
					}
					return false;
				}
			}
		</script>

7.5 滚动条带内容移动

  • 设置内容
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			
			html,body{
				height: 100%;
				overflow: hidden;
			}
			
			#wrap{
				position: relative;
				width: 100%;
				height: 100%;
				overflow: hidden;
			}
			
			#wrap .content{
				position: absolute;
				left: 0;
				top: 0;
			}
			
			
			#wrap .scrollBar{
				position: absolute;
				right: 0;
				top: 0;
				width: 30px;
				height: 100%;
				background-color: hotpink;
				border-left: 1px solid greenyellow;
				border-right: 1px solid greenyellow;
			}
			
			#wrap .scrollBar .scrollIn{
				position: absolute;
				left: 50%;
				transform: translateX(-50%);
				top: 0;
				width: 26px;
				height: 100px;
				background-color: deepskyblue;
			}
		</style>
	</head>
	<body>
		<div id="wrap">
			
			<div class="content"></div>
			
			
			<div class="scrollBar">
				<div class="scrollIn"></div>
			</div>
		</div>
		<script type="text/javascript">
			//让滚动条滑块先动起来
			window.onload = function(){
				var scrollIn = document.querySelector('#wrap .scrollBar .scrollIn');
				var content = document.querySelector('#wrap .content');
				
				//模拟内容,给网页上写点内容
				for(var i = 0; i < 200; i++){
					content.innerHTML += i + '<br>';
//					content.innerHTML = content.innerHTML +  i + '<br>'
				}
				
				scrollIn.onmousedown = function(e){
					e = e || window.event;
					//按下的时候获取元素的初始位置和鼠标的初始位置
					var eleY = scrollIn.offsetTop;
					var startY = e.clientY;
					//全局捕获
					scrollIn.setCapture&&scrollIn.setCapture();//只有低版本浏览器才会用到全局捕获
					document.onmousemove = function(e){
						e = e || window.event;
						//可以获取鼠标的结束位置
						var endY = e.clientY;
						//求出鼠标的距离差
						var disY = endY - startY;
						//求出元素移动的最终位置  =  元素的初始位置  + 鼠标的距离差
						var lastY = eleY + disY;
						
						//添加临界值
						if(lastY > document.documentElement.clientHeight - scrollIn.offsetHeight){
							lastY = document.documentElement.clientHeight - scrollIn.offsetHeight
						}else if(lastY < 0){
							lastY = 0;
						}
						//把求出来的最终位置设置给元素
						scrollIn.style.top = lastY + 'px';
					};
					document.onmouseup = function(){
						document.onmousemove = document.onmouseup = null;
						scrollIn.releaseCapture&&scrollIn.releaseCapture();//低版本浏览器释放全局捕获
					}
					return false;
				}
			}
		</script>
	</body>
</html>	
  • 滚动条长度设置(注意样式中原本定死的滚动条)
    • 自定义滚动条的万能比例:
      滑块的高度 / 滑槽的高度 = 滑槽的高度 / 内容的高度 = 滑块滚动距离 / 内容的滚动距离
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			
			html,body{
				height: 100%;
				overflow: hidden;
			}
			
			#wrap{
				position: relative;
				width: 100%;
				height: 100%;
				overflow: hidden;
			}
			
			#wrap .content{
				position: absolute;
				left: 0;
				top: 0;
			}
			
			
			#wrap .scrollBar{
				position: absolute;
				right: 0;
				top: 0;
				width: 30px;
				height: 100%;
				background-color: hotpink;
				border-left: 1px solid greenyellow;
				border-right: 1px solid greenyellow;
			}
			
			#wrap .scrollBar .scrollIn{
				position: absolute;
				left: 50%;
				transform: translateX(-50%);
				top: 0;
				width: 26px;
				/*height: 100px;*/
				background-color: deepskyblue;
			}
		</style>
	</head>
	<body>
		<div id="wrap">
			
			<div class="content"></div>
			
			
			<div class="scrollBar">
				<div class="scrollIn"></div>
			</div>
		</div>
		<script type="text/javascript">
			//让滚动条滑块先动起来
			window.onload = function(){
				var scrollIn = document.querySelector('#wrap .scrollBar .scrollIn');
				var content = document.querySelector('#wrap .content');
				
				
				//模拟内容,给网页上写点内容
				for(var i = 0; i < 100; i++){
					content.innerHTML += i + '<br>';
//					content.innerHTML = content.innerHTML +  i + '<br>'
				}
				
				//设置滑块的高度
//				自定义滚动条的万能比例:
//				滑块的高度 / 滑槽的高度 = 滑槽的高度 / 内容的高度 = 滑块滚动距离 / 内容的滚动距离 
				var scale = document.documentElement.clientHeight / content.offsetHeight;
				var scrollHeight = document.documentElement.clientHeight * scale;
				scrollIn.style.height = scrollHeight + 'px';
				
				scrollIn.onmousedown = function(e){
					e = e || window.event;
					//按下的时候获取元素的初始位置和鼠标的初始位置
					var eleY = scrollIn.offsetTop;
					var startY = e.clientY;
					//全局捕获
					scrollIn.setCapture&&scrollIn.setCapture();//只有低版本浏览器才会用到全局捕获
					document.onmousemove = function(e){
						e = e || window.event;
						//可以获取鼠标的结束位置
						var endY = e.clientY;
						//求出鼠标的距离差
						var disY = endY - startY;
						//求出元素移动的最终位置  =  元素的初始位置  + 鼠标的距离差
						var lastY = eleY + disY;
						
						//添加临界值
						if(lastY > document.documentElement.clientHeight - scrollIn.offsetHeight){
							lastY = document.documentElement.clientHeight - scrollIn.offsetHeight
						}else if(lastY < 0){
							lastY = 0;
						}
						//把求出来的最终位置设置给元素
						scrollIn.style.top = lastY + 'px';
					};
					document.onmouseup = function(){
						document.onmousemove = document.onmouseup = null;
						scrollIn.releaseCapture&&scrollIn.releaseCapture();//低版本浏览器释放全局捕获
					}
					return false;
				}
			}
		</script>
	</body>
</html>
  • 滚动条和内容联动(注意方向)
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			
			html,body{
				height: 100%;
				overflow: hidden;
			}
			
			#wrap{
				position: relative;
				width: 100%;
				height: 100%;
				overflow: hidden;
			}
			
			#wrap .content{
				position: absolute;
				left: 0;
				top: 0;
			}
			
			
			#wrap .scrollBar{
				position: absolute;
				right: 0;
				top: 0;
				width: 30px;
				height: 100%;
				background-color: hotpink;
				border-left: 1px solid greenyellow;
				border-right: 1px solid greenyellow;
			}
			
			#wrap .scrollBar .scrollIn{
				position: absolute;
				left: 50%;
				transform: translateX(-50%);
				top: 0;
				width: 26px;
				/*height: 100px;*/
				background-color: deepskyblue;
			}
		</style>
	</head>
	<body>
		<div id="wrap">
			
			<div class="content"></div>
			
			
			<div class="scrollBar">
				<div class="scrollIn"></div>
			</div>
		</div>
		<script type="text/javascript">
			//让滚动条滑块先动起来
			window.onload = function(){
				var scrollIn = document.querySelector('#wrap .scrollBar .scrollIn');
				var content = document.querySelector('#wrap .content');
				
				
				//模拟内容,给网页上写点内容
				for(var i = 0; i < 200; i++){
					content.innerHTML += i + '<br>';
//					content.innerHTML = content.innerHTML +  i + '<br>'
				}
				
				//设置滑块的高度
//				自定义滚动条的万能比例:
//				滑块的高度 / 滑槽的高度 = 滑槽的高度 / 内容的高度 = 滑块滚动距离 / 内容的滚动距离 
				var scale = document.documentElement.clientHeight / content.offsetHeight;
				var scrollHeight = document.documentElement.clientHeight * scale;
				scrollIn.style.height = scrollHeight + 'px';
				
				scrollIn.onmousedown = function(e){
					e = e || window.event;
					//按下的时候获取元素的初始位置和鼠标的初始位置
					var eleY = scrollIn.offsetTop;
					var startY = e.clientY;
					//全局捕获
					scrollIn.setCapture&&scrollIn.setCapture();//只有低版本浏览器才会用到全局捕获
					document.onmousemove = function(e){
						e = e || window.event;
						//可以获取鼠标的结束位置
						var endY = e.clientY;
						//求出鼠标的距离差
						var disY = endY - startY;
						//求出元素移动的最终位置  =  元素的初始位置  + 鼠标的距离差
						var lastY = eleY + disY;
						
						//添加临界值
						if(lastY > document.documentElement.clientHeight - scrollIn.offsetHeight){
							lastY = document.documentElement.clientHeight - scrollIn.offsetHeight
						}else if(lastY < 0){
							lastY = 0;
						}
						//把求出来的最终位置设置给元素
						scrollIn.style.top = lastY + 'px';
						//添加内容滚动逻辑
//						滑槽的高度 / 内容的高度 = 滑块滚动距离 / 内容的滚动距离 
						var contentDis = lastY / scale;
						content.style.top = -contentDis + 'px';
						
						
					};
					document.onmouseup = function(){
						document.onmousemove = document.onmouseup = null;
						scrollIn.releaseCapture&&scrollIn.releaseCapture();//低版本浏览器释放全局捕获
					}
					return false;
				}
			}
		</script>
	</body>
</html>

7.6 滚轮事件基础

区分上下

  • ie/chrome : mousewheel(dom2的标准模式)

​ event.wheelDelta

​ 上:120

​ 下:-120

​ 上和下指的是滚轮的方向

  • firefox: DOMMouseScroll(dom2的标准模式)

​ event.detail

​ 上:-3

​ 下:3

​ 上和下指的是滚轮的方向

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			#box{
				width: 300px;
				height: 300px;
				background-color: red;
			}
		</style>
	</head>
	<body>
		<div id="box"></div>
		
		
		<script type="text/javascript">
			window.onload = function(){
				var box = document.getElementById('box');
				//IE/CHROME
				box.addEventListener('mousewheel',scrollMove);
				//fireFox
				box.addEventListener('DOMMouseScroll',scrollMove);
				
				//与其讲滚轮事件不如说在讲怎么区分滚轮是往下还是往上
				//兼容性去处理回调函数
				var flag = true;
				function scrollMove(e){
					e = e || window.event;
					if(e.wheelDelta){
						//ie或者chrome
						if(e.wheelDelta > 0){
							//往上
							flag = true;
						}else{
							//往下
							flag = false;
						}
						
					}else if(e.detail){
						//火狐
						if(e.detail > 0){
							//往下
							flag = false;
						}else{
							//往上
							flag = true;
						}
					}
					if(flag){
						//不管什么浏览器,一定是往上滚的
						box.style.height = box.offsetHeight - 10 + 'px';
						
					}else{
						//不管什么浏览器,一定是往下滚的
						box.style.height = box.offsetHeight + 10 + 'px';
					}
				}
			}
		</script>
	</body>
</html>

7.7 自定义滚动条添加滚轮事件

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			
			html,body{
				height: 100%;
				overflow: hidden;
			}
			
			#wrap{
				position: relative;
				width: 100%;
				height: 100%;
				overflow: hidden;
			}
			
			#wrap .content{
				position: absolute;
				left: 0;
				top: 0;
			}
			
			
			#wrap .scrollBar{
				position: absolute;
				right: 0;
				top: 0;
				width: 30px;
				height: 100%;
				background-color: hotpink;
				border-left: 1px solid greenyellow;
				border-right: 1px solid greenyellow;
			}
			
			#wrap .scrollBar .scrollIn{
				position: absolute;
				left: 50%;
				transform: translateX(-50%);
				top: 0;
				width: 26px;
				/*height: 100px;*/
				background-color: deepskyblue;
			}
		</style>
	</head>
	<body>
		<div id="wrap">

			<div class="content"></div>


			<div class="scrollBar">
				<div class="scrollIn"></div>
			</div>
		</div>
		<script type="text/javascript">
			//让滚动条滑块先动起来
			window.onload = function() {
				var scrollIn = document.querySelector('#wrap .scrollBar .scrollIn');
				var content = document.querySelector('#wrap .content');


				//模拟内容,给网页上写点内容
				for (var i = 0; i < 200; i++) {
					content.innerHTML += i + '<br>';
			      //content.innerHTML = content.innerHTML +  i + '<br>'
				}

				//设置滑块的高度
				//				自定义滚动条的万能比例:
				//				滑块的高度 / 滑槽的高度 = 滑槽的高度 / 内容的高度 = 滑块滚动距离 / 内容的滚动距离 
				var scale = document.documentElement.clientHeight / content.offsetHeight;
				var scrollHeight = document.documentElement.clientHeight * scale;
				scrollIn.style.height = scrollHeight + 'px';


				//拖拽滑块相关的
				scrollIn.onmousedown = function(e) {
					e = e || window.event;
					//按下的时候获取元素的初始位置和鼠标的初始位置
					var eleY = scrollIn.offsetTop;
					var startY = e.clientY;
					//全局捕获
					scrollIn.setCapture && scrollIn.setCapture(); //只有低版本浏览器才会用到全局捕获
					document.onmousemove = function(e) {
						e = e || window.event;
						//可以获取鼠标的结束位置
						var endY = e.clientY;
						//求出鼠标的距离差
						var disY = endY - startY;
						//求出元素移动的最终位置  =  元素的初始位置  + 鼠标的距离差
						var lastY = eleY + disY;

						//添加临界值
						if (lastY > document.documentElement.clientHeight - scrollIn.offsetHeight) {
							lastY = document.documentElement.clientHeight - scrollIn.offsetHeight
						} else if (lastY < 0) {
							lastY = 0;
						}
						//把求出来的最终位置设置给元素
						scrollIn.style.top = lastY + 'px';
						//添加内容滚动逻辑
						//滑槽的高度 / 内容的高度 = 滑块滚动距离 / 内容的滚动距离 
						var contentDis = lastY / scale;
						content.style.top = -contentDis + 'px';


					};
					document.onmouseup = function() {
						document.onmousemove = document.onmouseup = null;
						scrollIn.releaseCapture && scrollIn.releaseCapture(); //低版本浏览器释放全局捕获
					}
					return false;
				}

				//滚动滚轮相关的
				//IE/CHROME
				document.addEventListener('mousewheel', scrollMove);
				//fireFox
				document.addEventListener('DOMMouseScroll', scrollMove);
				//与其讲滚轮事件不如说在讲怎么区分滚轮是往下还是往上
				//兼容性去处理回调函数
				var flag = true;

				function scrollMove(e) {
					e = e || window.event;
					if (e.wheelDelta) {
						//ie或者chrome
						if (e.wheelDelta > 0) {
							//往上
							flag = true;
						} else {
							//往下
							flag = false;
						}

					} else if (e.detail) {
						//火狐
						if (e.detail > 0) {
							//往下
							flag = false;
						} else {
							//往上
							flag = true;
						}
					}

					if (flag) {
						//不管什么浏览器,一定是往上滚的
						//往上滚   滑块往上跑   内容往下跑
						//滑槽的高度 / 内容的高度 = 滑块滚动距离 / 内容的滚动距离 
						var lastY = scrollIn.offsetTop - 10;
						if (lastY < 0) {
							lastY = 0;
						}
						scrollIn.style.top = lastY + 'px';
						var contentDis = -scrollIn.offsetTop / scale;
						content.style.top = contentDis + 'px';
					} else {
						//不管什么浏览器,一定是往下滚的
						//往下滚   滑块往吓跑    内容往上跑
						var lastY = scrollIn.offsetTop + 10;
						if (lastY > document.documentElement.clientHeight scrollIn.offsetHeight) {
							lastY = document.documentElement.clientHeight - scrollIn.offsetHeight
						}
						scrollIn.style.top = lastY + 'px';
						var contentDis = -scrollIn.offsetTop / scale;
						content.style.top = contentDis + 'px';
					}

				}

			}
		</script>
	</body>
</html>

8. 轮播图

8.1 轮播图逻辑点击按钮

原始页面:

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			ul,li{
				list-style: none;
			}
			
			img{
				display: block;
				/*vertical-align: middle;*/
			}
			
			a{
				text-decoration: none;
			}
			
			input{
				outline: none;
			}
			
			.clearFix:after{
				content: '';
				display: table;
				clear: both;
			}
			
			#box{
				position: relative;
				width: 600px;
				height: 300px;
				margin: 50px auto;
				overflow: hidden;
			}
			
			#box .list{
				width: 3000px;
				height: 300px;
			}
			
			#box .list li{
				float: left;
				width: 600px;
				height: 300px;
			}
			
			#box .list li img{
				width: 600px;
				height: 300px;
			}
			
			
			#box span{
				position: absolute;
				top: 50%;
				transform: translateY(-50%);
				width: 50px;
				height: 100px;
				background-color: rgba(200,200,200,.7);
				font-size: 50px;
				text-align: center;
				line-height: 100px;
				color: white;
				opacity: 0;
				transition: opacity 2s;
			}
			#box .left{
				left: 0;
			}
			#box .right{
				right: 0;
			}
			
			#box .iconList{
				position: absolute;
				left: 50%;
				transform: translateX(-50%);
				bottom: 10px;
				overflow: hidden;
			}
			
			#box .iconList li{
				float: left;
				width: 40px;
				height: 40px;
				margin-right: 10px;
				border-radius: 50%;
				background-color: gray;
			}
			
			#box .iconList li.current{
				background-color: red;
			}
			
			
		</style>
	</head>
	<body>
		<div id="box">
			
			<ul class="list">
				<li><img src="img/1.jpg"/></li>
				<li><img src="img/2.jpg"/></li>
				<li><img src="img/3.jpg"/></li>
				<li><img src="img/4.jpg"/></li>
				<li><img src="img/5.jpg"/></li>
			</ul>
			
			<span class="left">  <  </span>
			<span class="right">  >  </span>
			
			
			<ul class="iconList">
				<li class="current"></li>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
			</ul>
		</div>
		
		<script type="text/javascript">
			window.onload = function(){
				var box = document.getElementById('box');
				var spanNodes = document.querySelectorAll('#box span');
					
				//移入
				box.onmouseenter= function(){
					spanNodes[0].style.opacity = 1;
					spanNodes[1].style.opacity = 1;
				};
				//移出
				box.onmouseleave = function(){
					spanNodes[0].style.opacity = 0;
					spanNodes[1].style.opacity = 0;
				};
			}
		</script>
	</body>
</html>
  • 手动点击更换图片
     //点击右侧按钮图片动起来
	 spanNodes[1].onclick = function(){
	 //可以求出目前ul所在的位置
	 var startX = ulNode.offsetLeft;
	 //也可以知道移动的距离差 -600
	 var disX = -600;
	 //我们就可以求出点击一次移动的最终位置
	 var lastX = startX + disX;
	 //把求出的最终位置设置给ul,这样点击就已经能轮播了,但是是瞬变轮播
	 ulNode.style.left = lastX + 'px';
 }
  • 点击平滑切换
				var ulNode = document.querySelector('#box .list');
				var timeAll = 600;//点击一次移动一张图片的距离所需要的总时间
				var stepTime = 20;//每都一步所需要的的时间
				var timer = null;
				//点击右侧按钮图片动起来
				spanNodes[1].onclick = function(){
					//可以求出目前ul所在的位置
					var startX = ulNode.offsetLeft;
					//也可以知道移动的距离差 -600
					var disX = -600;
					//我们就可以求出点击一次移动的最终位置
					var lastX = startX + disX;
					//把求出的最终位置设置给ul,这样点击就已经能轮播了,但是是瞬变轮播
					//如果要变成滑动就不能这样做,我们得让这个-600慢慢一步一步走;
//					ulNode.style.left = lastX + 'px';
//					用循环定时器模拟过度效果
					//求出每一步走的距离
					var stepDis = disX / (timeAll / stepTime);
					timer = setInterval(function(){
						var left = ulNode.offsetLeft + stepDis;
						//当慢慢移动到最后和瞬间移动到最后距离一样的时候,我们就清除定时器
						if(left === lastX){
							clearInterval(timer);
						}
						ulNode.style.left = left + 'px';
					},stepTime);
					
				}
				
				//点击左侧按钮
				spanNodes[0].onclick = function(){
					//可以求出目前ul所在的位置
					var startX = ulNode.offsetLeft;
					//也可以知道移动的距离差 -600
					var disX = 600;
					//我们就可以求出点击一次移动的最终位置
					var lastX = startX + disX;
					//把求出的最终位置设置给ul,这样点击就已经能轮播了,但是是瞬变轮播
					//如果要变成滑动就不能这样做,我们得让这个-600慢慢一步一步走;
//					ulNode.style.left = lastX + 'px';
//					用循环定时器模拟过度效果
					//求出每一步走的距离
					var stepDis = disX / (timeAll / stepTime);
					timer = setInterval(function(){
						var left = ulNode.offsetLeft + stepDis;
						//当慢慢移动到最后和瞬间移动到最后距离一样的时候,我们就清除定时器
						if(left === lastX){
							clearInterval(timer);
						}
						ulNode.style.left = left + 'px';
					},stepTime);
					
				}
  • 封装优化
				var ulNode = document.querySelector('#box .list');
				var timeAll = 600;//点击一次移动一张图片的距离所需要的总时间
				var stepTime = 20;//每都一步所需要的的时间
				var timer = null;
				//点击右侧按钮图片动起来
				spanNodes[1].onclick = function(){
					move(true);
				}
				//点击左侧按钮
				spanNodes[0].onclick = function(){
					move(false);
				}
				
				function move(flag){
					if(flag){
						var disX = -600;
					}else{
						var disX = 600;
					}
					//可以求出目前ul所在的位置
					var startX = ulNode.offsetLeft;
					//我们就可以求出点击一次移动的最终位置
					var lastX = startX + disX;
					//把求出的最终位置设置给ul,这样点击就已经能轮播了,但是是瞬变轮播
					//如果要变成滑动就不能这样做,我们得让这个-600慢慢一步一步走;
					//ulNode.style.left = lastX + 'px';
					//用循环定时器模拟过度效果
					//求出每一步走的距离
					var stepDis = disX / (timeAll / stepTime);
					timer = setInterval(function(){
						var left = ulNode.offsetLeft + stepDis;
						//当慢慢移动到最后和瞬间移动到最后距离一样的时候,我们就清除定时器
						if(left === lastX){
							clearInterval(timer);
						}
						ulNode.style.left = left + 'px';
					},stepTime);
				}

8.2 无限循环点击轮播

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			ul,li{
				list-style: none;
			}
			
			img{
				display: block;
				/*vertical-align: middle;*/
			}
			
			a{
				text-decoration: none;
			}
			
			input{
				outline: none;
			}
			
			.clearFix:after{
				content: '';
				display: table;
				clear: both;
			}
			
			#box{
				position: relative;
				width: 600px;
				height: 300px;
				margin: 50px auto;
				overflow: hidden;
			}
			
			#box .list{
				position: absolute;
				left: -600px;
				top: 0;
				width: 4200px;
				height: 300px;
			}
			
			#box .list li{
				float: left;
				width: 600px;
				height: 300px;
			}
			
			#box .list li img{
				width: 600px;
				height: 300px;
			}
			
			
			#box span{
				position: absolute;
				top: 50%;
				transform: translateY(-50%);
				width: 50px;
				height: 100px;
				background-color: rgba(200,200,200,.7);
				font-size: 50px;
				text-align: center;
				line-height: 100px;
				color: white;
				opacity: 0;
				transition: opacity 2s;
			}
			#box .left{
				left: 0;
			}
			#box .right{
				right: 0;
			}
			
			#box .iconList{
				position: absolute;
				left: 50%;
				transform: translateX(-50%);
				bottom: 10px;
				overflow: hidden;
			}
			
			#box .iconList li{
				float: left;
				width: 40px;
				height: 40px;
				margin-right: 10px;
				border-radius: 50%;
				background-color: gray;
			}
			
			#box .iconList li.current{
				background-color: red;
			}
			
			
		</style>
	</head>
	<body>
		<div id="box">
			
			<ul class="list">
				<!--无缝效果需要改变结构  最前面加最后一个,最后面加最前面一个-->
				<li><img src="img/5.jpg"/></li>
				<li><img src="img/1.jpg"/></li>
				<li><img src="img/2.jpg"/></li>
				<li><img src="img/3.jpg"/></li>
				<li><img src="img/4.jpg"/></li>
				<li><img src="img/5.jpg"/></li>
				<li><img src="img/1.jpg"/></li>
			</ul>
			
			<span class="left">  <  </span>
			<span class="right">  >  </span>
			
			
			<ul class="iconList">
				<li class="current"></li>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
			</ul>
		</div>
		
		<script type="text/javascript">
			window.onload = function(){
				var box = document.getElementById('box');
				var spanNodes = document.querySelectorAll('#box span');
				var ulNode = document.querySelector('#box .list');
				
				
				var timeAll = 600;//点击一次移动一张图片的距离所需要的总时间
				var stepTime = 20;//每都一步所需要的的时间
				var timer = null;
				
				
				//移入
				box.onmouseenter= function(){
					spanNodes[0].style.opacity = 1;
					spanNodes[1].style.opacity = 1;
				};
				//移出
				box.onmouseleave = function(){
					spanNodes[0].style.opacity = 0;
					spanNodes[1].style.opacity = 0;
				};
				
				
				
				//点击右侧按钮图片动起来
				
				spanNodes[1].onclick = function(){
					move(true);
				}
				
				//点击左侧按钮
				spanNodes[0].onclick = function(){
					move(false);
				}
				
				
				function move(flag){
					if(flag){
						var disX = -600;
					}else{
						var disX = 600;
					}
					//可以求出目前ul所在的位置
					var startX = ulNode.offsetLeft;
					//我们就可以求出点击一次移动的最终位置
					var lastX = startX + disX;
					//把求出的最终位置设置给ul,这样点击就已经能轮播了,但是是瞬变轮播
					//如果要变成滑动就不能这样做,我们得让这个-600慢慢一步一步走;
//					ulNode.style.left = lastX + 'px';
//					用循环定时器模拟过度效果
					//求出每一步走的距离
					var stepDis = disX / (timeAll / stepTime);
					timer = setInterval(function(){
						var left = ulNode.offsetLeft + stepDis;
						//当慢慢移动到最后和瞬间移动到最后距离一样的时候,我们就清除定时器
						if(left === lastX){
							clearInterval(timer);
							//无缝的逻辑
							if(left === -3600){
								left = -600;
							}else if(left === 0){
								left = -3000;
							}
						}
						ulNode.style.left = left + 'px';
					},stepTime);
				}
				
			}
		</script>
	</body>
</html>

8.3 左右按钮联动小圆点变色

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			ul,li{
				list-style: none;
			}
			
			img{
				display: block;
				/*vertical-align: middle;*/
			}
			
			a{
				text-decoration: none;
			}
			
			input{
				outline: none;
			}
			
			.clearFix:after{
				content: '';
				display: table;
				clear: both;
			}
			
			#box{
				position: relative;
				width: 600px;
				height: 300px;
				margin: 50px auto;
				overflow: hidden;
			}
			
			#box .list{
				position: absolute;
				left: -600px;
				top: 0;
				width: 4200px;
				height: 300px;
			}
			
			#box .list li{
				float: left;
				width: 600px;
				height: 300px;
			}
			
			#box .list li img{
				width: 600px;
				height: 300px;
			}
			
			
			#box span{
				position: absolute;
				top: 50%;
				transform: translateY(-50%);
				width: 50px;
				height: 100px;
				background-color: rgba(200,200,200,.7);
				font-size: 50px;
				text-align: center;
				line-height: 100px;
				color: white;
				opacity: 0;
				transition: opacity 2s;
			}
			#box .left{
				left: 0;
			}
			#box .right{
				right: 0;
			}
			
			#box .iconList{
				position: absolute;
				left: 50%;
				transform: translateX(-50%);
				bottom: 10px;
				overflow: hidden;
			}
			
			#box .iconList li{
				float: left;
				width: 40px;
				height: 40px;
				margin-right: 10px;
				border-radius: 50%;
				background-color: gray;
			}
			
			#box .iconList li.current{
				background-color: red;
			}
			
			
		</style>
	</head>
	<body>
		<div id="box">
			
			<ul class="list">
				<!--无缝效果需要改变结构  最前面加最后一个,最后面加最前面一个-->
				<li><img src="img/9.jpg"/></li>
				<li><img src="img/17.jpg"/></li>
				<li><img src="img/2.jpg"/></li>
				<li><img src="img/3.jpg"/></li>
				<li><img src="img/7.jpg"/></li>
				<li><img src="img/9.jpg"/></li>
				<li><img src="img/17.jpg"/></li>
			</ul>
			
			<span class="left">  <  </span>
			<span class="right">  >  </span>
			
			
			<ul class="iconList">
				<li class="current"></li>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
			</ul>
		</div>
		
		<script type="text/javascript">
			window.onload = function(){
				var box = document.getElementById('box');
				var spanNodes = document.querySelectorAll('#box span');
				var ulNode = document.querySelector('#box .list');
				var iconItems = document.querySelectorAll('#box .iconList li');
				var timeAll = 600;//点击一次移动一张图片的距离所需要的总时间
				var stepTime = 20;//每都一步所需要的的时间
				var timer = null;
				
				
				//移入
				box.onmouseenter= function(){
					spanNodes[0].style.opacity = 1;
					spanNodes[1].style.opacity = 1;
				};
				//移出
				box.onmouseleave = function(){
					spanNodes[0].style.opacity = 0;
					spanNodes[1].style.opacity = 0;
				};
				
				
				
				//点击右侧按钮图片动起来
				
				spanNodes[1].onclick = function(){
					move(true);
				}
				
				//点击左侧按钮
				spanNodes[0].onclick = function(){
					move(false);
				}
				
				
				function move(flag){
					if(flag){
						var disX = -600;
					}else{
						var disX = 600;
					}
					//可以求出目前ul所在的位置
					var startX = ulNode.offsetLeft;
					//我们就可以求出点击一次移动的最终位置
					var lastX = startX + disX;
					//把求出的最终位置设置给ul,这样点击就已经能轮播了,但是是瞬变轮播
					//如果要变成滑动就不能这样做,我们得让这个-600慢慢一步一步走;
//					ulNode.style.left = lastX + 'px';
//					用循环定时器模拟过度效果
					//求出每一步走的距离
					var stepDis = disX / (timeAll / stepTime);
					timer = setInterval(function(){
						var left = ulNode.offsetLeft + stepDis;
						//当慢慢移动到最后和瞬间移动到最后距离一样的时候,我们就清除定时器
						if(left === lastX){
							clearInterval(timer);
							//无缝的逻辑
							if(left === -3600){
								left = -600;
							}else if(left === 0){
								left = -3000;
							}
						}
						ulNode.style.left = left + 'px';
					},stepTime);
					
					//小圆点变色
					//排它
					//先让所有的小圆点变灰
					for(var i = 0; i < iconItems.length; i++){
						iconItems[i].className = '';
					}
					
					//让对应的小圆点变红
					//要求对应的小圆点,其实就是要求出对应的小圆点的下标
					//想要求小圆点的下标,我们可以转而求要显示的图片的下标,
					//图片下标 - 1就是我们要的小圆点下标
					var index = lastX / -600 - 1;
					if(index > 4){
						index = 0;
					}else if(index < 0){
						index = 4;
					}
					
					iconItems[index].className = 'current';			
				}	
			}
		</script>
	</body>
</html>

8.4 点击小圆点切换变色

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			ul,li{
				list-style: none;
			}
			
			img{
				display: block;
				/*vertical-align: middle;*/
			}
			
			a{
				text-decoration: none;
			}
			
			input{
				outline: none;
			}
			
			.clearFix:after{
				content: '';
				display: table;
				clear: both;
			}
			
			#box{
				position: relative;
				width: 600px;
				height: 300px;
				margin: 50px auto;
				overflow: hidden;
			}
			
			#box .list{
				position: absolute;
				left: -600px;
				top: 0;
				width: 4200px;
				height: 300px;
			}
			
			#box .list li{
				float: left;
				width: 600px;
				height: 300px;
			}
			
			#box .list li img{
				width: 600px;
				height: 300px;
			}
			
			
			#box span{
				position: absolute;
				top: 50%;
				transform: translateY(-50%);
				width: 50px;
				height: 100px;
				background-color: rgba(200,200,200,.7);
				font-size: 50px;
				text-align: center;
				line-height: 100px;
				color: white;
				opacity: 0;
				transition: opacity 2s;
			}
			#box .left{
				left: 0;
			}
			#box .right{
				right: 0;
			}
			
			#box .iconList{
				position: absolute;
				left: 50%;
				transform: translateX(-50%);
				bottom: 10px;
				overflow: hidden;
			}
			
			#box .iconList li{
				float: left;
				width: 40px;
				height: 40px;
				margin-right: 10px;
				border-radius: 50%;
				background-color: gray;
			}
			
			#box .iconList li.current{
				background-color: red;
			}
			
			
		</style>
	</head>
	<body>
		<div id="box">
			
			<ul class="list">
				<!--无缝效果需要改变结构  最前面加最后一个,最后面加最前面一个-->
				<li><img src="img/9.jpg"/></li>
				<li><img src="img/17.jpg"/></li>
				<li><img src="img/2.jpg"/></li>
				<li><img src="img/3.jpg"/></li>
				<li><img src="img/7.jpg"/></li>
				<li><img src="img/9.jpg"/></li>
				<li><img src="img/17.jpg"/></li>
			</ul>
			
			<span class="left">  <  </span>
			<span class="right">  >  </span>
			
			
			<ul class="iconList">
				<li class="current"></li>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
			</ul>
		</div>
		
		<script type="text/javascript">
			window.onload = function(){
				var box = document.getElementById('box');
				var spanNodes = document.querySelectorAll('#box span');
				var ulNode = document.querySelector('#box .list');
				var iconItems = document.querySelectorAll('#box .iconList li');
				var timeAll = 600;//点击一次移动一张图片的距离所需要的总时间
				var stepTime = 20;//每都一步所需要的的时间
				var timer = null;
				
				
				//移入
				box.onmouseenter= function(){
					spanNodes[0].style.opacity = 1;
					spanNodes[1].style.opacity = 1;
				};
				//移出
				box.onmouseleave = function(){
					spanNodes[0].style.opacity = 0;
					spanNodes[1].style.opacity = 0;
				};
				
				
				
				//点击右侧按钮图片动起来
				
				spanNodes[1].onclick = function(){
					move(true);
				}
				
				//点击左侧按钮
				spanNodes[0].onclick = function(){
					move(false);
				}
				
				//点击小圆点移动
				for(var i = 0; i < iconItems.length; i++){
					iconItems[i].index = i;
					iconItems[i].onclick = function(){
						//点击小圆点后的逻辑
						//和小圆点变色求小圆点的下标  刚好相反
						//点击哪个小圆点,可以获取到点击的这个小圆点的下标
						//根据小圆点的下标可以求出要显示的图片的下标
						//就可以求出要显示的图片对应的最终位置
						//把最终位置传到move可以求出点击小圆点后的距离差
						//点击按钮和点击小圆点逻辑是一样的,只是距离差不同
						move((this.index + 1)* -600);
					}
				}

				function move(flag){
					if(typeof flag === "boolean"){
						//证明点击的是按钮
						if(flag){
							var disX = -600;
						}else{
							var disX = 600;
						}
					}else{
						//证明点击的是小圆点进来的flag不是布尔值
						var disX = flag - ulNode.offsetLeft;
					}
					
					//可以求出目前ul所在的位置
					var startX = ulNode.offsetLeft;
					//我们就可以求出点击一次移动的最终位置
					var lastX = startX + disX;
					//把求出的最终位置设置给ul,这样点击就已经能轮播了,但是是瞬变轮播
					//如果要变成滑动就不能这样做,我们得让这个-600慢慢一步一步走;
//					ulNode.style.left = lastX + 'px';
//					用循环定时器模拟过度效果
					//求出每一步走的距离
					var stepDis = disX / (timeAll / stepTime);
					timer = setInterval(function(){
						var left = ulNode.offsetLeft + stepDis;
						//当慢慢移动到最后和瞬间移动到最后距离一样的时候,我们就清除定时器
						if(left === lastX){
							clearInterval(timer);
							//无缝的逻辑
							if(left === -3600){
								left = -600;
							}else if(left === 0){
								left = -3000;
							}
						}
						ulNode.style.left = left + 'px';
					},stepTime);
					
					//小圆点变色
					//排它
					//先让所有的小圆点变灰
					for(var i = 0; i < iconItems.length; i++){
						iconItems[i].className = '';
					}
					
					//让对应的小圆点变红
					//要求对应的小圆点,其实就是要求出对应的小圆点的下标
					//想要求小圆点的下标,我们可以转而求要显示的图片的下标,
					//图片下标 - 1就是我们要的小圆点下标
					var index = lastX / -600 - 1;
					if(index > 4){
						index = 0;
					}else if(index < 0){
						index = 4;
					}
					
					iconItems[index].className = 'current';
				}
			}
		</script>
	</body>
</html>

8.5 定时器叠加问题

发生情况:连续点击 定时器执行的时间的间隔很短

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			ul,li{
				list-style: none;
			}
			
			img{
				display: block;
				/*vertical-align: middle;*/
			}
			
			a{
				text-decoration: none;
			}
			
			input{
				outline: none;
			}
			
			.clearFix:after{
				content: '';
				display: table;
				clear: both;
			}
			
			#box{
				position: relative;
				width: 600px;
				height: 300px;
				margin: 50px auto;
				overflow: hidden;
			}
			
			#box .list{
				position: absolute;
				left: -600px;
				top: 0;
				width: 4200px;
				height: 300px;
			}
			
			#box .list li{
				float: left;
				width: 600px;
				height: 300px;
			}
			
			#box .list li img{
				width: 600px;
				height: 300px;
			}
			
			
			#box span{
				position: absolute;
				top: 50%;
				transform: translateY(-50%);
				width: 50px;
				height: 100px;
				background-color: rgba(200,200,200,.7);
				font-size: 50px;
				text-align: center;
				line-height: 100px;
				color: white;
				opacity: 0;
				transition: opacity 2s;
			}
			#box .left{
				left: 0;
			}
			#box .right{
				right: 0;
			}
			
			#box .iconList{
				position: absolute;
				left: 50%;
				transform: translateX(-50%);
				bottom: 10px;
				overflow: hidden;
			}
			
			#box .iconList li{
				float: left;
				width: 40px;
				height: 40px;
				margin-right: 10px;
				border-radius: 50%;
				background-color: gray;
			}
			
			#box .iconList li.current{
				background-color: red;
			}
			
			
		</style>
	</head>
	<body>
		<div id="box">
			
			<ul class="list">
				<!--无缝效果需要改变结构  最前面加最后一个,最后面加最前面一个-->
				<li><img src="img/9.jpg"/></li>
				<li><img src="img/17.jpg"/></li>
				<li><img src="img/2.jpg"/></li>
				<li><img src="img/3.jpg"/></li>
				<li><img src="img/7.jpg"/></li>
				<li><img src="img/9.jpg"/></li>
				<li><img src="img/17.jpg"/></li>
			</ul>
			
			<span class="left">  <  </span>
			<span class="right">  >  </span>
			
			
			<ul class="iconList">
				<li class="current"></li>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
			</ul>
		</div>
		
		<script type="text/javascript">
			window.onload = function(){
				var box = document.getElementById('box');
				var spanNodes = document.querySelectorAll('#box span');
				var ulNode = document.querySelector('#box .list');
				var iconItems = document.querySelectorAll('#box .iconList li');
				var timeAll = 600;//点击一次移动一张图片的距离所需要的总时间
				var stepTime = 20;//每都一步所需要的的时间
				var timer = null;
				var isMove = false;
				
				//移入
				box.onmouseenter= function(){
					spanNodes[0].style.opacity = 1;
					spanNodes[1].style.opacity = 1;
				};
				//移出
				box.onmouseleave = function(){
					spanNodes[0].style.opacity = 0;
					spanNodes[1].style.opacity = 0;
				};
				//点击右侧按钮图片动起来
				
				spanNodes[1].onclick = function(){
					move(true);
				}
				//点击左侧按钮
				spanNodes[0].onclick = function(){
					move(false);
				}
				
				//点击小圆点移动
				for(var i = 0; i < iconItems.length; i++){
					iconItems[i].index = i;
					iconItems[i].onclick = function(){
						move((this.index + 1)* -600);
					}
				}
				
				function move(flag){
					//第二次开始的时候去判断开关状态;
					if(isMove){
						return;
					}
					//第一次点击的时候
					isMove = true;
					
					if(typeof flag === "boolean"){
						//证明点击的是按钮
						if(flag){
							var disX = -600;
						}else{
							var disX = 600;
						}
					}else{
						//证明点击的是小圆点进来的flag不是布尔值
						var disX = flag - ulNode.offsetLeft;
					}
					
					//可以求出目前ul所在的位置
					var startX = ulNode.offsetLeft;
					//我们就可以求出点击一次移动的最终位置
					var lastX = startX + disX;
					var stepDis = disX / (timeAll / stepTime);
					timer = setInterval(function(){
						var left = ulNode.offsetLeft + stepDis;
						//当慢慢移动到最后和瞬间移动到最后距离一样的时候,我们就清除定时器
						if(left === lastX){
							clearInterval(timer);
							//无缝的逻辑
							if(left === -3600){
								left = -600;
							}else if(left === 0){
								left = -3000;
							}
							//在特定的条件下,让isMove再次变为false,为了后期也能动,否则后期点击就不动了
							isMove = false;
							
						}
						ulNode.style.left = left + 'px';
					},stepTime);
					
					//小圆点变色
					//排它
					//先让所有的小圆点变灰
					for(var i = 0; i < iconItems.length; i++){
						iconItems[i].className = '';
					}
					
					var index = lastX / -600 - 1;
					if(index > 4){
						index = 0;
					}else if(index < 0){
						index = 4;
					}
					
					iconItems[index].className = 'current';
				}
			}
		</script>
	</body>
</html>

8.6 自动轮播

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style>
			*{
				margin: 0;
				padding: 0;
			}
			ul,li{
				list-style: none;
			}
			
			img{
				display: block;
				/*vertical-align: middle;*/
			}
			
			a{
				text-decoration: none;
			}
			
			input{
				outline: none;
			}
			
			.clearFix:after{
				content: '';
				display: table;
				clear: both;
			}
			
			#box{
				position: relative;
				width: 600px;
				height: 300px;
				margin: 50px auto;
				overflow: hidden;
			}
			
			#box .list{
				position: absolute;
				left: -600px;
				top: 0;
				width: 4200px;
				height: 300px;
			}
			
			#box .list li{
				float: left;
				width: 600px;
				height: 300px;
			}
			
			#box .list li img{
				width: 600px;
				height: 300px;
			}
			
			
			#box span{
				position: absolute;
				top: 50%;
				transform: translateY(-50%);
				width: 50px;
				height: 100px;
				background-color: rgba(200,200,200,.7);
				font-size: 50px;
				text-align: center;
				line-height: 100px;
				color: white;
				opacity: 0;
				transition: opacity 2s;
			}
			#box .left{
				left: 0;
			}
			#box .right{
				right: 0;
			}
			
			#box .iconList{
				position: absolute;
				left: 50%;
				transform: translateX(-50%);
				bottom: 10px;
				overflow: hidden;
			}
			
			#box .iconList li{
				float: left;
				width: 40px;
				height: 40px;
				margin-right: 10px;
				border-radius: 50%;
				background-color: gray;
			}
			
			#box .iconList li.current{
				background-color: red;
			}
			
			
		</style>
	</head>
	<body>
		<div id="box">
			
			<ul class="list">
				<!--无缝效果需要改变结构  最前面加最后一个,最后面加最前面一个-->
				<li><img src="img/9.jpg"/></li>
				<li><img src="img/17.jpg"/></li>
				<li><img src="img/2.jpg"/></li>
				<li><img src="img/3.jpg"/></li>
				<li><img src="img/7.jpg"/></li>
				<li><img src="img/9.jpg"/></li>
				<li><img src="img/17.jpg"/></li>
			</ul>
			
			<span class="left">  <  </span>
			<span class="right">  >  </span>
			
			
			<ul class="iconList">
				<li class="current"></li>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
			</ul>
		</div>
		
		<script type="text/javascript">
			window.onload = function(){
				var box = document.getElementById('box');
				var spanNodes = document.querySelectorAll('#box span');
				var ulNode = document.querySelector('#box .list');
				var iconItems = document.querySelectorAll('#box .iconList li');
				var timeAll = 600;//点击一次移动一张图片的距离所需要的总时间
				var stepTime = 20;//每都一步所需要的的时间
				var timer = null;
				var isMove = false;
				var autoTimer = null;
				
				//移入
				box.onmouseenter= function(){
					spanNodes[0].style.opacity = 1;
					spanNodes[1].style.opacity = 1;
					clearInterval(autoTimer);
				};
				//移出
				box.onmouseleave = function(){
					spanNodes[0].style.opacity = 0;
					spanNodes[1].style.opacity = 0;
					autoRun();
				};
				
				
				
				//点击右侧按钮图片动起来
				
				spanNodes[1].onclick = function(){
					move(true);
				}
				
				//点击左侧按钮
				spanNodes[0].onclick = function(){
					move(false);
				}
				
				//点击小圆点移动
				for(var i = 0; i < iconItems.length; i++){
					iconItems[i].index = i;
					iconItems[i].onclick = function(){
						//点击小圆点后的逻辑
						//和小圆点变色求小圆点的下标  刚好相反
						//点击哪个小圆点,可以获取到点击的这个小圆点的下标
						//根据小圆点的下标可以求出要显示的图片的下标
						//就可以求出要显示的图片对应的最终位置
						//把最终位置传到move可以求出点击小圆点后的距离差
						//点击按钮和点击小圆点逻辑是一样的,只是距离差不同
						move((this.index + 1)* -600);
					}
				}
				
				//自动轮播
				autoRun();
				function autoRun(){
					autoTimer = setInterval(function(){
						move(true);
					},2000);
				}
				function move(flag){
					
					//第二次开始的时候去判断开关状态;
					if(isMove){
						return;
					}
					
					//第一次点击的时候
					isMove = true;
					
					if(typeof flag === "boolean"){
						//证明点击的是按钮
						if(flag){
							var disX = -600;
						}else{
							var disX = 600;
						}
					}else{
						//证明点击的是小圆点进来的flag不是布尔值
						var disX = flag - ulNode.offsetLeft;
					}
					
					//可以求出目前ul所在的位置
					var startX = ulNode.offsetLeft;
					//我们就可以求出点击一次移动的最终位置
					var lastX = startX + disX;
					//把求出的最终位置设置给ul,这样点击就已经能轮播了,但是是瞬变轮播
					//如果要变成滑动就不能这样做,我们得让这个-600慢慢一步一步走;
//					ulNode.style.left = lastX + 'px';
//					用循环定时器模拟过度效果
					//求出每一步走的距离
					var stepDis = disX / (timeAll / stepTime);
					timer = setInterval(function(){
						var left = ulNode.offsetLeft + stepDis;
						//当慢慢移动到最后和瞬间移动到最后距离一样的时候,我们就清除定时器
						if(left === lastX){
							clearInterval(timer);
							//无缝的逻辑
							if(left === -3600){
								left = -600;
							}else if(left === 0){
								left = -3000;
							}
							isMove = false;
							
						}
						ulNode.style.left = left + 'px';
					},stepTime);
					
					//小圆点变色
					//排它
					//先让所有的小圆点变灰
					for(var i = 0; i < iconItems.length; i++){
						iconItems[i].className = '';
					}
					var index = lastX / -600 - 1;
					if(index > 4){
						index = 0;
					}else if(index < 0){
						index = 4;
					}
					
					iconItems[index].className = 'current';
				}
				
			}
		</script>
	</body>
</html>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Dom详细讲解 的相关文章

  • 普通 JSON 到 GraphSON 格式

    我有两个问题 我在哪里可以真正找到 GraphSON 文件的基本格式 保证 gremlin 控制台成功加载 我正在尝试将 JSON 大约有 10 20 个字段 转换为另一个可以由 gremlin 查询的文件 但我实际上找不到有关 graph
  • Node.js req.body 在表单数据内容类型中未定义

    在这里 我为这个表单数据传递 API 创建了一个小演示 现在我正在使用邮递员检查此 API 但我没有收到任何数据 Code const http require http const express require express cons
  • 逻辑 && 和 || JavaScript 中的运算符

    我想进一步澄清一些事情 考虑一下 var a 42 var b abc var c null a b 42 a b abc c b abc c b null 我知道对于 运算符 如果第一个操作数的测试为真 则 表达式的结果是第一个操作数 a
  • 即使 WebPack 构建工作正常,VS Code 显示未找到模块

    我的 VS Code 说它找不到导入 即使我的 WebPack 构建仍然有效 这是进口 import as tf from tensorflow tfjs 以及来自 VS Code 的消息 找不到模块 tensorflow tfjs 您的意
  • 将对象传递给jquery中的回调函数

    我最近正在开发小型聊天模块 该模块需要不断检查服务器是否有新消息 我正在向服务器发送 ajax 请求 服务器将保持连接 直到找到新消息 长轮询 Code var chatController function other variable
  • jqGrid如何将额外的类应用于标题列

    我想在特定列上应用一个额外的类 我知道通过在 colModel 中指定这一点对于行是可能的 但这些类仅应用于 结果行 中的列 而不应用于标题 我想要达到的是通过简单的类名隐藏较小视口的特定列 与 Twitter Bootstrap 一起使用
  • Firestore onSnapshot() 方法多次触发

    我有一个带有多个路由和 vuex 的 vue cli 4 应用程序 Firestore 数据库已成功连接 我的应用程序立即反映从 Firestore 控制台应用于数据库的修改 在离开包含与 Firestore 同步 的组件的路线然后返回后
  • $index 中的 AngularJS 数字

    举例来说 我有以下代码 伪 div index div 结果将是 1 2 3 4 5 6 我怎样才能改变上面的代码以便打印索引 001 002 003 004 005 006 以便索引打印为 3 位数字 您可以使用过滤器轻松完成此操作 首先
  • Google 将用于 Google 可视化的文件保存在哪里?我可以将其设置为我网站的本地文件吗?另外,有没有让仪表在 IE 中工作的代码示例?

    EDIT请在此处查看生成的 html 和 Javascript http jsfiddle net GregMcNulty K6Vrb 1 http jsfiddle net GregMcNulty K6Vrb 1 根据这个评论4 http
  • Gecko/Firefox 对 HTML5 通知的支持

    我想知道是否有任何内置支持HTML5 通知到目前为止 Gecko 浏览器有哪些功能 也许有一些隐藏的开发人员 我知道 WebKitwindow webkitNotifications效果很好 那么 有 Firefox 实现吗 Update
  • JS 中的 .Jar 文件

    有谁知道如何在 JS 中访问 jar 文件 我已经用 Java 创建了类并作为 jar 文件导入 我想从 JS 文件访问该类 大家好 我感谢你们所有人 我尝试在 Firefox XUL 中使用 JS 列出文件夹中的文件 但我做不到 然后我决
  • Mocha 测试对原生 ES6 模块的“esm”支持

    有一个很棒的帖子 使用 Mocha 和 esm 测试原生 ES 模块 https web archive org web 20220318155753 https alxgbsn co uk 2019 02 22 testing nativ
  • 传单地图显示为灰色

    我正在启动 leaflet js快速开始 http leafletjs com examples quick start html但我的地图显示为灰色 我缺少什么吗 脚本 js var leafletMap L map leafletMap
  • 如何判断CKEditor是否已加载?

    如何确定 CKEditor 是否已加载 我查看了API文档 但只能找到loaded事件 我想检查 CKEditor 是否已加载 因为如果我第二次加载它 我的文本区域就会消失 The loaded活动对我不起作用 instanceReady
  • Javascript onclick隐藏div

    我想使用 javascript 隐藏这个警告 div 我的 javascript 正确吗 我想在单击关闭图标时隐藏 关闭 div images close icon gif div strong Warning strong These a
  • 解析器阻塞与渲染阻塞

    我一直在阅读有关优化网络性能的 Google 开发人员文档 我对那里使用的术语有点困惑 CSS 和 JavaScript 文件都会阻止 DOM 构建 但是 CSS 被称为渲染阻塞 而 JavaScript 被称为解析器阻塞 解析器阻塞 和
  • 未捕获错误:找不到从“ui/app”loader.js 导入的模块“ember”:164

    我使用以下命令构建并提供我的 ember 应用程序 ember build ember serve 两者都按预期工作 然后我转到以下 localhost 4200 URL 查看应用程序 并在 javascript 控制台中看到以下错误 Un
  • 使用 puppeteer 部署 firebase 功能时说即使我启用了 --no-sandbox 也找不到 chrome

    我正在尝试将 firebase 函数部署到使用 puppeteer 的 firebase 项目 我让它在本地计算机上运行 但是当它尝试在 firebase 上运行时 我收到此错误 Exception from a finished func
  • RegisterClientScriptCode 在部分回发后不起作用

    以下代码行位于 SharePoint 网站的用户控件中 ScriptManager RegisterClientScriptBlock this this GetType jquery144 false ScriptManager Regi
  • 根据对象内的值将对象数组分成两部分

    我一直在尝试 并努力 弄清楚如何根据键值对拆分对象数组 长话短说 我有一个火车正在停靠的车站列表 需要将之前的停靠点和未来的停靠点分开 我正在使用的数据如下所示 station code SOC station name Southend

随机推荐

  • 大头小头 字节序

    http blog csdn net zjf82031913 article details 7245183 字节序的问题涉及硬件架构 目前主要是Motorola的PowerPC系列CPU和Intel的x86系列CPU PowerPC系列采
  • Kibana导入CVS数据

    导入CVS数据 下载数据源CVS文件2018 7 12月份地震数据 https www elastic co assets bltb0648a200c490f5e quakes data csv 导入Machine Learning gt
  • 压缩zip文件和解压zip文件(设置压缩密码)

    欢迎访问个人博客 德鲁大叔撸代码 说明 注意引入的依赖 否则一直报错 很不容易找到的错误 import net lingala zip4j core ZipFile import net lingala zip4j exception Zi
  • 搭建并部署Vue3+TypeScript+Vite+ElementPlus项目

    目录 前言 一 搭建Vue3项目 1 安装yarn命令 2 创建VUE项目 3 安装VUE依赖 4 启动VUE项目 5 访问VUE项目 6 打包VUE项目 带项目名 7 部署VUE项目 二 使用Visual Studio Code管理vue
  • CVPR2023 语义分割论文合集

    国际计算机视觉与模式识别会议 CVPR 是计算机科学领域中的顶级会议之一 也是图像处理 机器学习 人工智能等多个领域的交叉学科会议 每年的CVPR会议都会有大量的论文投稿和学术交流活动 其中涵盖了包括图像处理 计算机视觉 模式识别 机器学习
  • STM32 USBH CDC开发及应用

    USB 是英文 Universal Serial BUS 通用串行总线 的缩写 其是一个外部总线标准 用于规范USB主机与外部设备的连接和通讯 由于项目需要 需要开发基于STM32 USB主机 HOST 的CDC的开发 用于编队表演系统中底
  • 【软件测试7】web自动化测试——12306购票实战

    web自动化测试 12306购票实战 一 自动化购票流程 登录 进入购票 填写信息 选择车次 预定 选择购票人 二 自动化环境配置 软件环境 Python selenium Python安装 Python Pycharm安装 seleniu
  • ECS云服务器2核4g够用吗?

    够不够用要看具体的需求 一般来说这个算是入门或者是入门以上的配置吧 满足我们一般个人用户大部分的建站需求 够不够用需要结合建站需求来考虑的 一般来说这个配置的阿里云服务器基本可以满足我们大部分个人和小微企业的建站需求了 我们除非是大型网站建
  • [生产力]VSCode必备插件-C/C++开发

    文章目录 1 C C for Visual Studio Code 2 C Intellisense 3 Git Graph 4 compareit 5 TODO Highlight 6 Bookmarks 7 Markdown All i
  • LLVM系列第一章:编译LLVM源码

    系列文章目录 LLVM系列第一章 编译LLVM源码 LLVM系列第二章 模块Module LLVM系列第三章 函数Function LLVM系列第四章 逻辑代码块Block LLVM系列第五章 全局变量Global Variable LLV
  • [CSDN] 批量导出博客markdown文件

    需求 为了备份或者迁移博客 需要导出博客的md格式文件 除了 爬虫 自带导出功能 编辑模式 ctrl c ctrl v 之外还有一种十分方便的方法 一行命令导出法 方法 进入 404页面 https blog console api csd
  • 自旋锁与读写锁

    1 读写锁 读写锁与互斥量类似 但是读写锁允许更高的并行性 互斥量要么是锁住多个要么是未锁住状态 而且一次只有一个线程可以对其加锁 读写锁可以有三种状态 读模式写加锁状态 写模式写加锁状态 不加锁状态 一次只有一个线程可以占有写模式下的读写
  • 四家中国企业上榜、AI 开发工具崛起,CB Insights 2022 年度 AI 100 全球榜单发布!...

    整理 郑丽媛 出品 CSDN ID CSDNnews 近日 全球知名市场数据分析机构 CB Insights 最新公布了 2022 年度 AI 100 榜单 自 2017 年起 CB Insights 每年都会发布 AI 100 榜单 在全
  • yum安装mysql 8.0

    一 安装mysql 8 0 yum源 cd etc yum repos d curl https repo mysql com mysql80 community release el7 3 noarch rpm gt centos7 my
  • 黄淮学院CSDN高校俱乐部李神龙主席发来的新年礼物感恩帖

    下午刚收到俱乐部总部给我发的礼物 心里甜甜的 先展示一下 嘿嘿 表示下半学年一定要好好工作 要不就对不起天山经理 姚希姐 付菁姐还有仲伟哥给的评语了 新的一年祝天山经理升官发财 姚希付菁姐美貌如花 仲伟哥英明神武 CSDN高校俱乐部一家人亲
  • Spring Cloud之Eureka集群与安全认证

    文章目录 前言 一 Eureka集群 1 修改配置文件为application replica1 properties 2 新增配置文件application replica2 properties 3 分别使用两个配置文件启动同一eure
  • 基本数据类型与引用数据类型的区别

    一 数据类型 java中的数据类型分为两大类 基本数据类型与引用数据类型 1 基本数据类型 基本数据类型只有8种 可按照如下分类 整数类型 long int short byte 浮点类型 float double 字符类型 char 因为
  • 拳王公社:最新虚拟资源项目赚钱成交系统,1.2W字干货大揭秘!

    小白如何快速利用虚拟资源赚到钱 本文篇幅较长 要赚钱 请耐心读完 一 选择好项目的5大要素 现在是互联网时代 信息差就是利润差 网络小白 新手找副业难 没方向 找不到好项目成为了问题 小白找副业或兼职最担心的就是承担大量资金投入 承担不明确
  • A - Odd Palindrome (回文串)

    A Odd Palindromehttps vjudge csgrandeur cn problem Gym 101652N include
  • Dom详细讲解

    1 Dom的基本介绍 1 1 什么是DOM 文档对象模型 英文全称为Document Object Model 它提供了对文档的结构化的表述 并定义了一种方式可以使从程序中对该结构进行访问 从而改变文档的结构 样式和内容 D Documen