美文网首页我爱编程
Web前端------JS基础匀速动画、缓动动画函数封装和Scr

Web前端------JS基础匀速动画、缓动动画函数封装和Scr

作者: Peak_One | 来源:发表于2018-05-17 16:55 被阅读319次

关于缓动动画的JS代码封装:(支持来回运动)

缓动动画在书写的时候会存在一些问题,牵涉到向上取整和向下取整问题,这些问题的关于是由于offsetleft在取值的时候是采用四舍五入取整的策略,导致缓动动画在运动为末尾会陷入死循环,导致无法到达最终的目标位置,以及无法清除定时器。所以特别将缓动动画的封装代码展示出来以供后期使用:

//缓动动画封装
    function animate(ele,target) {
        //要用定时器,先清定时器
        //一个萝卜一个坑儿,一个元素对应一个定时器
        clearInterval(ele.timer);
        //定义定时器
        ele.timer = setInterval(function () {
            //获取步长
            //步长应该是越来越小的,缓动的算法。
            var step = (target-ele.offsetLeft)/10;
            //对步长进行二次加工(大于0向上取整,小于0项下取整)
            step = step>0?Math.ceil(step):Math.floor(step);
            //动画原理: 目标位置 = 当前位置 + 步长
            ele.style.left = ele.offsetLeft + step + "px";
            //检测缓动动画有没有停止
            console.log(1);
            if(Math.abs(target-ele.offsetLeft)<=Math.abs(step)){
                //处理小数赋值
                ele.style.left = target + "px";
                clearInterval(ele.timer);
            }
        },30);
    }

关于匀速动画的JS代码封装:(支持来回运动)

   function animate(ele,target){
        //要用定时器,先清除定时器
        //一个盒子只能有一个定时器,这样儿的话,不会和其他盒子出现定时器冲突
        //而定时器本身讲成为盒子的一个属性
        clearInterval(ele.timer);
        //我们要求盒子既能向前又能向后,那么我们的步长就得有正有负
        //目标值如果大于当前值取正,目标值如果小于当前值取负
        var speed = target>ele.offsetLeft?10:-10;
        ele.timer = setInterval(function () {
            //在执行之前就获取当前值和目标值之差
            var val = target - ele.offsetLeft;
            ele.style.left = ele.offsetLeft + speed + "px";
            //目标值和当前值只差如果小于步长,那么就不能在前进了
            //因为步长有正有负,所有转换成绝对值来比较
            if(Math.abs(val)<Math.abs(speed)){
                ele.style.left = target + "px";
                clearInterval(ele.timer);
            }
        },30)
    }



Scroll()方法的封装

scrollTop和scrollLeft是用来监测浏览器滑动范围(Y方向和X方向)的两个属性,但是各大浏览器对于这两个属性的支持程度不同,所以在使用时,要兼容各大浏览器
具体差别如下描述:
一、未声明 DTD(谷歌只认识他)
document.body.scrollTop
二、已经声明DTD(IE678只认识他)
document.documentElement.scrollTop
三、火狐/谷歌/ie9+以上支持的
window.pageYOffset

常见的兼容性写法:

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

为了检测网页是否声明DTD,引入了compatMode
document.compatMode === "BackCompat"
BackCompat 未声明
CSS1Compat 已经声明
注意大小写
借助Json,对该方法进行封装如下:

  function scroll(){
            //如果这个属性存在,那么返回值应该是0-无穷大
            //如果没有返回值是undefined;
            //只要判断不是undefined就可以调用此方法
            //练习使用此种封装
            if(window.pageYOffset !== undefined){
//                var json = {
//                    "top": window.pageYOffset,
//                    "left": window.pageXOffset
//                };
//                return json;
                return {
                    "top": window.pageYOffset,
                    "left": window.pageXOffset
                };
            }else if(document.compatMode === "CSS1Compat"){
                return {
                    "top": document.documentElement.scrollTop,
                    "left": document.documentElement.scrollLeft
                };
            }else{
                return {
                    "top": document.body.scrollTop,
                    "left": document.body.scrollLeft
                };
            }

            //简单封装(实际工作使用)
//            return {
//                "top": window.pageYOffset || document.body.scrollTop || document.documentElement.scrollTop,
//                "left":  window.pageXOffset || document.body.scrollLeft || document.documentElement.scrollLeft
//            }
        }
另外:获取title、body、head、html标签
  • document.title --- 文档标题;
  • document.head --- 文档的头标签
  • document.body --- 文档的body标签;
  • document.documentElement --- 这个很重要
    它表示文档的html标签, 也就是说,基本结构当中的html标签并不是通过document.html 去访问的,而是document.documentElement
JS楼层跳转小案例

代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

</head>
<style>
    *{
        margin: 0px;
        padding: 0px;
    }
    html,body{
        height: 100%;
    }
    ul{
        list-style: none;
        height: 100%;
    }

    ul li{
        height: 100%;
    }

    ol{
        list-style: none;
        position: fixed;
        top: 80px;
        left:50px;
    }

    ol li{
        width: 50px;
        height: 50px;
        border:1px solid #000;
        text-align: center;
        line-height: 50px;
        margin-top: -1px;
        cursor: pointer;
    }
