IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 前端笔记第三期(JavaScript运动效果实现) -> 正文阅读

[JavaScript知识库]前端笔记第三期(JavaScript运动效果实现)

1.匀速直线运动

原理详解

var oDiv = document.getElementsByTagName('div')[0];
var oBtn = document.getElementsByTd('btn');
var timer = null;
oBtn.onclick = function(){
    // 每次执行先clear一下,保证每次触发的事件不会叠加生效
    clearInterval(timer);
    // 判断当前div是在目标300px处的左侧还是右侧,若在左侧,移动7px,若在右侧,移动 -7px
    var iSpeed = 300 - oDiv.offsetLeft > 0 ? 7 : - 7;
    // 延时30ms执行以下函数,在其定位位置每次右移4px
    timer = setInterval(function (){
        // 让方块运动到300px处停止,判断离300px相差是否小于4px
        // 使用 Math.abs() 取绝对值,不考虑正负号
        if(Math.abs(300 - oDiv.offsetLeft) < Math.abs(iSpeed)){
            clearInterval(timer);
            oDiv.style.left = '300px';
        }else{
            // 为div位置赋值,每次增加7px
            oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px';
        }
    }, 30);

实现封装

// dom:让谁移动(oDiv)    target:移动到哪(300)
function startMove(dom, target){
    clearInterval(timer);
    var iSpeed = target - oDiv.offsetLeft > 0 ? 7 : - 7;
    timer = setInterval(function (){
        if(Math.abs(target - dom.offsetLeft) < Math.abs(iSpeed)){
            clearInterval(timer);
            dom.style.left = target + 'px';
        }else{
            dom.style.left = dom.offsetLeft + iSpeed + 'px';
        }
    }, 30);
}

2.缓冲运动

物体的速度,距离目标点越近,就越慢,当到达目标点时,停止

实现封装

function startMove(dom, target){
    clearInterval(timer);
    var iSpeed = null;
    timer = setInterval(function(){
        // 移动速度为:目标位置-初始位置 / 7(可改,调速)
        iSpeed = (target - oDiv.offsetLeft) / 7;
        // 判断速度是正数或负数,正数向上取整,负数向下取整
        iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
        if(oDiv.offsetLeft == target) {
            clearInterval(timer);
        }else{
            oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px';
        }
    }, 30);
}

应用demo

页面侧面伸缩栏,鼠标移上去后,菜单弹出来,鼠标移走,菜单缩回去

<style>
    /* 设置样式,div样式为400px,初始状态在-400px,处于隐藏状态 */
    .wrapper {
        width: 400px;
        height: 80px;
        background: orange;
        position: absolute;
        left: -400px;
        top: 200px;
    }
    /* span样式大小为50px,在div右侧占50px,在页面中显示 */
    .wrapper span {
        width: 50px;
        height: 80px;
        background: red;
        position: absolute;
        right: -50px;
        top: 0px;
    }
</style>

<div class="wrapper">
    <span></span>
</div>

<script>
    var timer = null;
    // 将div选中
    var oDiv = document.getElementsByClassName('wrapper')[0];
    // 鼠标移入事件,鼠标移入后,将div移动到0的位置
    oDiv.onmouseenter = function (){
        startMove(this, 0);
    }
    // 鼠标移出后,将div移动回-400位置隐藏
    oDiv.onmouseleave = function (){
        startMove(this, -400);
    }

function startMove(dom, target){
    clearInterval(timer);
    var iSpeed = null;
    timer = setInterval(function(){
        iSpeed = (target - oDiv.offsetLeft) / 7;
        iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
        if(oDiv.offsetLeft == target) {
            clearInterval(timer);
        }else{
            oDiv.style.left = oDiv.offsetLeft + iSpeed + 'px';
        }
    }, 30);
}
</script>

多物体运动

<style>
    div {
        width: 100px;
        height: 100px;
        background: red;
        opacity: 1;    /* 不透明度 */
        margin-bottom: 100px;
    }
</style>
<div></div>
<div></div>
<div></div>
<script>
    var timer = null;
    var oDivArray = document.getElementsByTagName('div');

    for (var i = 0; i < oDivArray.length; i++) {
        oDivArray[i].onmouseenter = function () {
            startMove(this, 400);
        }
        oDivArray[i].onmouseleave = function () {
            startMove(this, 100);
        }
    }

    function getStyle(dom, attr){
        if(window.getComputedStyle){
            return window.getComputedStyle(dom, null)[attr];
        }else{
            return dom.currentStyle[attr];
        }
    }

    // 所有元素都缓冲直线运动
    function startMove (dom, target) {
        // 只清理当前dom的定时器,为每次传入的dom都分配一个定时器,可避免定时器被覆盖
        // 多物体运动时应注意定时器覆盖问题,为每个运动物体分别分配定时器,启用和清理时避免冲突
        clearInterval(dom.timer);
        var iSpeed = null,  // 速度
            iCur = null;    // 元素宽度
        dom.timer = setInterval(function () {
            // 获取元素宽度,返回值为100px,使用parseInt将其转化为整数100
            iCur = parseInt( getStyle(dom, 'width') );
            iSpeed = (target - iCur ) / 7;
            iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
            if (iCur == target) {
                clearInterval(dom.timer);
            }else{
                dom.style.width = iCur + iSpeed + 'px';
            }
        }, 30);
    }

    // 改进,元素可分别独自运动,缓冲向右运动、向下运动、透明度变化等
    function startMove (dom, attr, target) {
        clearInterval(dom.timer);
        var iSpeed = null,
            iCur = null;
        dom.timer = setInterval(function () {
            // 判断要更改的属性是否是透明度
            if (attr == 'opcity') {
                // 由于透明度的取值特殊,所以需要扩大100倍,计算后,再缩小100倍
                iCur = parseFloat( getStyle(dom, attr) ) * 100;
            }else {
                iCur = parseInt( getStyle(dom, attr) );
            }
            iSpeed = (target - iCur) / 7;
            iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
            if (iCur == target) {
                clearInterval(dom.timer);
            }
            // 若更改的是透明度,缩小100倍
            if (attr == 'opacity') {
                dom.style.opacity = ( iCur + iSpeed ) / 100;
            }else {
                // 更改元素位置
                dom.style[attr] = iCur + iSpeed + 'px';
            }
        }, 30);
    }
</script>

多物体多值运动封装版

<style>
    div {
        position: absolute;
        left: 0px;
        width: 100px;
        height: 100px;
        background: red;
        opacity: 1;
    }
    #topDiv {
        top: 200px;
    }
    #bottomDiv {
        top: 400px;
    }
