JS5-PC端网页特效

常见offset系列属性作用

常见client系列属性作用

常见scroll系列属性作用

封装简单动画函数

写出网页轮播图案例

offset

偏移量,使用offset相关属性可以动态的得到该元素的位置、大小等

  • 获得元素距离带有定位父元素的位置
  • 获得元素自身的大小
  • 注意:返回的数值不带单位

offsetParent: 返回作为该元素带有定位的父级元素,如果父级都没有定位则返回body

offsetWidth:获取元素的宽,包括内边距、边框、内容

offsetHeight:获取元素的高,包括内边距、边框、内容

offsetLeft:获取元素距离左边位置的值,以带有定位的父亲为准,如果没有父亲或者父亲没有定位则相对body

offsetTop;获取元素距离上面位置的值,以带有定位的父亲为准,如果没有父亲或者父亲没有定位则相对body

offset与style区别

  • offset可以得到任意样式表的样式值 style只能得到内嵌样式的样式值
  • offset得到的是数字型,不带单位 style是字符串带单位
  • offset包含整个盒子,style得到的只是width,不包括padding和border
  • offset只能读不能写,而width可以赋值
  • 因此,读属性值一般用offset,写属性一般用width

案例:获取鼠标在盒子里的坐标

  1. 获取鼠标在页面内的坐标
  2. 获取盒子在页面内的坐标
  3. 相减
var box=document.querySelector('.box');
box.addEventListener('mousemove',function(){//鼠标移动事件
    var x=e.pageX-this.offsetLeft;
    var y=e.pageY-this.offsetTop;
    this.innerHTML='X坐标是'+x+'y坐标是'+y;
})

元素可视区client系列

client是客户端,可动态得到元素边框大小,元素大小等,与offset最大的区别就是不包含边框

clientTop 上边框

clientLeft 左边框

clientWidth

clientHeight 包括padding、内容,不包括边框,返回数值不带单位

立即执行函数

不需要调用立马能够自己执行的函数

(function(){})()    或者  (function(){}())
  • 第二个小括号可以看做是调用函数,可以传递参数,外面括号是实参,里面小括号是形参
  • 两种方法使用方法一致
  • 最大的作用就是独立创建了一个作用域,所有变量都是局部变量,不会有命名冲突

淘宝源码分析

(function flexible(window, document) {
    var docEl = document.documentElement
    var dpr = window.devicePixelRatio || 1

    // adjust body font size
    function setBodyFontSize() {
        if (document.body) {
            document.body.style.fontSize = (12 * dpr) + 'px'
        } else {
            document.addEventListener('DOMContentLoaded', setBodyFontSize)
        }
    }
    setBodyFontSize();

    // set 1rem = viewWidth / 10
    function setRemUnit() {
        var rem = docEl.clientWidth / 10
        docEl.style.fontSize = rem + 'px'
    }

    setRemUnit()

    // reset rem unit on page resize
    window.addEventListener('resize', setRemUnit)
    window.addEventListener('pageshow', function(e) {
        if (e.persisted) {
            setRemUnit()
        }
    })

    // detect 0.5px supports
    if (dpr >= 2) {
        var fakeBody = document.createElement('body')
        var testElement = document.createElement('div')
        testElement.style.border = '.5px solid transparent'
        fakeBody.appendChild(testElement)
        docEl.appendChild(fakeBody)
        if (testElement.offsetHeight === 1) {
            docEl.classList.add('hairlines')
        }
        docEl.removeChild(fakeBody)
    }
}(window, document))
  • 前进后退、a标签、刷新都会触发load,但是火狐浏览器使用load事件时存在往返缓存,后退按钮不能刷新页面,可以使用pageshow事件触发,这个事件在页面显示时触发,无论页面是否来自缓存,可以根据事件对象的persisted判断是否缓存中页面触发的pageshow事件,这个事件要给window添加

元素滚动scroll系列

scrollTop: 返回被卷去的上侧距离,返回数值不带单位(隐藏的高度)

scrollLeft: 左侧距离,同上

scrollWidth: 返回自身实际宽度,不含边框,返回数值不带单位,包含内容超出盒子的部分

scrollHeight:高度 同上

scroll事件:

'scroll' 滚动触发的事件

window.pageXOffset:页面被卷曲的头部

兼容性问题:

  1. 声明了DTD,使用document.documentElement.scrollTop
  2. 未声明DTD,使用document.body.scrollTop
  3. 新方法window.pageYOffset和window.pageXOffset,IE9开始支持

兼容性方案(了解)

function getScroll() {
    return {
        left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0,
        top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0
    };
}

三大系列总结

  • offset包含边框,scroll包括文字超出部分

  • offset一般用于获取元素位置,client常用与获取元素大小,获取滚动距离一般用scroll

mouseenter和mouseover

mouseover:经过自身盒子会触发,经过子盒子还会触发一次

mouseenter只有经过自身盒子才会触发,因为mouseenter不会冒泡

动画函数封装

动画实现原理