</style>
<body>
    <ul>
        <li>鞋子区域</li>
        <li>袜子区域</li>
        <li>裤子区域</li>
        <li>裙子区域</li>
        <li>帽子区域</li>
    </ul>
    <ol>
        <li>鞋子</li>
        <li>袜子</li>
        <li>裤子</li>
        <li>裙子</li>
        <li>帽子</li>
    </ol>
    <script src="animate.js"></script>
    <script>
        //需求:点击ol中的li,屏幕划定到对应的ul中的li的范围
        //思路:还是利用window.scrollTo();利用缓动动画原理实现屏幕滑动
        //步骤;
        //0.获取元素
        var ul=document.getElementsByTagName("ul")[0];
        var ol=document.getElementsByTagName("ol")[0];
        var ulLiArr=ul.children;
        var olLiArr=ol.children;
        var timer=null;
        var target=0;
        var leader=0;
        //1.指定ul和ol中的li的背景色,对应的li背景色相同
        //设置一个数组,里面装颜色,然后指定的颜色给数组中的指定元素
        var arrColor=["pink","blue","yellow","orange","green"];
        //利用for循环给两个数组中的元素上色
        for (var i = 0; i < arrColor.length; i++) {
            ulLiArr[i].style.backgroundColor=arrColor[i];
            olLiArr[i].style.backgroundColor=arrColor[i];
            //属性绑定索引值
            olLiArr[i].index=i;
            //2.老三步(并绑定事件)循环绑定

            olLiArr[i].onclick=function () {
                //*****获取目标位置
                //获取索引值
                target = ulLiArr[this.index].offsetTop;
                //要用定时器,先清除定时器
                clearInterval(timer);
                //3.利用缓动动画原理实现屏幕滑动
                timer=setInterval(function () {
                    //1.获取步长。
                    var step=(target-leader)/10;
                    //2.二次处理步长
                    step=step>0?Math.ceil(step):Math.floor(step);
                    //3.屏幕滑动
                    leader=leader+step;
                    window.scrollTo(0,leader);
                    //4.清除定时器
                    if(Math.abs(leader-target)<=Math.abs(step)){
                        window.scrollTo(0,target);
                        clearInterval(timer);
                    }
                },25);


            }

            
        }

        window.onscroll=function () {
            //每次屏幕互动,把屏幕卷曲的头部复制给leader,模拟获取显示区域距离网页顶部的距离
            leader=scroll().top;
            document.title=leader;

        }


    </script>
</body>
</html>

其中引用的JS文件如下:

//缓动动画封装
function animate(ele,target) {
    clearInterval(ele.timer);
    ele.timer = setInterval(function () {
        var step = (target-ele.offsetTop)/10;
        step = step>0?Math.ceil(step):Math.floor(step);
        ele.style.top = ele.offsetTop + step + "px";
        console.log(1);
        if(Math.abs(target-ele.offsetTop)<Math.abs(step)){
            ele.style.top = target + "px";
            clearInterval(ele.timer);
        }
    },25);
}

function scroll() {  // 开始封装自己的scrollTop
    if(window.pageYOffset != null) {  // 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
    }
}
/**
 * Created by Lenovo on 2016/9/2.
 */
/**
 * 通过传递不同的参数获取不同的元素
 * @param str
 * @returns {*}
 */
function $(str){
    var str1 = str.charAt(0);
    if(str1==="#"){
        return document.getElementById(str.slice(1));
    }else if(str1 === "."){
        return document.getElementsByClassName(str.slice(1));
    }else{
        return document.getElementsByTagName(str);
    }
}

/**
 * 功能:给定元素查找他的第一个元素子节点,并返回
 * @param ele
 * @returns {Element|*|Node}
 */
function getFirstNode(ele){
    var node = ele.firstElementChild || ele.firstChild;
    return node;
}

/**
 * 功能:给定元素查找他的最后一个元素子节点,并返回
 * @param ele
 * @returns {Element|*|Node}
 */
function getLastNode(ele){
    return ele.lastElementChild || ele.lastChild;
}

/**
 * 功能:给定元素查找他的下一个元素兄弟节点,并返回
 * @param ele
 * @returns {Element|*|Node}
 */
function getNextNode(ele){
    return ele.nextElementSibling || ele.nextSibling;
}

/**
 * 功能:给定元素查找他的上一个兄弟元素节点,并返回
 * @param ele
 * @returns {Element|*|Node}
 */
function getPrevNode(ele){
    return ele.previousElementSibling || ele.previousSibling;
}

/**
 * 功能:给定元素和索引值查找指定索引值的兄弟元素节点,并返回
 * @param ele 元素节点
 * @param index 索引值
 * @returns {*|HTMLElement}
 */
function getEleOfIndex(ele,index){
    return ele.parentNode.children[index];
}

/**
 * 功能:给定元素查找他的所有兄弟元素,并返回数组
 * @param ele
 * @returns {Array}
 */
function getAllSiblings(ele){
    //定义一个新数组,装所有的兄弟元素,将来返回
    var newArr = [];
    var arr = ele.parentNode.children;
    for(var i=0;i<arr.length;i++){
        //判断,如果不是传递过来的元素本身,那么添加到新数组中。
        if(arr[i]!==ele){
            newArr.push(arr[i]);
        }
    }
    return newArr;
}

效果如下所示:


效果图.gif

有一些bug,就是不方便滑动,需要优化

欢迎关注我的个人微信公众号,免费送计算机各种最新视频资源!你想象不到的精彩!


0.jpg

相关文章

网友评论

    本文标题:Web前端------JS基础匀速动画、缓动动画函数封装和Scr

    本文链接:https://www.haomeiwen.com/subject/ootidftx.html