Javascript动画相关

  1. 家族之一offset

三大家族(offset/scroll/client)

事件对象/event   (事件被触动时,鼠标和键盘的状态)(通过属性控制)

offset --偏移,补偿,位移。

js中有一套方便的获取元素尺寸的办法就是offset家族;

offsetWidthoffsetHight 以及offsetLeftoffsetTop以及offsetParent

共同组成了offset家族。

 

1.1 offsetWidth和offsetHight (检测盒子自身宽高+padding+border)

这两个属性,他们绑定在了所有的节点元素上。获取之后,只要调用这两个属性,我们就能够获取元素节点的宽和高。

offset宽/高  =  盒子自身的宽/高 + padding +border;

offsetWidth = width+padding+border;

offsetHeight = Height+padding+border;

 

1.2 offsetLeft和offsetTop  (检测距离父盒子有定位的左/上面的距离)

返回距离上级盒子(带有定位)左边s的位置

如果父级都没有定位则以body为准

offsetLeft 从父亲的padding 开始算,父亲的border 不算。

在父盒子有定位的情况下,offsetLeft == style.left(去掉px)

 

1.3 offsetParent   (检测父系盒子中带有定位的父盒子节点)

1、返回该对象的父级 (带有定位)

           如果当前元素的父级元素没有进行CSS定位 (position为absolute或relative,fixed),   offsetParentbody

2、如果当前元素的父级元素中有CSS定位        (position为absolute或relative,fixed),   offsetParent取最近的那个父级元素。

 

1.4 offsetLeft和style.left区别

 

最大区别在于offsetLeft可以返回没有定位盒子的距离左侧的位置。

而 style.left不可以

二、offsetTop 返回的是数字,而 style.top 返回的是字符串,除了数字外还带有单位:px。

三、offsetTop 只读,而 style.top 可读写。(只读是获取值,可写是赋值

四、如果没有给 HTML 元素指定过 top 样式,则style.top 返回的是空字符串。

 

style.left在=的左边和右边还不一样。(左边的时候是时候是值)属性,右边的

 

offsetLeft获取盒子距离左侧具有定位的父盒子的距离(没有的body),四舍五入取整。

Style.left获取的是具体值。 (赋值的时候也是直接赋值)                 

ffsetLeft offsetTop获取值

style.left style.top赋值

 

  1. 动画入门

部分函数(必须掌握)

Math.abs(num);        //取绝对值

Math.floor(num);      //向下取整

Math.ceil(num);        //向上取整

Math.round(num);          //四舍五入    负数四舍六入

Math.random()    //随机数0-1

 

  1. 家族之二Scroller

scroll这个单词本身是--卷页,卷曲

3.1 ScrollWidth和scrollHeight(不包括border)

检测盒子的宽高。(调用者:节点元素。属性。)

盒子内容的宽高。(如果有内容超出了,显示内容的高度)

IE567可以比盒子小。 IE8+火狐谷歌不能比盒子小

3.2 scrollTop和scrollLeft

网页,被浏览器遮挡的头部和左边部分。

被卷去的头部和左边部分。

3.3 他有兼容性问题

1.未声明 DTD(谷歌只认识他)

document.body.scrollTop

2.已经声明DTD(IE678只认识他)

document.documentElement.scrollTop

火狐/谷歌/ie9+以上支持的

window.pageYOffset

3.兼容写法:

var aaa=window.pageYOffset||document.documentElement.scrollTop || document.body.scrollTop || 0;

var aaa=document.documentElement.scrollTop+document.body.scrollT

3.4判断页面有没有DTD

document.compatMode === "BackCompat"

BackCompat  未声明

CSS1Compat  已经声明

注意大小写

function scroll() {  // 开始封装自己的scrollTop
   
if(window.pageYOffset !== undefined) {  // ie9+ 高版本浏览器
        // 因为 window.pageYOffset 默认的是  0  所以这里需要判断
       
return {
           
left: window.pageXOffset,
           
top: window.pageYOffset
        }
    }
   
else if(document.compatMode === "CSS1Compat") {    // 标准浏览器   来判断有没有声明DTD
       
return {
           
left: document.documentElement.scrollLeft,
           
top: document.documentElement.scrollTop
        }
    }
    
return {   // 未声明 DTD
       
left: document.body.scrollLeft,
       
top: document.body.scrollTop
    }
}

 

3.5 事件

a) onscroll事件

