文档对象模型,英文全称为Document Object Model,它提供了对文档的结构化的表述,并定义了一种方式可以使从程序中对该结构进行访问,从而改变文档的结构,样式和内容。
D:Document,文档,表示的整个Html的网页文档
O:Object, 对象,将网页的每一部分(标签)转换为每一个对象
M:Model,模型,使用模型来表示对象之间的关系,方便我们获取。
DOM 将文档解析为一个由节点和对象(包含属性和方法的对象)组成的结构集合。简言之,它会将web页面和脚本或程序语言连接起来,让脚本来操作页面,使用js代码将页面的样式,内容,结构修改。
通过一些js的方法来获取标签的对象(documet.getElementById()),然后调用属性和方法修改原来标签的样式和内容,结构。
文档树
或 DOM树
document | 文档 | html页面代码 所有的html结构 |
---|---|---|
object | 对象 | 将html中每一个标签 都变成一个对象 |
model | 模型 | 用另一种形式展示 |
window是浏览器窗口对象,所有东西都被当作是window的子对象
文档对象document 是window下的一个属性 代表整个DOM文档对象
根元素(root) html标签
文档树(dom树) 以HTML为根节点 形成的一棵倒立的树状结构,我们称作DOM树;这个树上所有的东西都叫节点,节点有很多类(节点共12类)
元素节点 标签
属性节点 属性
文本节点 内容
注释节点 注释
这些节点如果我们通过DOM方法去获取或者其它的操作去使用的话,就叫DOM对象
对象
**来处理前言:DOM(Document Object Model,文档对象模型)是针对HTML文档和XML(可扩展的标记语言)文档的一个API。DOM描绘了一个层次化的节点树,允许开发人员添加、移出和修改页面的某一部分,DOM脱胎于Netscape及微软公司创始的DHTML(动态HTML)。但现在它已经成为表现和操作页面标记的真正跨平台、语言中立的方式。
不可以同时添加同一类事件多次,如果添加后面覆盖前面
dom0事件解绑 本质上就是把事件回调函数和事件对象的事件属性断开指向
box.οnclick= null
前言: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>
练习:封装解绑事件
事件流:发生了事件之后的各个盒子的顺序
<!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('我是祖宗');
}
}
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事件可以根据第三个参数选择是捕获还是冒泡,一般我们都不写,默认是冒泡
<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>
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);
}
<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>
什么时候用?
用法?
好处?
总结
事件委派其实是借用事件冒泡去做的,因为事件冒泡导致内部所有的元素发生事件都会冒泡到祖先身上,我们不在子元素身上去添加事件监听和处理,而是在共同的祖先身上去添加,让祖先去处理子元素发生的事件;祖先去处理其实就是通过事件对象当中的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>
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>
window.onload window.onload是一个事件,在文档加载完成后能立即触发
window.onload = function () {
var div = document.getElementById("d");
div.style.color = "red";
};
事件源 | 事件的源头 是由谁触发的 btn |
---|---|
事件类型 | 发生了什么事情 onclick |
事件的回调函数 | 函数没有调用就执行了 我们称之为回调函数 function |
事件三要素
事件处理三大步
事件写好之后可以重复触发执行;
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";
};
<!-- 默认情况下是不选中 -->
<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 = “”)设置为空字符串 , 如果不设置(任意字符都可以)
修改文本的三个属性
element.textContent 获取或修改元素中的文本内容
innerText获取内容时,会考虑css样式
element.innerHTML 获取或修改元素中的html代码
可以直接向元素中添加html代码
innerHTML插入内容时,有被xss注入的风险
// 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);
<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 = "哈哈";
};
}
<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";
};
}
使用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;
};
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
})
在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()
})
什么是节点
文档树所有包含的东西都可以称作节点;最关注的节点是元素(就是我们平时所说的标签)节点(head body title hr td tr。。)
常用的节点分类
nodeType nodeName nodeValue
文本节点 3 #text 文本内容
元素节点 1 元素名大写 null
注释节点 8 #comment 注释内容
childNodes 拿到的是某个元素的子节点:包括子元素节点和文本子节点,如果有注释还有注释节点;
children 拿到的是某个元素的子元素节点
子节点:childNodes (儿子节点):
子元素节点: children(儿子元素):
<ul>
<li></li>
<li id='single'></li>
<li></li>
<ul>
let ul = document.querSelector('ul');
父子关系
获取ul内部的所有子节点
console.log(ul.childNodes);//拿到ul所有的子节点 (文本 元素 注释)
获取ul内部的所有子元素节点
console.log(u.children);//拿到ul所有的子元素节点,低级浏览器还包含注释
获取ul的第一个子节点
console.log(ul.firstChild);
获取ul的第一个子元素节点,但是只有高级浏览器认识
console.log(ul.firstElementChild);
获取ul的最后一个子节点
console.log(ul.lastChild);
获取ul的最后一个子元素节点,但是只有高级浏览器认识
console.log(ul.lastElementChild);
兄弟关系
let liNode = document.quersalary(‘#single’)
获取li的上一个兄弟节点
console.log(liNode.previousSibling);
获取li的上一个兄弟元素节点,但是只有高级浏览器认识
console.log(liNode.previousElementSibling);
获取li的下一个兄弟节点
console.log(liNode.nextSibling);
获取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));
* {
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';
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<p>我是一个段落</p>
<button>添加h1</button>
</body>
</html>
<script type="text/javascript">
window.onload = function(){
var btn = document.querySelector('button');
btn.onclick = function(){
//第一种动态添加节点,元素的方式,以后不用,因为会覆盖原本有的元素
document.write('<h1>我是标题</h1>');
}
}
</script>
说明:几个特殊元素的获取方式
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>'
//1、创建一个你想添加的元素 dom对象,但是创建好的这个对象并不在页面上
var h1Node = document.createElement('h1');
//2、把创建好的h1标签写内容
h1Node.innerHTML = '我是标题';
//3、经历完前两步,h1标签就已经准备好了,然后页面上想要看到,必须把h1添加给页面上已经存在的元素
document.body.appendChild(h1Node);//追加的意思就是末尾加
let arr = ["孙悟空", "猪八戒", "沙和尚", "白骨精", "唐僧", "玉兔公主"];
let str = "<ul>";
for (let i = 0; i < arr.length; i++) {
str += "<li>" + arr[i] + "</li>";
}
document.body.innerHTML = str;
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);
<!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>
//从末尾加 追加
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);
var ulNode = document.querySelector('ul');
var liNodeOld = document.querySelector('li:nth-child(4)');
var liNode = document.createElement('li');
liNode.innerHTML = '钢铁侠';
ulNode.replaceChild(liNode,liNodeOld);
//删除节点
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);
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)
}
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)
};
- 第一种 直接通过元素的 style 来修改
const btn = document.getElementById("btn")
const box1 = document.querySelector(".box1")
btn.onclick = function () {
box1.className += " one" // 注意类名前面的空格,因为一个元素类与类之间有一个空格 <div class="one two"></div>
}
- 第二种 通过 classList (推荐)
classList
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')); // 判断是否包含
})
触发回车之后,把表单的内容动态创建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);
}
}
};
onclick 鼠标事件
ondbclick 左键双击
oncontextmenu 右键单机
onmousemove 鼠标移动
onmouseenter 鼠标移入
onmouseleave 鼠标移出
onmouseover 鼠标移入
onmouseout 鼠标移出
onmousedown 按下
oncroll 滚轮
系统给我们封装的,任何事件都会有这个event对象,这个对象当中封装了和这个事件相关的一切信息
如果是高级浏览器去调用函数的回调函数,它会把事件对象封装好传给回调函数的第一个形参;
如果是低版本浏览器去调用,它会把事件对象封装好作为window的一个属性 window.event;所以我们在去拿事件对象的时候,要兼容性去拿
event = event || window.event;
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>
<!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
拿的是鼠标相对**页面(第一屏)**的水平距离和垂直距离 相对的是页面的左上角(以页面左上角为原点)
<!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>
单次定时器(延迟定时)
一般用来做延迟效果 定时炸弹
<!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>
<!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>
<!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>
元素的大小:宽和高的获取:以后我们拿元素的宽和高,先看元素有没有边框,如果没有边框,那么
clientWidth和offsetWidth是一样的,如果有边框,看你需要不,需要的话就用offsetWidth
不需要就用clientWidth; scrollWidth几乎不用
元素的位置(偏移量)的获取:以后需要获取元素的位置直接通过offsetLeft和offsetTop去获取,但是注意相对的参照元素是谁;(和绝对定位参照类似)
视口宽高求法(固定的)
<!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>
页面的第一屏
<!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>
<!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>
<!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>
<!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>
html和body这两个元素overflow的scroll属性,控制着系统的滚动条,系统的滚动条有两个,一个是body身上的,一个是document身上的。我们平时看到的那个滚动条是document身上的。如果我们想要控制系统滚动条哪个显示哪个关闭分以下情况:
<!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>
<!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>
在盒子当中写上文字,拖拽先选中文字,在拖拽,文字跟着走,盒子不动,放手盒子会瞬间到放手的位置
因为浏览器有默认行为,拖拽文字就是一个默认行为。解决:取消浏览器的默认行为
取消浏览器默认行为根据事件添加方式不同而不同
<!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>
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;
}
}
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;
}
}
<!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>
我们的页面架构首先要清楚
页面的最外层是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>
<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>
<!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>
区分上下
event.wheelDelta
上:120
下:-120
上和下指的是滚轮的方向
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>
<!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>
原始页面:
<!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);
}
<!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>
<!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>
<!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>
发生情况:连续点击 定时器执行的时间的间隔很短
<!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>
<!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>