1.client家族
◆box.clientWidth:表示盒子的宽度加padding
◆box.clientHeight:表示盒子的高度加padding
◆box.clientTop:表示盒子上边的border大小
◆box.clientLeft:表示盒子左边的border大小
◆
client家族
2.offset与scroll和client他们的width、height的区别
◆offsetWidth和offsetHeight代表着盒子的宽高(如果盒子定义的了宽高,就以定义的宽高为主,如果盒子没有定义宽高就以盒子内容为主)加上padding+border。
◆scrollWidth和scrollHeight代表着盒子的内容的宽高(如果内容的宽高小于盒子定义的宽高,那么就以盒子定义的宽高为主,如果盒子的内容宽高大于盒子定义一个宽高,那么久以盒子的内容的宽高为主)+padding。
◆clientWidth和clientHeight代表着盒子的宽高(就算内容超过盒子,它也只获取盒子定义的宽高,如果盒子没有定义宽高,那么就获取内容的宽高)+padding。
3.offset与scroll和client他们的top、left的区别
◆offsetTop和offsetLeft代表着距离最近的父系盒子带有定位的盒子之间的距离,也就是带有定位的盒子与盒子之间的上边的距离和左边的距离,如果父系盒子中没有定位的盒子,那么就取当前盒子距离浏览器(0,0)坐标点的距离。◆scrollTop和scrollLeft代表着被卷去的距离,除了document之外其它盒子也能用,但是盒子必须要有滚动条,但是自己模拟的滚动条不行,只能使用css样式overflow:scroll;弄出来的滚动条才行。
◆clientTop和clientLeft代表着clientWidth和clientHeight不包括的上border和左border,而且只能够获取到上边的border和左边的border。
4. 使用client对象检测浏览器的宽度和高度(可视区域),也就是当你放大缩小时宽度高度就会发生变化,因为可视区域也发生了变化,检测的方式与获取scollLeft和scrollTop类似
◆无论有没有DTD,在IE9及其以上的版本的浏览器和一些主流浏览器可以使用
window.innerWidth和window.innerHeight
来检测并获取当前浏览器可视区域的宽高,在IE9以下时,获取的值都是undefined。
◆当有DTD时,可以使用
document.documentElement.clientWidth和document.documentElement.clientHeight
来检测并获取当前任何版本浏览器可视区域的宽高,如果没有DTD时用这个只能够正常检测IE任何版本的浏览器的可视区域的宽高。
◆当没有DTD时,可以使用
document.body.clientWidth和document.body.clientHeight
在IE9以上的浏览器及各个主流浏览器检测当前浏览器的可视区域的宽高,但是有DTD时无法正常检测任何版本的浏览器的可视区域的宽高。
★所以兼容性写法和scrollTop与scrollLeft有点不一样
return {
width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
}
,不能够正常检测的是指高度,高度无法正常检测,宽度时而能够正常检测时而不能够正常检测,所以这种兼容性写法,可能在一些老的浏览器中还是会出现问题,但是这个已经是最好的兼容性写法了。◆使用client检测浏览器可视区域宽高:
使用client检测浏览器可视区域宽高
5.页面适配浏览器:根据浏览器可视宽度给页面上颜色
◆window.onresize事件是可视区域大小改变事件,只要浏览器可视区域发生1px的变化,都会触发window.onresize事件,就像window.onscroll事件一样,只要滚动条中的滑块儿移动1px,都会触发window.onscroll事件,注意:首次打开浏览器并不一定会触发window.onresize事件,只有当你改变浏览器窗体大小的时候才会触发。
◆根据浏览器可视宽度给页面上颜色:在css3没有退出媒体查询之前就是使用这种方式,来让网页来根据浏览器的可视区域动态适配css样式的。
根据浏览器可视宽度给页面上颜色
6.获取屏幕分辨率的高度和宽度可以window.screen.width和window.screen.height来获取
使用screen对象检测屏幕分辨率大小
7.事件冒泡
◆简单描述:事件冒泡:当一个元素上的事件被触发的时候,其所有父系容器如果定义了和这个元素被触发的事件时,那就会触发其所有父系容器的这个事件,比如鼠标点击了一个按钮,按钮设置了单击事件,按钮的父容器也设置了单击事件,那么你点击鼠标按钮时触发了单击事件,于此同时也会触发父容器的单击事件,元素开始不断的往上冒泡,一直冒泡到dom树的顶端
◆冒泡的原理:因为子容器在父容器中,你点击子容器的时候,其实也相当于点击了父容器的区域,所以就等于你先点击了子容器,然后你由点击了父容器的区域,于是乎当你给子容器和父容器都设置了单击事件时,先触发子容器的单击事件然后再触发父容器的单击事件,如果父容器的父容器也还设置了单击事件,那么就会一直往上触发单击事件。
◆事件传播阶段分三个:捕获阶段、冒泡阶段、目标阶段
◇事件捕获阶段:事件从最上一级标签开始往下查找,直到捕获到事件目标(target)为止。
◇事件冒泡阶段:事件从事件目标(target)开始往上冒泡直到页面的最上一级标签。
☆使用捕获的方式执行事件可是使用对象.addListenerEvent("事件",fn,true);来实现,使用冒泡的方式执行事件可以使用对象.on事件=fn;来实现。
◇事件目标阶段:其实很像是在捕获阶段是从外往内的,将每一个事件push进一个数组中,冒泡阶段是从数组中pop出来,事件目标阶段,将pop出的事件的方法执行,整个过程很像是一个进栈出栈然后执行。
◆冒泡顺序:
◇IE6.0:div->body->html->document
◇其它浏览器:div->body->html->document->window
☆这些事件不会冒泡也不能冒泡:blur、focus、load、unload、onmouseenter、onmouseleave
◆判断一个事件默认冒不冒泡,使用event.bubbles,如果返回值为true则这个事件冒泡,反之这个事件不冒泡。在冒泡中找到最开始的第一个触发这个事件的对象,使用event.target,谁是第一个泡泡,target就指向谁,但是在IE678中使用了srcElement,所以就需要兼容性的写法,有两种,一种直接用 || 一种是用三元运算符
var obj=event.target||event.srcElement;//返回true就是冒泡
var obj=event.target?event.target:event.srcElement;//返回true就是冒泡
★
事件冒泡的相关信息
8.取消事件冒泡
◆取消事件冒泡的方式,在IE678里面使用 event.cancelBubble=ture;表示取消冒泡,但是在IE9及其以上的主流浏览器使用的是event.stopPropagation();表示停止传播,也就是停止向外冒泡,阻止冒泡的兼容性写法
obj.onmouseover=function(event){
//获取兼容性的事件对象
event=event||window.event;
if(event&&event.stopPropagation){
event.stopPropagation();//停止冒泡
}else{
event.cancelBubble=true;//取消冒泡
}
}
◆
取消事件冒泡
9.事件冒泡灵活运用之事件委托
◆利用事件冒泡和event.target可以减少很多不必要的事件的定义,通过判断事件源的第一个对象,就知道是谁最开始触发了这个事件,那么就可以在最大的那个父容器的事件里面做最直接的事情了,页面元素的事件其实一直都存在,只不过是内部的事件驱动程序没有写罢了,所以就算你没有给页面元素手动设置事件,也能够通过event.target来找到触发事件的第一个事件源对象,
使用事件冒泡和事件源来显示隐藏模态框:模态框效果,这个很常用
利用事件冒泡和事件源来显示隐藏模态框
登陆
注册
◆js中的【事件委托】是通过事件冒泡来实现的,通过设置父容器的事件,当调用自己的事件时,在父容器那里去执行,从而,当子容器过多时减少了事件过多的定义,只需要定义一个父容器的事件即可,但是在父容器的事件中需要过滤,因为并不是所有的子元素都需要定义事件,所以可能需要在父容器中设置判断,判断当前触发的第一个事件源对象是否符合要求,如果符合的话就执行。
通过事件冒泡来进行事件委托
- 我是土著li
- 我是土著li
- 我是土著li
- 我是土著li
- 我是土著li
10.获取行内式、内嵌式、外链式的CSS样式的各种方式
◆获取对象的属性值的两种方式,第一种是对象.属性名,第二种是对象["属性名"],第二种非常的灵活,第一种比较准确。
◆获取行内式:对象.style.属性名和对象.style["属性名"],这种方式只能取行内的样式,这个style也是一个对象,它是页面标签中的style属性里的字符串转换成了json对象,如果你想获取页面标签中style属性的字符串,可以使用style.cssText来获取纯字符串。
◆获取内嵌式和外链式:对象.currentStyle.属性名和对象.currentStyle["属性名"]只能够在IE浏览器中使用,window.getComputedStyle(对象,伪元素对象).属性名和window.getComputedStyle(对象,伪元素对象)["属性名"]可以在IE9及以上的等一些主流浏览器中使用,如果没有伪元素对象可以给这个方法的参数赋值null,获取行内式的方式只能够获取行内式,但是获取内嵌式与外链式的方式其实还可以获取行内式的样式。
◆获取内嵌式与外链式的兼容性写法
if(window.getComputedStyle){
return window.getComputedStyle(element,null)["background-color"];
}else {
return element.currentStyle["background-color"];
}
◆获取外链式和内嵌式的css样式:
获取外链式和内嵌式的css样式
◆无论是行内式的样式还是内嵌式外链式的样式,使用[]方括号的方式获取样式时,既可以使用驼峰命名法也可以使用-命名法,如box.style.backgroundColor即可以写成box.style["backgroundColor"]也可以写成box.style["background-color"]这样,都行,但是如果使用对象.的方式只能够使用驼峰命名法。
◆通过元素和属性名获取样式的属性值:内嵌式、外链式的CSS样式的兼容性写法
/**
* 功能:获取该元素样式属性的属性值
* @param element
* @param attribute
* @returns {*}
*/
function getStyle(element, attribute) {
return element.currentStyle
?
element.currentStyle[attribute]
:
window.getComputedStyle(element, null)[attribute];
}
但是,当页面使用ctrl+鼠标滚轮进行发大缩小时,会造成获取getStyle(element, key)获取的值有小数的。
11.匀速动画计算步长与缓速动画计算步长
◆匀速动画计算步长
element.speed =element.target > element.leader ? 10 : -10;
◆缓速动画计算步长
//获取步长
element.speed = (element.target- element.leader) / 10 || 0; //二次计算步长
element.speed = element.speed > 0 ?Math.ceil(element.speed) : Math.floor(element.speed);
12.封装缓速动画框架
◆简单版
封装的兼容性样式对象制作缓速动画框架(简单版)
◆中级版
封装的兼容性样式对象制作缓速动画框架(中级版)
◆高级版
封装的兼容性样式对象制作缓速动画框架(高级版)
13.使用封装的缓速框架来DIY动画效果:手风琴效果+360开机动画
◆使用dom简单封装的jquery:
/* 功能:显示元素
* @param element
*/
function show(element) {
element.style.display = "block";
}
/**
* 功能:隐藏元素
* @param element
*/
function hide(element) {
element.style.display = "none";
}
/**
* 功能:最强的缓速移动方法
* 参数:传递元素对象、传递样式参数对象、传递回掉函数
* @param element
* @param json
* @param fn
*/
function animate(element, json, fn) {
//使用定时器之前先清除定时器
clearInterval(element.timer);
//使用定时器
element.timer = setInterval(function () {
//开闭思想
var bool = true;
//遍历json对象 完成每一个属性的缓速动画效果
for (var key in json) {
//key作为属性名 json[key]作为目标属性值
//bug:当页面使用ctrl+鼠标滚轮进行发大缩小时,
// 会造成获取getStyle(element, key)获取的值有小数,
//或者你传递进来的数值带有小数,那么就可能会造成死循环
//因为parseInt是向下取整的,所以不能那样子,只能够向上取整
//var str = getStyle(element, key)
//var index = str.indexOf("px");
//str = str.slice(0, index);
//element.str= getStyle(element, key).slice(0,getStyle(element, key).indexOf("px"))
// 获取当前的位置
element.leader = Math.ceil(getStyle(element, key).replace("px", "")) || 0;
//获取步长
element.speed = (json[key] - element.leader) / 10 || 0;
//二次计算步长
element.speed = element.speed > 0 ?
Math.ceil(element.speed) : Math.floor(element.speed);
////匀速的步长计算
//element.speed = json[key] > element.leader ? 10 : -10;
//只要有一个位置不是指距离一步之遥 这么做事考虑到了小数的情况
if (Math.abs(json[key] - element.leader) <= Math.abs(element.speed)) {
element.style[key] = json[key] + 'px';
continue;
} else {
bool = false;
}
//进行移动
element.style[key] = (element.leader + element.speed) + "px";
}
console.log(1)
if (bool) {
// //直接到达指定目标位置
clearInterval(element.timer);
// //执行完毕后 执行回掉函数
if (fn) {
fn();
}
}
}, 18);
}
/**
* 功能:垂直方向上缓度滚动到某个位置
* 参数说明:element元素对象 target指定位置
* @param element
* @param target
*/
function scrollAnimateY(element, target) {
//使用定时器之前先清除定时器
clearInterval(element.timer);
//设置定时器
element.timer = setInterval(function () {
//计算步长
element.speed = (target - element.leader) / 10;
//二次计算步长 防止 水永远取不尽 定时器永远不停
element.spend = element.spend > 0 ? Math.ceil(element.spend) : Math.floor(element.spend);
//距离是否只剩一步之遥
if (Math.abs(target - element.leader) <= Math.abs(element.speed)) {
window.scrollTo(0, target);
console.log(element.leader);
clearInterval(element.timer);
return;
}
//设置移动的动画
window.scrollTo(0, element.leader + element.speed);
}, 30);
}
/**
* 功能:水平方向的元素缓速移动的动画
* @param element
* @param target
*/
function animateX(element, target) {
//绑定计时器之前先清除定时器
clearInterval(element.timer);
element.timer = setInterval(function () {
//注意:this.offsetLeft最终获取的是number类型的值,并且它还会对小数进行四舍五入,
//如果this.style.left中有小数,并且还低于0.5,那么就会导致offsetLeft每次获取到的值,
//都是一样,然后就会造成 盒子不懂,定时器不停的现象发生,所以缓速动画时要记得给步长取整
// 如果步长>0就向上取整,避免步长小于0.5时出现bug,
// 如果步长<0,就向下取整,避免步长下雨-0.5时出现bug。
//每次移动的步长
element.spend = (target - element.offsetLeft) / 10
//对步长进行取整,避免offsetLeft底层的四舍五入的影响
element.spend = element.spend > 0 ? Math.ceil(element.spend) : Math.floor(element.spend);
//目标位置减去当前位置的绝对值 如果小于步长的绝对值 那么就说明也就一步之遥了,
// 那么直接移动到指定的位置清除计时器算了。
if (Math.abs(target - element.offsetLeft) <= Math.abs(element.spend)) {
element.style.left = target + "px";
clearInterval(element.timer);
return;
}
//重新设置距离左边的位置
element.style.left = element.offsetLeft + element.spend + "px";
console.log(element.style.left)
}, 30);
}
/**
* 功能:垂直方向的元素缓速移动的动画
* @param element
* @param target
*/
function animateY(element, target) {
//绑定计时器之前先清除定时器
clearInterval(element.timer);
element.timer = setInterval(function () {
//注意:this.offsetTop最终获取的是number类型的值,并且它还会对小数进行四舍五入,
//如果this.style.Top中有小数,并且还低于0.5,那么就会导致offsetTop每次获取到的值,
//都是一样,然后就会造成 盒子不懂,定时器不停的现象发生,所以缓速动画时要记得给步长取整
// 如果步长>0就向上取整,避免步长小于0.5时出现bug,
// 如果步长<0,就向下取整,避免步长下雨-0.5时出现bug。
//每次移动的步长
element.spend = (target - element.offsetTop) / 10
//对步长进行取整,避免offsetTop底层的四舍五入的影响
element.spend = element.spend > 0 ? Math.ceil(element.spend) : Math.floor(element.spend);
//目标位置减去当前位置的绝对值 如果小于步长的绝对值 那么就说明也就一步之遥了,
// 那么直接移动到指定的位置清除计时器算了。
if (Math.abs(target - element.offsetTop) <= Math.abs(element.spend)) {
element.style.top = target + "px";
clearInterval(element.timer);
return;
}
//重新设置距离左边的位置
element.style.top = element.offsetTop + element.spend + "px";
console.log(element.style.top)
}, 10);
}
/**
* 功能:获取兼容性的css样式对象的样式属性值
* 其它:可以获取内嵌式、外链式、行内式的样式对象的样式属性值
* @param element
* @returns {*}
*/
//function getStyle(element, attribute) {
// return element.currentStyle ?
// element.currentStyle[attribute] :
// window.getComputedStyle(element, null)[attribute];
//}
function getStyle(element, attribute) {
return (element.currentStyle
?
element.currentStyle[attribute]
:
window.getComputedStyle(element, null)[attribute])
||
element.style[attribute];
}
/**
* 功能:用来检测浏览器可视区域的兼容性的client对象
* @returns {{width: (Number|number), height: (Number|number)}}
*/
function client() {
return {
width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
}
}
/**
* 功能:获取scroll对象
* @returns {*}
*/
function scroll() {
/*
*注意事项:
*1.无论有没有声明DTD 在IE9及以上的所有浏览器都支持window.pageXOffset和window.pageYOffset
* 但是在IE9以下不支持,并且会返回undefined。
*2.在没有声明DTD时 在IE9以上的所有浏览器都支持document.body.scrollLeft和document.body.scrollTop
* 在声明了DTD时 所有浏览器都不支持,并且会返回0
*3.在声明了DTD时 所有浏览器都支持document.documentElement.scrollLeft和document.documentElement.scrollTop
* 无论有没有声明DTD IE浏览器都支持,没有声明DTD 其它除了IE浏览器外都不支持,并且会返回0。
* */
//判断是否不为undefined
if (window.pageXOffset !== "undefined" || window.pageYOffset !== "undefined") {
//返回一个关于scroll的对象回去
return {scollLeft: window.pageXOffset, scollTop: window.pageYOffset};
}
else if (document.compatMode === "BackCompa") {//是否没有声明DTD(或者其它标签之上的标记)
//判断是否是IE浏览器
if (document.documentElement.scrollLeft || document.documentElement.scrollTop) {
return {scollLeft: document.documentElement.scrollLeft, scollTop: document.documentElement.scrollTop};
}
else {//如果不是IE浏览器
return {scollLeft: document.body.scrollLeft, scollTop: document.body.scrollTop};
}
}
else {//如果声明了DTD
return {scollLeft: document.documentElement.scrollLeft, scollTop: document.documentElement.scrollTop};
}
// //精简版封装只需要返回 这个就是上面判断的精简 效果一样
// return {
// scollLeft: window.pageXOffset || document.body.scrollLeft || document.documentElement.scrollLeft,
// scollTop: window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop
// }
}
/**
* 功能:根据 传递参数 返回相应的对象
* 说明:参数为:#id选择器、.class选择器、tag普通选择器其中一种
* @param str
* @returns {*}
*/
function $(str) {
//获取头部选择符
var head = str.charAt(0);
//去除id选择器与class选择器标识后的内容
var body = str.slice(1);
if (head === "#") { //id
return document.getElementById(body);
} else if (head === ".") {//class
return document.getElementsByClassName(body);
} else {//tag
return document.getElementsByTagName(str);
}
}
//******************获取子元素节点*********开始********//
/**
* 功能:获取第一个子元素节点
* @param ele
* @returns {Element|*|Node}
*/
function getfirstchild(ele) {
return ele.firstElementChild || ele.firstChild;
}
/**
* 功能:获取最后一个子元素节点
* @param ele
* @returns {Element|*|Node}
*/
function getlastchild(ele) {
return ele.lastElementChild || ele.lastChild;
}
/**
* 功能:获取对应索引值的子元素节点
* @param ele
* @param index
* @returns {*|HTMLElement}
*/
function getchildofindex(ele, index) {
return ele.children[index];
}
/**
* 功能:获取所有的子元素节点
* @param ele
* @returns {Array}
*/
function getallchild(ele) {
var newArr = [];
var oldArr = ele.children;//childNodes;
for (var i = 0; i < oldArr.length; i++) {
if (oldArr[i].nodeType === 1) {
newArr.push(oldArr[i]);
}
}
return newArr;
}
//******************获取子元素节点*********结束********//
//******************获取兄弟元素节点*********开始********//
/**
* 功能:获取上一个兄弟元素节点
* @param ele
* @returns {Element|*|Node}
*/
function getpresibling(ele) {
var pre = ele.previousElementSibling || ele.previousSibling;
return pre;
}
/**
* 功能:获取下一个兄弟元素节点
* @param ele
* @returns {Element|*|Node}
*/
function getnextsibling(ele) {
return ele.nextElementSibling || ele.nextSibling;
}
/**
* 功能:获取对应索引值的兄弟元素节点
* @param ele
* @param index
* @returns {*|HTMLElement}
*/
function getsiblingofindex(ele, index) {
return ele.parentNode.children[index];
}
/**
* 功能:获取所有的兄弟元素节点(不包括自己)
* @param ele
* @returns {Array}
*/
function getallsibling(ele) {
var newArr = [];
var oldArr = ele.parentNode.children;
for (var i = 0; i < oldArr.length; i++) {
if (oldArr[i] != ele) {
newArr.push(oldArr[i]);
//newArr[newArr.length]=oldArr[i];
}
}
return newArr;
}
//******************获取兄弟元素节点*********结束********//
◆手风琴效果:图片大小为1226*640
使用封装的样式缓速框架制作手风琴
◆360开机动画:
模拟360开机动画缓速退出