只要页面滚动无论向左向右,向上向下,哪怕只有1px,都会触动这个事件

 

b) 屏幕跳转

window.scrollTo

方法可把内容滚动到指定的坐标。

格式:

scrollTo(xpos,ypos)

xpos    必需。要在窗口文档显示区左上角显示的文档的 x 坐标。

ypos   必需。要在窗口文档显示区左上角显示的文档的 y 坐标

 

3.5 案例

固定导航栏

使用fixed定位

广告跟随

window.onsroll(){}绑定事件

返回头部小火箭 

  1. 定义全局定时器timer
  2. 获取对象
  3. 给对象绑定事件
  4. 计算步长
  5. 处理步长(向上取整 向下取整)
  6. 计算屏幕滑动距离(leader = leader+step)
  7. 调用函数window.srollTo(0,learder);
  8. 判断是否到达指定地点,闪现清理定时器

4获取title、body、head、html标签

document.title --- 文档标题;

document.head --- 文档的头标签

document.body --- 文档的body标签;

document.documentElement --- 这个很重要

 

它表示文档的html标签,也就是说,基本结构的html标签并不是通过document.html访问的,而是document.documentElement;

5 关于json

Json是一种和数组类似的数据类型。

不同的是:数组中的元素是单一的。

而json中的元素,是以键值对的形式出现的。(key: value)

定义方法

var  json  =  { key1:value1,key2:value2,key3:value3...  };

数组是通过索引值获取数组中的元素的,而json是通过key获取元素的。

获取内容

JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,我们称之为JavaScript对象表示法。使用JSON进行数据传输的优势之一。表示方法为键值对,key:value。

var myjson={k1:v1,k2:v2,k3:v3...}

注意:不用添加双引号,

var json = {"name":"xh","sno":"35","lover":{"sex":"gril","name":"ty"}};

获取方式:v1 == myjson.k1  v2 == myjson.k2

Json一般就是被当做一个配置单用;

 

遍历:

for(var i in json){

      console.log(i);

      console.log(json[i]);

}

 

6.事件对象(event)

再触发DOM上的某个事件时,会产生一个事件对象event

比如鼠标操作时候,会添加鼠标位置的相关信息到事件对象中。(类似Date)

普通浏览器支持 event(带参,任意参数)

ie 678 支持 window.event(无参,内置)

总结:他是一个事件中的内置对象。内部装了很多关于鼠标和事件本身的信息。

6.1 event的事件获取

IE678中,window.event