通过定时器setInterval()不断移动盒子位置

  1. 获取盒子当前位置
  2. 在盒子当前位置上加移动距离
  3. 利用定时器不断重复操作
  4. 加一个结束定时器的条件
  5. 此元素一定要加定位,因为要使用element.left实现移动

动画函数简单封装

需要传递两个参数,动画对象和移动的距离

可以实现某个对象右移移动到某个位置

function animate(obj,target){
	clearInterval(obj.timer)//
    obj.timer=setInterval(function(){
        if(obj.offsetLeft>=target){
            clearInterval(obj.timer);
        }
        obj.style.left=obj.offsetLeft+1+'px';
    },30);
}
  • var timer=每次开辟空间浪费资源,且使用obj.timer避免不同调用使用相同的变量timer,因此通过添加属性实现给不同元素添加不同定时器
  • 注意要先清除原来的定时器,只保留当前定时器,避免多次触发动画时创建很多定时器造成不正常现象

缓动动画

让元素的运动速度有所变化,最常见的是让速度慢慢减下来

思路:

  1. 让盒子每次移动的距离慢慢变小
  2. (目标值-现在的位置)/10 作为每次移动的距离步长即可
  3. 停止的条件:让当前盒子位置等于目标位置时停止定时器

把每次+1的步长改为慢慢变小的值 即

function animate(obj,target){
	clearInterval(obj.timer)//
    obj.timer=setInterval(function(){
    	var step=target-obj.offsetLeft)/10;//计算步长,要注意不要出现小号,还要考虑负值
    	step>0?Math.ceil(step):Math.floor(step)
        if(obj.offsetLeft==target){//修改为等于号
            clearInterval(obj.timer);
        }
        obj.style.left=obj.offsetLeft+step+'px';
    },30);
}

为了实现在多个目标间移动,需要考虑步长正负

动画函数添加回调函数(重要)

回调函数原理:函数可以作为一个参数,将这个参数传到另一个函数里,当那个函数执行完之后再执行传进去的这个函数,这个过程称为回调

操作方法:输入添加一个函数作为参数,函数执行写在计时器停止的内容里,即可实现执行完动画后执行回调函数

if(callback){

callback()}

如下代码即可实现运动完毕后盒子变颜色

function animate(obj, target, callback) {
            // console.log(callback);  callback = function() {}  调用的时候 callback()

            // 先清除以前的定时器,只保留当前的一个定时器执行
            clearInterval(obj.timer);
            obj.timer = setInterval(function() {
                // 步长值写到定时器的里面
                // 把我们步长值改为整数 不要出现小数的问题
                // var step = Math.ceil((target - obj.offsetLeft) / 10);
                var step = (target - obj.offsetLeft) / 10;
                step = step > 0 ? Math.ceil(step) : Math.floor(step);
                if (obj.offsetLeft == target) {
                    // 停止动画 本质是停止定时器
                    clearInterval(obj.timer);
                    // 回调函数写到定时器结束里面
                    if (callback) {
                        // 调用函数
                        callback();
                    }
                }
                // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
                obj.style.left = obj.offsetLeft + step + 'px';

            }, 15);
        }
        var span = document.querySelector('span');
        var btn500 = document.querySelector('.btn500');
        var btn800 = document.querySelector('.btn800');

        btn500.addEventListener('click', function() {
            // 调用函数
            animate(span, 500);
        })
        btn800.addEventListener('click', function() {
                // 调用函数
                animate(span, 800, function() {
                    // alert('你好吗');
                    span.style.backgroundColor = 'red';
                });
            })

返回顶部

window.scroll(0, 0);//x,y不跟单位直接写数字就好
  1. 快速滚动到顶端

  2. 编写垂直运动的动画函数,点击后目标设为0(y坐标)

goBack.addEventListener('click', function () {
            animate(window, 0);//窗口动画,对象是window
        });
        function animate(obj, target, callback) {
            // console.log(callback);  callback = function() {}  调用的时候 callback()

            // 先清除以前的定时器,只保留当前的一个定时器执行
            clearInterval(obj.timer);
            obj.timer = setInterval(function () {
                // 步长值写到定时器的里面
                // 把我们步长值改为整数 不要出现小数的问题
                // var step = Math.ceil((target - obj.offsetLeft) / 10);

                var step = (target - window.pageYOffset) / 10;
                step = step > 0 ? Math.ceil(step) : Math.floor(step);
                if (window.pageYOffset == target) {
                    // 停止动画 本质是停止定时器
                    clearInterval(obj.timer);
                    // 回调函数写到定时器结束里面
                    callback && callback();//如果有参数传入才会调用callback
                }
                // 把每次加1 这个步长值改为一个慢慢变小的值  步长公式:(目标值 - 现在的位置) / 10
                // obj.style.left = obj.offsetLeft + step + 'px';
                window.scroll(0, window.pageYOffset + step);

            }, 15);
        }
posted @ 2021-11-13 16:49  清梨  阅读(50)  评论(0编辑  收藏  举报