</style>

<div id='topDiv'></div>
<div id='bottomDiv'></div>

<script>
    // 更改元素的多个值
    // width:100→400,height:100→400,left:0→200,top:200→300,opacity:1→0.5
    var oTopDiv = document.getElemensById('topDiv');
    var oBottomDiv = document.getElementsById('bottomDiv');
    oTopDiv.onclick = function () {
        startMove(this, {width: 400, height: 400, left: 200, top: 300, opacity: 50}, function () {
            startMove(oBottomDiv, {width: 400, height: 400, left: 200, top: 300, opacity: 50}, function () {
                alert('over');
            })
        })
    }

    // 获取元素某一样式
    function getStyle (dom, attr) {
        if (window.getComputedStyle) {
            return window.getComputedStyle(dom, null)[attr];
        }else {
            return dom.currentStyle[attr];
        }
    }

    // 操作对象,目标属性数组,回调函数
    function startMove (dom, attrObj, callback) {
        clearInterval(dom.timer);
        var iSpeed = null,
            iCur = null;
        dom.timer = setInterval(function () {
            var bStop = ture;
            for (var attr in attrObj) {
                if (attr == 'opacity') {
                    iCur = parseFloat( getStyle(dom, attr) ) * 100;
                }else {
                    iCur = parseInt( getStyle(dom, attr) );
                }
                iSpeed = (attrObj[attr] - iCur) / 7;
                iSpeed = iSpeed > 0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
                if (attr == 'opacity') {
                    dom.style.opacity = (iCur + iSpeed + 'px');
                }
                if(iCur != attrObj[attr]) {
                    bStop = false;
                }
            }
            if (bStop) {
                calerInterval(dom.timer);
                // 逻辑与运算,判断callback为一个函数的时候,才执行callback
                typeof callback == 'function' && callback();
            }
        })
    }
</script>
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-10-17 11:54:34  更:2021-10-17 11:55:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/9 21:59:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码