在火狐谷歌中,event或者,在事件绑定的函数中,加参,这个参数就是event.

  Box.onclick = function (aaa){   //aaa就是event 

 var aa = event.target;        //获取点击的dom节点

 

6.2 clientX与clientY

Javascript动画相关

 

pageX/pageY:鼠标相对于整个页面顶部的x坐标,y坐标

screenX/screenY: 鼠标相对于整个屏幕的x坐标,y坐标

 

6.3 兼容获取方式有两种:

不写参数直接使用event;

写参数,但是为event....var event  = event || window.event;(主要用这种)

6.4 PageY和pageX的兼容写法(很重要

在页面位置就等于 = 看得见的+看不见的

pageY/pageX=event.clientY/clientX+scroll().top/scroll().left

6.5 onmousemove事件

常用事件:

  • onmouseover  鼠标经过
  • onmouseenter
  • onmouseleave
  • onmouseout  鼠标离开
  • onmousedown  鼠标按下
  • onmouseup  鼠标弹起
  • onmousemove  鼠标移动(1px也触动)

只要鼠标在绑定该事件的事件源上移动,哪怕1像素,也会触动这个事件。(这个事件可以直接或者间接的替代定时器

获取鼠标在盒子的位置

 

sda

 

 
   

 

 

 

 

 

 

targex = pageX – div.offsetTop;

targey = pageY – div.offsetLeft;

 

div.onmousemove = function(event){

      event = event ||window.event;

      //1.获取鼠标在整个页面的位置

      var pagex = event.pageX||scroll().left+event.clientX;

      var pagey = event.pageY||scroll.top+event.clientY;

      //2.获取盒子在整个页面的位置

      //3.用鼠标的位置减去盒子的位置赋值给盒子的内容

      var targetx = pagex – div.offsetLeft;;

      var targety = pagey – div.offsetTop;

}

 

clientX/clientY: 鼠标相对于当前可见页面的x坐标,y坐标

 

 

event阻止表单submit跳转

Javascript动画相关

 

7.三大家族之三client用户(可视区)

注意:event.clientX 与 event.clientY是event事件的成员变量。与这个不同

包括:

7.1 client的属性

1、clientWidth    获取网页可视区域宽度(两种用法)

     clientHeight     获取网页可视区域高度(两种用法)

     调用者不同,意义不同:

           盒子调用:指盒子本身。

           body/html调用:可视区域大小。

/*2、clientX       鼠标距离可视区域左侧距离(event调用)

   clientY       鼠标距离可视区域上侧距离(event调用)

*/

3. clientTop        盒子的上border

   clientLeft        盒子的左border

 

区别1:(offset/scroll/client宽高)

clientWidth  = width  + padding

clientHeight = height + padding

offsetWidth  = width  + padding + border

offsetHeight = height + padding + border

scrollWidth   = 内容宽度(不包含border)

scrollHeight  = 内容高度(不包含border)

 

区别2:(offset/scroll/client上下)

offsetTop/offsetLeft :

调用者:任意元素。(盒子为主)

作用:距离父系盒子中带有定位的距离。

scrollTop/scrollLeft:(盒子也可以调用,必须有滚动条)

调用者:document.body.scrollTop/.....(window)

作用:浏览器无法显示的部分(被卷去的部分)。

clientY/clientX:(clientTop/clientLeft 值的是border)

调用者:event.clientX(event)

作用:鼠标距离浏览器可视区域的距离(左、上)。

7.2 client家族之:检浏览器宽/高度(可视区域)

ie9及其以上的版本

window.innerWidth/Height 

标准模式(有DTD)(“CSS1Compat”)

document.documentElement.clientWidth

document.documentElement.clientHeight

怪异模式 (没有DTD)

document.body.clientWidth

document.body.clientHeight

封装:类似scroll();

 

根据浏览器可视宽度,给定背景色。

模拟响应式 :  移动版(640)/平板版/PC版(960)

 移动端           /        PC端

 

 

8. 冒泡事件

事件传播的三个阶段是:捕获、冒泡和目标阶段

事件捕获阶段:事件从最上一级标签开始往下查找,直到捕获到事件目标(target)。

事件冒泡阶段:事件从事件目标(target)开始,往上冒泡直到页面的最上一级标签。

 

8.1 冒泡定义

div1>div2>div3 都设置点击事件时,

点击div3 会触发div3 div2 div1 事件

冒泡:从原始元素一直冒泡到dom树的最上层

捕获:从上往下执行

8.2冒泡顺序

IE 6.0:

div -> body -> html -> document

其他浏览器:

div -> body -> html -> document -> window

不是所有的事件都能冒泡。以下事件不冒泡:blur、focus、load、unload、onmouseenter

onmouseleave

 

检测一个事件是否冒泡:

document.onmouseenter = function(fn){

      event||event||window.event;

      console.log(event.bubbles);

}

如何阻止冒泡

w3c的方法是:(火狐、谷歌、IE11)

event.stopPropagation()

IE10以下则是使用:

event.cancelBubble = true

兼容代码如下:

 var event = event || window.event;

 if(event && event.stopPropagation){

            event.stopPropagation();

  }else{

            event.cancelBubble = true;

  }

 

  1. 变量属性获取/赋值方法

1给属性赋值:(既能获取又能赋值)

    1. div.style.width                              单个赋值
    2. div.style[“width”]                    变量赋值

2获取属性值:(只能获取)

    1. div.currentStyle.width;   IE678      单个获取
    2. window.getComputedStyle(div,null).width;
    3. div.currentStyle[“width”];   IE678        变量获取
    4. window.getComputedStyle(div,null)[“width”];

          参数1:获取属性的元素。

      参数2:伪元素,C3学习。

 

 

 

 

 

兼容方法获取元素样式

  function getStyle(ele,attr){

        if(window.getComputedStyle){

         return window.getComputedStyle(ele,null)[attr];

        }

         return ele.currentStyle[attr];

}

注意:封装获取到的数值要用parseInt去掉px单位

如var leader = parseInt(getStyle(div,attr))||0;

 

 

10.正则表达式

正则定义(1.内置对象法,2.字面量)

//1.对象定义法

var reg1 = new RegExp(/abc/);

//2.字面量

var reg2 = /def/;

console.log(reg2);

//验证 该方法返回的是一个bool值

reg1.test(“ab”);

N.经验

if(x<0){
   
mask.style.left = 0+"px";
}

if(x>box.offsetWidth-mask.offsetWidth){
   
mask.style.left = box.offsetWidth-mask.offsetWidth;
}

else{
   
mask.style.left = x+"px";
}

if(y<0){
   
mask.style.top = 0+"px";
}

else if(y>box.offsetHeight-mask.offsetHeight){
   
mask.style.top = box.offsetHeight-mask.offsetHeight;
}

else{
   
mask.style.top = y +"px";
}

 

if语句都tm要赋值,能不能移出if再赋值呢?

不然卡死你?为什么卡呢?

改良:

if(x<0){
   
x = 0;
}

if(x>box.offsetWidth-mask.offsetWidth){
   
x = box.offsetWidth-mask.offsetWidth;
}

if(y<0){
   
y = 0;
}

else if(y>box.offsetHeight-mask.offsetHeight){
   
y= box.offsetHeight-mask.offsetHeight;
}

mask.style.left = x+"px";
mask.style.top = y +"px";

 

  1. 自己封装的框架获取属性并赋值并移动

很多属性我们的框架无法获取值和赋值。

border-radius: 1px  21px  41px  1px ;

opacity: 0.5;

background: rgba(0,0,0,.4);

z-index: 1;

第一个是透明度(旋转木马)

  1. 值为小数,获取的时候要特殊处理。
  2. 兼容问题。IE678不识别opacity;

第二个是层级(旋转木马)(由需求决定的)

层级的提高是一次性直接提到最高,不需要一点一点儿的缓动。

 

function animate(ele,json,fn){
    clearInterval(ele.
timer);
   
//开闭原则
   
var bool = true;
    ele.
timer = setInterval(function(){
       
//遍历属性与值
       
for(var k in json){
           
//如果b不等于undefined和null
           
var leader = parseInt(getStyle(ele,k))||0;

           
//判断如果属性为opacity的时候特殊获取值
           
if(k === "opacity"){
               
leader = getStyle(ele,k)*100 || 1;
            }
else{
               
leader = parseInt(getStyle(ele,k)) || 0;
            }
           
//1获取步长
           
var step = (json[k]-leader)/10;
           
step = step>0?Math.ceil(step):Math.floor(step);
           
leader = leader + step;
           
//3.赋值
            //特殊情况特殊赋值
           
if(k === "opacity"){
                ele.style[
k] = leader/100;
               
//兼容IE678
               
ele.style.filter = "alpha(opacity="+leader+")";
               
//如果是层级,一次行赋值成功,不需要缓动赋值
                //为什么?需求!
           
}else if(k === "zIndex"){
                ele.style.zIndex = json[
k];
            }
else{
                ele.style[
k] = leader + "px";
            }
           
console.log(1);
           
//4.清理定时器
            //判断: 目标值和当前值的差大于步长,就不能跳出循环
            //不考虑小数的情况:目标位置和当前位置不相等,就不能清除清除定时器。
           
if(json[k] !== leader){
               
bool = false;
            }
        }
       
if(bool){
            clearInterval(ele.
timer);
           
if(fn){
                fn();
            }
        }
    },
50);

 

 

N.案例

 

  1. (案例)轮播图(setInterval+ style.left+animate)

基本概念:

步长 = step = (目标距离 – 所在距离)/10 = target – div.offsetLeft;(缓动)

var speed = target>ele.offsetLeft?10:-10;    (平均)

移动方法: div.style.left = div.offsetLeft+ step;

时间控制函数: setInterval(函数,间隔时间)      //每间隔时间执行一次函数

实现效果

Javascript动画相关

Javascript动画相关

原理:通过子绝父相 控制ul的style-left距离(向左移动肯定为负数)

Javascript动画相关

Javascript动画相关

//移动函数自定义
function animate(ele,target) {
    clearInterval(ele.
timer);
   
var speed = target>ele.offsetLeft?10:-10;
    ele.
timer = setInterval(function(){
       
//传递的目标值如果比当前值大,那么步长为+10
        //传递的目标值如果比当前值小,那么步长为-10
       
if (ele.offsetLeft === target){
            clearInterval(ele.
timer);
        }
else{
            ele.style.left = ele.offsetLeft+
speed+"px";
        }
    })
}

function autoPlay() {
   
//通过控制key的自增来模拟图片的索引值,然后移动ul
   
key++;
   
if(key>indicators.length){
       
//图片已经滑动到最后一张,接下来,跳转到第一张,然后在滑动到第二张
       
ul.style.left = 0;
       
key = 0;
    }
    animate(
ul,-key*imageWidth);
   
//修改indicator的样式
}

  1. 拖拽窗口(style.left+event+onmouse事件)

Javascript动画相关

结构:div(absolute)>top+bottom

整体思路:

1).top设置鼠标按下事件(onmousedown)

2).在按下事件内记录鼠标在盒子中的所在位置,以及设置文档鼠标移动事件

document.onmousemove = function(event){

记录鼠标在网页中的位置}

3).移动div,在鼠标离开div时清除document.onmousemove事件

hd.onmouseup = function () {
   
//解绑
   
document.onmousemove = null;
}

 

4).需要注意的是:盒子移动的距离为: 鼠标在网页中的位置-鼠标在盒子中的位置

