JS运动总结

跟着视频学习了JS的运动基础以及相关的应用,总结了以下一套运动框架,可以直接调用。(以下所有项目调用的move.js文件均为此函数)

/**
 * 获取非行间样式,  兼容IE6--8
 * @param styObj    属性对象
 * @param name      属性名
 * return string    样式值
 */
function getStyle(styObj,name) {

    if(styObj.currentStyle){
        return styObj.currentStyle[name];
    }else {
        return getComputedStyle(styObj,false)[name];
    }
}

/**
 * 运动函数
 * @param obj           运动对象
 * @param json          json属性数组
 *                      json={ attr1:target1,attr2:target2 ......}
 * @param fnElement     回调函数
 */
function startMoving(obj,json,fnElement) {

    if(obj.timer != null)       // 多物体运动时,定时器各自工作,互不干扰
        clearInterval(obj.timer);

    obj.timer = setInterval(function () {
        let stop = true;        // 假设所有的值都已到了

        for(let attr in json){ 

            let currVal = 0;  // 当前属性样式值
            if(attr == "opacity"){
                currVal = Math.round(parseFloat(getStyle(obj,attr))*100);
            }else {
                currVal = parseInt(getStyle(obj,attr));
            }

            let speed = (json[attr] - currVal) / 8; // 运动速度
            speed = speed>0? Math.ceil(speed) : Math.floor(speed);  // 速度取整

            // 判断当前值是否等于目标值,如果不等,说明还未到达运动停止条件
            if(currVal != json[attr])
                stop=false;

            if(attr == "opacity"){
                obj.filter = "alpha(opacity:"+(currVal + speed)+")";
                obj.style.opacity = (currVal + speed) / 100;
            }else {
                obj.style[attr] = currVal + speed +"px";
            }
        }

        // 如果stop==true,说明中间没有出现未到达情况
        if(stop){
            clearInterval(obj.timer);
            if(fnElement) fnElement();
        }
    },30);
}

该框架可实现多个属性同时发生改变时的运用。需要注意的是,在开启定时器时,一定要先给每个对象都加入属于自己的定时器,这样当开启多个定时器时,才不会引起一系列不必要的问题。


运用运动框架,我写了几个简单的小案例,供参考学习和巩固。

案例1:

<head>
    <meta charset="UTF-8">
    <title>JS运动--完美运动框架,多属性同时运动</title>
    <style>
        div{width: 100px;height: 100px;background-color: darkred;filter: alpha(opacity:30);opacity: 0.3;position: absolute;right: 0;bottom: 0}
    </style>
</head>
<body>
<button id="btn">显示</button>
<div></div>

<script src="move.js"></script>
<script>
    window.onload = function () {
        let div = document.getElementsByTagName("div")[0];

        let btn = document.getElementById("btn");
        let flag=false; // 记录按钮是否被点击
        btn.onclick = function () {

            if(flag == false){
                btn.innerHTML = "隐藏";

                // 注意!!! 这种情况下会出现异常。
                // 因为当width达到目标值后,程序认为已经运动结束了,就将定时器给关闭了,导致后面的效果无法运行
                // 改进,使用 json 解决
                startMoving(div,{width:110,height:400,opacity:100},function () {
                    console.info("完成了");
                });

                flag=true;
            }else {
                btn.innerHTML = "显示";
                startMoving(div,{width:100,height:100,opacity:30});
                flag=false;
            }
        }
    }
</script>
</body>

 

案例2:实现类似于论坛发帖的效果,新消息显示在最前面,并添加从上往下的动画效果。

总结:在这个案例中,又把前面学过的DOM操作复习了遍。从创建子节点到追加和插入子节点,以及JS的运动函数。在实现的过程中,对于可变长的li高度问题,需要通过offsetHight来获取待插入节点的高,然后再设置其运动的距离。

我在写的过程中,最开始设置了li的宽度,然后高度设为了100%,这样导致了我在插入的时候出现了两个问题:

  1. 运动的过程变得很快,看起来就很生硬。而且当li设置了border-bottom时,插入时文字会最先全部出来,然后border-bottom才缓慢下来,这种现象在当ul里面没有li时,插入第一个li 体现最明显。
  2. 当我每次添加新内容,新内容和旧内容从上往下出来时,旧内容的背景是透明的,原因我还不是很明白。

针对出现的问题,后来我发现是宽高出了问题,不应该设置宽高,内容的宽高应该由padding撑开。对于这种自适应的,应该要注意这个问题,很关键!!!

<head>
    <meta charset="UTF-8">
    <title>JS运动应用--论坛消息列表</title>
    <style>
        body,ul,ol,li,p,h1,h2,h3,h4,h5,h6,form,fieldset,table,td,img,div,dl,dt,dd,input{margin: 0; padding: 0;}
        body{font-size: 12px;}
        img{border: none;}
        li{list-style: none;}
        input,select,textarea{outline: none;}
        textarea{resize: none;}
        a{text-decoration: none;}

        #message ul{width: 550px;height: 400px;overflow: hidden;border: 1px solid black;margin: 40px auto;}

        /* 不设置li的宽高,内容由padding撑开 */
        #message ul li{border-bottom: 1px dashed;padding:10px 20px 4px;overflow: hidden}
    </style>
</head>
<body>
<div>
    <textarea id="inform" cols="100" rows="10"></textarea>
    <input id="btn" type="submit" value="回复">
</div>
<div id="message">
    <ul></ul>
</div>

<script src="move.js"></script>
<script>
    window.onload = function () {
        let btn = document.getElementById("btn");
        let inform = document.getElementById("inform");
        let uls = document.getElementById("message").getElementsByTagName("ul")[0];

        btn.onclick = function () {

            // 获取文本框输入的内容
            let message = inform.value;
            inform.value="";

            // 创建元素
            let li = document.createElement("li");

            li.innerHTML = message;

            if(uls.children.length >0){
                // 当前列表项插入到ul的第一个子节点前面
                uls.insertBefore(li,uls.children[0]);
            }else {
                uls.appendChild(li);
            }

            // 获取li当前内容的高度
            let liHeight = li.offsetHeight;

            li.style.height = "0";

            startMoving(li,{height:liHeight});
        }
    }
</script>
</body>

写在最后的话:

我在查阅资料的时候,发现了一个作者写的JS运动系列,里面的案例比我的更丰富一些,写得也确实比我的好。

https://www.cnblogs.com/xiaohuochai/p/5980424.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值