30
2020
04

JS拖拽碰壁实现效果

实际情况下,一个物体默认具有重力效果。物体的重力效果是时时刻刻都在发生的,相当于定时器的每次运动,都有向下的匀加速运动

如果投掷速度不同,则运动速度也不相同。在碰壁的情况下,速度会有损耗,并且发生速度方向变化。最终,物体会落到地上

<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<style type="text/css">
#nav{
    list-style:none;
    padding: 0;
    margin: 0 50px 0;
    text-align:center;
    color:white;
    font-weight:bold;
    background-color: #25517A;
    cursor:pointer;
    overflow:hidden;
    width: 500px;
}    
.navItem{
    line-height: 30px;
    float:left;
    width:100px;
    text-decoration: none;
    color:inherit;
}
#navActive{
    width: 100px;
    height: 30px;
    background-color: rgba(0,0,0,0.3);
    position:absolute;
    margin-top: -30px;
    cursor:pointer;
}
</style>
</head>
<body>
<body>
<div id="test" style="height: 100px;width: 100px;border-radius:50%;background:pink;position:absolute;top:40px;left:0;"></div>
<script>
//声明元素投掷步长值
var stepX=0,stepY=0;
//默认情况下,也存在重力效果
collisionMove({
    obj:test,
    stepX:stepX,
    stepY:stepY
})
function getCSS(obj,style){
    if(window.getComputedStyle){
        return getComputedStyle(obj)[style];
    }
    return obj.currentStyle[style];
} 
//碰撞运动函数
function collisionMove(json){
    var obj = json.obj;
    var fn = json.fn;
    //声明x、y轴的当前值
    var curX = parseFloat(getCSS(obj,'left'));
    var curY = parseFloat(getCSS(obj,'top'));
    //声明x、y轴的步长值
    var stepX = json.stepX;
    var stepY = json.stepY;
       //声明元素的重要加速度
       var g = json.g || 3;
    //步长值默认值为10
    if(isNaN(Number(stepX))){
        stepX = 10;
    }else{
        stepX = Number(stepX);
    }
    if(isNaN(Number(stepY))){
        stepY = 10;
    }else{
        stepY = Number(stepY);
    }
    //声明x、y轴方向
    var dirX = json.dirX;
    var dirY = json.dirY;
    dirX = stepX > 0 ? '+' : '-';
    dirY = stepY > 0 ? '+' : '-';
    //声明offset宽高
    var offsetWidth = obj.offsetWidth;
    var offsetHeight = obj.offsetHeight;
    //声明元素活动区域宽高
    var activeWidth = json.activeWidth;
    var activeHeight = json.activeHeight;
    //元素获取区域宽高默认值为可视区域宽高
    activeWidth = Number(activeWidth) || document.documentElement.clientWidth;
    activeHeight = Number(activeHeight) || document.documentElement.clientHeight;
    //声明left、top样式值
    var left;
    var top;
    //声明减速系数
    var k = 0.8;
    //声明碰撞次数
    var i = 0;
    //清除定时器
    if(obj.timer){return;}
     //开启定时器
    obj.timer = setInterval(function(){
        //获取x、y轴的当前值
        curX = parseFloat(getCSS(obj,'left'));
        curY = parseFloat(getCSS(obj,'top'));
        //受到重力影响,更新步长值stepY
        stepY += g;
        //更新left、top值
        left = curX + stepX;
        top = curY + stepY;
        //右侧碰壁前一刻,步长大于剩余距离,且元素向右运动时
        if((left > activeWidth - offsetWidth) && (dirX == '+')){
            left = activeWidth - offsetWidth;
        }
        //左侧碰壁前一刻,步长大于剩余距离,且元素向左运动时
        if((Math.abs(stepX) > curX) && (dirX == '-')){
            left = curX;
        }
        //下侧碰壁前一刻,步长大于剩余距离,且元素向下运动时
        if((top > activeHeight - offsetHeight) && (dirY == '+')){
            top = activeHeight - offsetHeight;
        }
        //上侧碰壁前一刻,步长大于剩余距离,且元素向上运动时
        if((Math.abs(stepY) > curY) && (dirY == '-')){
            top = curY;
        }
        obj.style.left= left + 'px';
        obj.style.top = top + 'px';
        //左侧或右侧碰撞瞬间
        if(left == activeWidth - offsetWidth || left == curX){
            //x轴方向速度损耗,并发生方向变化
            stepX = -stepX * k;
        }
        //上侧或下侧碰撞瞬间
        if(top == activeHeight - offsetHeight || top == curY){
            //y轴方向速度损耗,并发生方向变化
            stepY = -stepY * k;
            //x轴方向速度损耗
            stepX = stepX * k;
        }
        //元素与地面碰撞10次后,则停止运动
        if(top == activeHeight - offsetHeight){
            i++;
            if(i== 10){
                clearInterval(obj.timer)
                obj.timer = 0;
                fn && fn.call(obj);
            }            
        }
        //更新运动方向
        dirX = stepX > 0 ? '+' : '-';
        dirY = stepY > 0 ? '+' : '-';
    },20);            
}    
//初始抛掷
test.onmousedown = function(e){
    e = e || event;
    //声明上一次mousemove事件的坐标位置
    var lastX2 = e.clientX;
    var lastY2 = e.clientY;
    //获取元素距离定位父级的x轴及y轴距离
    var x0 = this.offsetLeft;
    var y0 = this.offsetTop;
    //获取此时鼠标距离视口左上角的x轴及y轴距离
    var x1 = e.clientX;
    var y1 = e.clientY;
    //鼠标按下时,获得此时的页面区域
    var L0 = 0;
    var R0 = document.documentElement.clientWidth;
    var T0 = 0;
    var B0 = document.documentElement.clientHeight;
    //鼠标按下时,获得此时的元素宽高
    var EH = this.offsetHeight;
    var EW = this.offsetWidth;
    document.onmousemove = function(e){
        e = e || event;
        //获取此时鼠标距离视口左上角的x轴及y轴距离
        var x2 = e.clientX;
        var y2 = e.clientY; 
        stepX = x2 - lastX2;
        stepY = y2 - lastY2;  
        lastX2 = e.clientX;
        lastY2 = e.clientY;
        //计算此时元素应该距离视口左上角的x轴及y轴距离
        var X = x0 + (x2 - x1);
        var Y = y0 + (y2 - y1);
        /******范围限定*******/
        //获取鼠标移动时元素四边的瞬时值
        var L = X;
        var R = X + EW;
        var T = Y;
        var B = Y + EH;
        //在将X和Y赋值给left和top之前,进行范围限定
        //只有在范围内时,才进行相应的移动
        //如果脱离左侧范围,则left置L0
        if(L < L0){X = L0;}
        //如果脱离右侧范围,则left置为R0
        if(R > R0){X = R0 - EW;}
        //如果脱离上侧范围,则top置T0
        if(T < T0){Y = T0;}
        //如果脱离下侧范围,则top置为B0
        if(B > B0){Y = B0 - EH;}
        //将X和Y的值赋给left和top,使元素移动到相应位置
        test.style.left = X + 'px';
        test.style.top = Y + 'px';
    }
    document.onmouseup = function(e){
        e = e || event;
        var maxHeight = document.documentElement.clientHeight - test.offsetHeight;
        var maxWidth = document.documentElement.clientWidth - test.offsetWidth;
        //以设置的投掷速度来进行碰撞运动
        collisionMove({
            obj:test,
            stepX:stepX,
            stepY:stepY
        })
        //当鼠标抬起时,拖拽结束,则将onmousemove赋值为null即可
        document.onmousemove = null;
        //释放全局捕获
        if(test.releaseCapture){
            test.releaseCapture();
        }
    }
    //阻止默认行为
    return false;
    //IE8-浏览器阻止默认行为
    if(test.setCapture){
        test.setCapture();
    }
}
</script>
</body>
</html>

具体效果点上面的运行代码来看。静态效果图:

原文链接:https://www.qiquanji.com/post/8059.html

本站声明:网站内容来源于网络,如有侵权,请联系我们,我们将及时处理。

微信扫码关注

更新实时通知

« 上一篇 下一篇 »

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。