1. client
clientTop、clientLeft:
clientTop:盒子的上boder
clientLeft:盒子的左border
clientWidth与clientHeight
1、在有DTD情况下:
document.body.clientWidth、document.body.clientHeight:显示的是body的宽和高,document.documentElement.clientWidth、document.documentElement.clientHeight:显示的是body可视范围的宽和高,
2、在无DTD情况下:
document.body.clientWidth、document.body.clientHeight显示的是body可视范围的宽和高;
document.documentElement.clientWidth、document.documentElement.clientHeight显示的是body的高和body可视范围的宽(IE中显示的都是body可视范围的宽和高)
3、不管有没有DTD:
window.innerWidth、window.innerHeight:显示的都是浏览器可视范围的宽和高,包括浏览器的头部和滚动条部分(IE678无法识别window.innerWidth)
调用者的区别:
1、clientTop、clientLeft、clientWidth、clientHeight调用者是元素
2、clientX、clientY调用者是event对象
client、scroll、offset区别:
clientWidth = width + padding
clientHeight = height + padding
offsetWidth = width + padding + border
offsetHeight = height + padding + border
scrollWidth = 内容宽度(不包含border)
scrollHeight = 内容高度(不包含border)
注意事项:IE67,scrollHeight即使不超出盒子,它的值也是内容的高度
兼容写法:
<script>
document.title = client().width + " " + client().height;
//新事件:浏览器大小变化事件(浏览器哪怕大小变化1px也会触动这个事件)
window.onresize = function () {
document.title = client().width + " " + client().height;
}
//获取屏幕可视区域的宽高
function client() {
if (window.innerHeight !== undefined) {
return {
"width": window.innerWidth,
"height": window.innerHeight
}
} else if (document.compatMode === "CSS1Compat") {
return {
"width": document.documentElement.clientWidth,
"height": document.documentElement.clientHeight
}
} else {
return {
"width": document.body.clientWidth,
"height": document.body.clientHeight
}
}
}
</script>
注意事项:window.innerWidth、window.innerHeight:显示的都是浏览器可视范围的宽和高,包括浏览器的头部和滚动条部分
2. Window 尺寸
有三种方法能够确定浏览器窗口的尺寸(浏览器的视口,不包括工具栏和滚动条)。
对于I E、Chrome、Firefox、Opera 以及 Safari:
window.innerHeight - 浏览器窗口的内部高度
window.innerWidth - 浏览器窗口的内部宽度
对于 Internet Explorer 8、7、6、5:
document.documentElement.clientHeight
document.documentElement.clientWidth
或者
document.body.clientHeight
document.body.clientWidth
实用的 JavaScript 方案(涵盖所有浏览器):
兼容写法
var w=window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth;
var h=window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
新事件 浏览器大小变化事件(浏览器哪怕大小变化1px也会触动这个事件)
window.onresize = function () {
document.title = client().width + " "+ client().height;
}
<script>
//新事件:浏览器大小变化事件(浏览器哪怕大小变化1px也会触动这个事件)
window.onresize = function () {
document.title = client().width + " "+ client().height;
}
//获取屏幕可视区域的宽高
function client(){
if(window.innerHeight !== undefined){
return {
"width": window.innerWidth,
"height": window.innerHeight
}
}else if(document.compatMode === "CSS1Compat"){
return {
"width": document.documentElement.clientWidth,
"height": document.documentElement.clientHeight
}
}else{
return {
"width": document.body.clientWidth,
"height": document.body.clientHeight
}
}
}
</script>
3. 判断浏览器大小决定显示方式
秀一下:
源码:
<script>
//需求:浏览器每次更改大小,判断是否符合某一标准然后给背景上色。
// // >960红色,大于640小于960蓝色,小于640绿色。
//步骤:
//1.老三步
//2.判断。
//3.上色
//1.老三步
window.onresize = fn;
//页面加载的时候直接执行一次函数,确定浏览器可视区域的宽,给背景上色
fn();
//封装成函数,然后指定的时候去调用和绑定函数名
function fn() {
//2.判断。
//3.上色
if(client().width>960){
document.body.style.backgroundColor = "red";
}else if(client().width>640){
document.body.style.backgroundColor = "blue";
}else{
document.body.style.backgroundColor = "green";
}
}
//获取屏幕可视区域的宽高
function client(){
if(window.innerHeight !== undefined){
return {
"width": window.innerWidth,
"height": window.innerHeight
}
}else if(document.compatMode === "CSS1Compat"){
return {
"width": document.documentElement.clientWidth,
"height": document.documentElement.clientHeight
}
}else{
return {
"width": document.body.clientWidth,
"height": document.body.clientHeight
}
}
}
</script>
4.判断屏幕大小
document.title = window.screen.width + " "+ window.screen.height;
5. 冒泡初体验
首先我们要先知道什么是冒泡。
假设有两个盒子box1和box2,box1包含box2。它们两同时都有一个相同的事件就是onclick,当我们点击box2时,它的onclick事件会执行,但随后它的父元素box1的onclick也会被执行,这就是冒泡。
捕获正好和冒泡相反。
下面代码里面的false是允许冒泡,true是允许捕获。如果不写默认是false;
box1.addEventListener("click", function () {
alert("我是box1");
},false);
box2.addEventListener("click", function () {
alert("我是box2");
},false);
事件被激发的时候,会有三个传播阶段。
三个阶段是:捕获、冒泡和目标阶段
事件冒泡阶段:事件从事件目标(target)开始,往上冒泡直到页面的最上一级标签。
事件捕获阶段:事件从最上一级标签开始往下查找,直到捕获到事件目标(target)。
知识点:
- 冒泡顺序
IE 6.0:
div -> body -> html -> document
其他浏览器:
div -> body -> html -> document -> window
不是所有的事件都能冒泡。以下事件不冒泡:blur、focus、load、unload、onmouseenter
onmouseleave
阻止冒泡的方法
假如想在box2上面阻止冒泡。
w3c的方法是:(火狐、谷歌、IE11)
event.stopPropagation()
IE10以下则是使用:event.cancelBubble = true//现在已废弃
兼容代码如下:
var event = event || window.event;
if(event && event.stopPropagation){
event.stopPropagation();
}else{
event.cancelBubble = true;
}
6. 模态框取消
点击模态框外,让整个模态框消失。
效果展示:
源码:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
body,html {
height: 100%;
padding: 0;
margin: 0;
}
.mask {
width: 100%;
height: 100%;
position: fixed;
top: 0;
left: 0;
display: none;
background: rgba(0, 0, 0, 0.6);
}
.login {
width: 400px;
height: 300px;
cursor: pointer;
background-color: #fff;
margin: 200px auto;
}
</style>
</head>
<body>
<div class="mask">
<div class="login" id="login"></div>
</div>
<a href="#">注册</a>
<a href="#">登陆</a>
<script src="jquery1.0.0.1.js"></script>
<script>
//需求:点击登录按钮,显示模态框。点击出去login以外的所有盒子隐藏模态框。
//步骤:
//1.给登录绑定事件
//2.给document绑定事件,因为可以冒泡,只要判断,点击的不是login,那么隐藏模态框
//1.给登录绑定事件
var mask = document.getElementsByClassName("mask")[0];
var a = document.getElementsByTagName("a")[1];
a.onclick = function (event) {
//显示模态框
show(mask);
//阻止冒泡
event = event || window.event;
if(event && event.stopPropagation){
event.stopPropagation();
}else{
event.cancelBubble = true;
}
}
//2.给document绑定事件,因为可以冒泡,只要判断,点击的不是login,那么隐藏模态框
document.onclick = function (event) {
//获取点击按钮后传递过来的值。
event = event || window.event;
//兼容获取事件触动时,被传递过来的对象
// var aaa = event.target || event.srcElement;
var aaa = event.target?event.target:event.srcElement;
console.log(event.target);
//判断目标值的ID是否等于login,如果等于不隐藏盒子,否则隐藏盒子。
if(aaa.id !== "login"){
mask.style.display = "none";
}
// 也可以这样写
// if(event.target.id !== "login"){
// mask.style.display = "none";
// }
}
</script>
</body>
</html>
隐藏模态框小结
判断当前对象
IE678 event.srcElement(事件源)
火狐/谷歌等 event.target(事件源)
兼容写法获取元素ID:
var event = event || window.event;
var targetId = event.target ? event.target.id : event.srcElement.id;
7. 事件委托
普通的事件绑定,没有办法为JS新创建的元素绑定事件。所以我们要使用冒泡的特性,事件委托!
源代码:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
li {
height: 30px;
line-height: 30px;
margin: 3px 0;
background-color: red;
cursor: pointer;
}
</style>
</head>
<body>
<button>创建4个移民li</button>
<ul>
<li>我是土著li</li>
<a href="#">我是土著li</a>
<li>我是土著li</li>
<li>我是土著li</li>
<a href="#">我是土著li</a>
<li>我是土著li</li>
</ul>
<script>
var liArr = document.getElementsByTagName("li");
var ul = document.getElementsByTagName("ul")[0];
var btn = document.getElementsByTagName("button")[0];
// for(var i=0;i<liArr.length;i++){
// liArr[i].onclick = function () {
// alert("我是土著li");
// }
// }
btn.onclick = function () {
for(var i=1;i<=4;i++){
var newLi = document.createElement("li");
var newA = document.createElement("a");
newLi.innerHTML = "我是移民li";
newA.innerHTML = "我是移民a";
newA.href = "#";
ul.appendChild(newLi);
ul.appendChild(newA);
}
}
//普通的事件绑定,没有办法为新创建的元素绑定事件。所以我们要使用冒泡的特性,事件委托!
//事件委托
ul.onclick = function (event) {
//获取事件触动的时候传递过来的值
event = event || window.event;
var aaa = event.target?event.target:event.srcElement;
//判断标签名,如果是li标签弹窗
if(aaa.tagName === "LI"){//必须是大写,因为tagName的返回值是大写
alert("我是li");
}
}
</script>
</body>
</html>
事件委托小结
(先绑定,后创建的元素没有事件)
阻止冒泡,阻止自己像父系盒子冒泡。
所有的泡泡冒泡到阻止位置停止向上冒泡
event.target是在事件被触动的时候把事件源绑定到event的target属性中。而之前的target是我们自定义的一个变量触动
8.缓动动画的完善(加强)
之前封装的动画缺点:
- 1.只能放入一个属性。(一个方法只能操作一个属性)
- 2.只能获取行内式,不能获取内嵌和外链样式。导致我们获取left值的时候,用offsetLeft模拟。
- 3.一次性放入多个属性值。
- 先看一下获取元素属性值和赋值方法
给属性赋值:(既能获取又能赋值)
div.style.width 单个赋值
div.style[“width”] 变量赋值
获取属性值:(只能获取)
window.getComputedStyle(div,null).width;单个获取
window.getComputedStyle(div,null)[“width”];变量获取
div.currentStyle.width; IE678
div.currentStyle[“width”]; IE678
1.只能放入一个属性。(方法只能操作一种属性)的解决办法。
源码:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
div {
position: absolute; width: 100px; height: 100px;background-color: pink;
}
</style>
</head>
<body>
<button>运动到400</button>
<button>宽度变为400</button>
<div></div>
<script>
var btnArr = document.getElementsByTagName("button");
var div = document.getElementsByTagName("div")[0];
btnArr[0].onclick = function () {
animate(div,"left",400);
}
btnArr[1].onclick = function () {
animate(div,"width",400);
}
//参数变为3个
function animate(ele,attr,target){
//先清定时器
clearInterval(ele.timer);
ele.timer = setInterval(function () {
console.log(ele.timer)
//四部
var leader = parseInt(getStyle(ele,attr)) || 0;
//1.获取步长
var step = (target - leader)/10;
//2.二次加工步长
step = step>0?Math.ceil(step):Math.floor(step);
leader = leader + step;
//3.赋值
ele.style[attr] = leader + "px";
//4.清除定时器
if(Math.abs(target-leader)<=Math.abs(step)){
ele.style[attr] = target + "px";
clearInterval(ele.timer);
}
},25);
}
//兼容方法获取元素样式
function getStyle(ele,attr){
if(window.getComputedStyle){
return window.getComputedStyle(ele,null)[attr];
}
return ele.currentStyle[attr];
}
</script>
</body>
</html>
2.让多个属性同时使用+开闭原则清除定时器+回调函数
源码:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
div {
position: absolute;
top: 40px;
left: 10px;
width: 100px;
height: 100px;
background-color: pink;
}
</style>
</head>
<body>
<button>运动到400然后回来</button>
<div></div>
<script>
var btnArr = document.getElementsByTagName("button");
var div = document.getElementsByTagName("div")[0];
btnArr[0].onclick = function () {
var json1 = {"left":300,"top":200,"width":300,"height":200};
var json2 = {"left":10,"top":30,"width":100,"height":100};
animate(div,json1,function () {animate(div,json2);});
}
//参数变为3个
function animate(ele,json,fn){
//先清定时器
clearInterval(ele.timer);
ele.timer = setInterval(function () {
//开闭原则
var bool = true;
//遍历属性和值,分别单独处理json
//attr == k(键) target == json[k](值)
for(var k in json){
//四部
var leader = parseInt(getStyle(ele,k)) || 0;
//1.获取步长
var step = (json[k] - leader)/10;
//2.二次加工步长
step = step>0?Math.ceil(step):Math.floor(step);
leader = leader + step;
//3.赋值
ele.style[k] = leader + "px";
//4.清除定时器
//判断: 目标值和当前值的差大于步长,就不能跳出循环
//不考虑小数的情况:目标位置和当前位置不相等,就不能清除清除定时器。
if(json[k] !== leader){
bool = false;
}
}
console.log(1);
//只有所有的属性都到了指定位置,bool值才不会变成false;
if(bool){
clearInterval(ele.timer);
//所有程序执行完毕了,现在可以执行回调函数了
//只有传递了回调函数,才能执行
if(fn){
fn();
}
}
},25);
}
//兼容方法获取元素样式
function getStyle(ele,attr){
if(window.getComputedStyle){
return window.getComputedStyle(ele,null)[attr];
}
return ele.currentStyle[attr];
}
</script>
</body>
</html>
9.手风琴案例
效果是这样的:
图片width:800,高度随意。
源码:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
ul{list-style: none}
*{margin:0; padding:0;}
div{
width: 1200px;
height: 400px;
margin:50px auto;
border:1px solid red;
overflow: hidden;
}
div li {
width: 20%;
height: 400px;
float: left;
}
div ul {
width: 1300px;
}
</style>
<script src="../jquery1.0.0.1.js"></script>
<script>
window.onload = function () {
//需求:鼠标放入到li中该盒子变宽,其他的盒子变窄。移开大盒子,回复原样。
//步骤:
//1.给li添加背景
//2.绑定onmouseover事件,鼠标放入到li中该盒子变宽,其他的盒子变窄
//3.移开大盒子,回复原样
var div = document.getElementsByTagName("div")[0];
var liArr = div.getElementsByTagName("li");
//1.给li添加背景
for(var i=0;i<liArr.length;i++){
liArr[i].style.background = "url(images/"+(i+1)+".jpg) no-repeat";
//2.绑定onmouseover事件,鼠标放入到li中该盒子变宽,其他的盒子变窄
liArr[i].onmouseover = function () {
//排他思想
for(var j=0;j<liArr.length;j++){
//引用框架实现宽度变窄
animate(liArr[j],{"width":100});
}
//剩下他自己
animate(this,{"width":800})
}
}
//3.移开大盒子,回复原样
div.onmouseout = function () {
for(var j=0;j<liArr.length;j++){
//引用框架实现宽度变窄
animate(liArr[j],{"width":240});
}
}
}
</script>
</head>
<body>
<div>
<ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</div>
</body>
</html>
9.模拟360开机弹窗关闭
效果是这样的:
图片找个类似的就行,切成上下两部分。
源码:
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<style>
.box{
width: 322px;
position: fixed;
bottom:0;
right:0;
}
span{
position: absolute;
top:0;
right:0;
width:30px;
height: 20px;
cursor: pointer;
}
</style>
<script src="../jquery1.0.0.1.js"></script>
<script>
window.onload = function () {
//需求:下面的盒子高度变为0,然后大盒子的宽在变为0.
var guanbi = document.getElementById("guanbi");
var box = guanbi.parentNode;
var b = document.getElementById("b");
guanbi.onclick = function () {
//下面的盒子高度变为0,然后大盒子的宽在变为0.
animate(b,{"height":0}, function () {
animate(box,{"width":0});
});
}
}
</script>
</head>
<body>
<div class="box">
<span id="guanbi"></span>
<div class="hd" id="t">
<img src="images/t.jpg" alt=""/>
</div>
<div class="bd" id="b">
<img src="images/b.jpg" alt=""/>
</div>
</div>
</body>
</html>