移动盒子之后,//禁止文本选中(选中后取消)

window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
其实没有也没什么问题

 

  1. 放大镜(onmousemove+event)

Javascript动画相关

获得鼠标在盒子中的位置

移动黄色盒子

特殊情况1.离box 的距离小于黄色盒子的宽高时,黄色盒子距离box的距离为0

特殊情况2当鼠标距离盒子右边的值-1/2黄盒子的宽时>整个大盒子的宽-黄色盒子的宽时,黄色盒子移动的距离固定为,个大盒子的宽-黄色盒子的宽时

最后,大图片需要等比例移动

//大图片走的距离/mask盒子都的距离 = 大图片/小图片

var bili = bigImg.offsetWidth/small.offsetWidth;

var xx = bili*x;
var yy = bili*y;


bigImg.style.marginTop = -yy+"px";
bigImg.style.marginLeft = -xx+"px";

 

  1. 模拟滚动条

Javascript动画相关

 

结构:

Javascript动画相关

绑定事件:注意:onmousemove时document

block.onmousedown = function(event){
   
document.onmousemove = function(event){

 

 

//高级比例:  内容走的距离/bar走的距离 = (内容的高-大盒子的高)/(scroll的高-bar的高)
var bili = (p.offsetHeight - box_left.offsetHeight)/(block.offsetHeight-box_right.offsetHeight);
p.style.top = y*bili +"px";

 

//让被选文字清除。
window.getSelection() ? window.getSelection().removeAllRanges() : document.selection.empty();

 

document.onmouseup = function(event){
   
document.onmousemove = null;
}

 

  1. 隐藏登录框(event+ stopPropagation)

Javascript动画相关

需求:点击白框外面隐藏白框

思路:

第一步:给登录按钮绑定显示白框事件,并阻止冒泡事件(第二步需要用到)

第二步:给document对象,绑定点击事件,判断事件源的id是否为login,否则隐藏白框

 

  1. 旋转木马(json,animate)

Javascript动画相关

原理:将五张图片的css写成一个json数组,点击按钮为li更换样式,更换样式的方法为jquey的animate(div,json,fn);