随手笔记10-拖拽效果-碰撞检测-简单封装动画函数

一、拖拽效果

分析:
1.拖拽效果必须鼠标按下(mousedown),切鼠标移动(mousemove )执行代码,鼠标弹起(mouseup)解除事件
2.鼠标的坐标减去 鼠标在盒子内的坐标, 才是拖拽目标真正要移动的位置
3.鼠标移动和弹起事件如果加给小盒子,那么在快速移动鼠标的时候会无法解绑事件,所以为了用户体验度,把这两个事件加给文档(document)
4.判断物体移动边界,小盒子最大移动距离=父元素(这里用当前窗口位置)-小盒子的宽高,然后分别判断他们最大的移动距离,针对边界值分别进行处理
5.如果拖拽目标是img,要阻止浏览器的默认行为,这里用return false;发现不兼容IE低版本,利用全局捕获解决(setCapture)
6.检测碰撞:

  • 这里的思路是,找出拖拽目标移动的安全区,然后利用反证的思想,对碰撞区作处理
  • 红色的盒子是拖拽目标,绿色盒子是碰撞区,其余者为安装区
  • 如果L1的值大于R2的值那么拖拽目标就处于安全区,
  • 如果T1的值大于B2的值那么拖拽目标就处于安全区,依此类推,可以找出安全区范围,利用if()else()语句,else就是碰撞区

在这里插入图片描述

css代码

 <style>
        * {
            padding: 0;
            margin: 0;
        }

        #box {
            width: 150px;
            height: 150px;
            background: red;
            position: absolute;
        }

        #two {
            width: 200px;
            height: 200px;
            background: green;
            position: absolute;
            top: 200px;
            left: 600px;
        }
<body>
    <div id="box"></div>
    <div id="two"></div>
 </body>

js部分

<script>
        var o = document.getElementById('box');//移动的物体
        var box = document.getElementById('two');//被碰撞物体
        var vH = document.documentElement.clientHeight;//视图的高度
        var vW = document.documentElement.clientWidth;//视图的宽度

        //添加鼠标按下事件
        o.onmousedown = function (e) {
            e = e || window.event;
            //鼠标距离物体的相对位置(left,top)
            var disX = e.clientX - this.offsetLeft,
                disY = e.clientY - this.offsetTop;

            //计算被碰撞物体的位置
            var L2 = box.offsetLeft,
                T2 = box.offsetTop,
                R2 = L2 + box.offsetWidth,
                B2 = T2 + box.offsetHeight;

            //判断,若是在低版本IE上,为物体添加全局捕获
            if (o.setCapture) {
                o.setCapture();
            }

            //鼠标移动
            document.onmousemove = function (e) {
                e = e || window.event;
                var x = e.clientX - disX;//物体位置=鼠标的位置-鼠标相对于物体的位置
                var y = e.clientY - disY;//物体位置

                //判断边界问题
                if (x < 0) {
                    x = 0;//最左边
                } else if (x > vW - o.offsetWidth) {
                    x = vW - o.offsetWidth;//最右边
                }

                if (y < 0) {
                    y = 0;//最上边
                } else if (y > vH - o.offsetHeight) {
                    y = vH - o.offsetHeight;
                }

                //计算碰撞逻辑中,移动物体的位置
                var L1 = x,
                    T1 = y,
                    R1 = L1 + o.offsetWidth,
                    B1 = T1 + o.offsetHeight;
                //判断碰撞
                if (L1 > R2 || T1 > B2 || R1 < L2 || B1 < T2) {
                    box.style.background = 'green';
                } else {      //碰撞区域
                    box.style.background = "orange";
                }

                //在鼠标移动过程中,修改物体的位置
                o.style.left = x + "px";
                o.style.top = y + 'px';
            };

            //鼠标抬起
            document.onmouseup = function () {
                // console.log('up');
                document.onmousemove = null;
                document.onmouseup = null;
                //释放全局捕获
                if (o.releaseCapture) {
                    o.releaseCapture();
                }
            };
            return false;//拦截浏览器的默认行为
        };
    </script>

二、动画函数的封装

核心原理,通过定时器不断改变目标对象属性的值
核心公式:
步长(速度)=(目标位置-当前位置)/10(系数,为了改变透明度这里用100)
speed = (target - cur) / 100;

//获取样式 解决getComputedStyle的兼容问题
function getStyle(obj, attr) {
    if (getComputedStyle) { //标准浏览器
        return getComputedStyle(obj, null)[attr];
    }
    return obj.currentStyle[attr]; //IE8之下
}

//obj目标对象,attr要改变的属性,target目标位置
function move(obj, attr, target) {
	//执行之前先清除上一次的定时器
    clearInterval(obj.timer);
    //启动定时器,为对象新增属性timer,用来保存定时器编号
    obj.timer = setInterval(function() {
        var cur = getStyle(obj, attr); //动画执行时,每一次的最新值
        var speed; //速度
        if (attr == 'opacity') {
            speed = (target - cur) / 100; //放大速度系数  100   
        } else {
            cur = parseInt(cur); //当前位置    
            speed = (target - cur) / 10; //速度
            //速度小于0,向左移动,向下取整才可以;速度大于0,向右移动,向上取整
            speed = speed > 0 ? Math.ceil(speed) : Math.floor(speed); //最后的时候,速度小于1,向上取整1
        }
		//到达目标位置停止的定时器
        if (cur == target) {
            clearInterval(t);
        }
        if (attr == "opacity") { //修改透明度
            obj.style.opacity = parseFloat(cur) + speed;
        } else {
            obj.style[attr] = cur + speed + "px";
        }
    }, 30);
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个爱编程的男孩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值