简单的拖拽排序

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>拖拽</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }
        ul {
            list-style: none;
        }
        #drag ul {
            width: 612px;
            margin: auto;
        }
        #drag ul li {
            width: 200px;
            height: 200px;
            float: left;
            border: 1px solid transparent;
        }
        #drag ul li img {
            width: 200px;
            height: 200px;
        }
    </style>
</head>
<body>
    <div id="drag">
        <ul>
            <li>
                <img src="images/1.jpg">
            </li>
            <li>
                <img src="images/2.jpg">
            </li>
            <li>
                <img src="images/3.jpg">
            </li>
            <li>
                <img src="images/4.jpg">
            </li>
            <li>
                <img src="images/5.jpg">
            </li>
            <li>
                <img src="images/6.jpg">
            </li>
            <li>
                <img src="images/7.jpg">
            </li>
            <li>
                <img src="images/8.jpg">
            </li>
            <li>
                <img src="images/9.jpg">
            </li>
        </ul>
    </div>
    <script type="text/javascript">
    let liItems = document.getElementsByTagName("li")  // 获取到每个li
    let zIndex = 1   //定义li的层级

    /**
     * 循环每个li获取他们的位置
     * offsetLeft
     * offsetTop
    */
    let distanceL = []  //  定义距离对象数组
    for(let i = 0; i<liItems.length; i++) {
        distanceL.push(
            {
                left: liItems[i].offsetLeft,
                top: liItems[i].offsetTop
            }
        )
    }

    //  把刚循环出来的位置值转换到图片的样式
    for(let i = 0; i<liItems.length; i++) {
        liItems[i].index = i;
        liItems[i].style.position = "absolute";
        liItems[i].style.left = distanceL[i].left + 'px';
        liItems[i].style.top = distanceL[i].top + 'px';
        liItems[i].style.margin = 0;
    }

    // 拖拽功能
    for (let i = 0; i < liItems.length; i++) {
        drag(liItems[i])
    }
    
    /**
     * 拖拽函数
    */
    function drag(obj) {
        // 给该对象绑定鼠标按下事件
        obj.onmousedown = function(ev) {
            ev = ev || window.event
            // 获取当前鼠标点击的位置
            let x = ev.clientX
            let y = ev.clientY

            // 获取当前图片的位置
            let left = this.offsetLeft
            let top = this.offsetTop

            // 设置li的层级不断往上加
            this.style.zIndex = zIndex++

            // 移动过程中
            document.onmousemove = function(ev) {
                ev = ev || window.event  
                
                // 获取移动中的位置,减去点击时候的位置,再加上图片原来的位置
                let moveLeft = ev.clientX - x + left
                let moveTop = ev.clientY - y + top
                obj.style.left = moveLeft + "px"
                obj.style.top = moveTop + "px"

                // 移动的时候先把边框去掉
                for(let i = 0; i< liItems.length; i++) {
                    liItems[i].style.border = "1px solid transparent"
                }

                // 检测碰撞
                let hit = nearLi(obj)
                if(hit) {
                    hit.style.border = "1px dashed red"
                }
            }

            //  当鼠标抬起的时候,需要把鼠标松开事件改为null
            document.onmouseup = function() {
                document.onmousemove = null;
                document.onmouseup = null;
                // 抬起来的时候再次获取碰撞的数据
                let oLi = nearLi(obj);
                if(oLi){
                    //  交换位置
                    animate(obj, {left: distanceL[oLi.index].left, top: distanceL[oLi.index].top},10, 0.08);
                    animate(oLi, {left: distanceL[obj.index].left, top: distanceL[obj.index].top},10, 0.08);
                    //  清除交换的边框
                    oLi.style.border = "1px solid transparent";
                    // 交换索引
                    let temp = obj.index;
                    obj.index = oLi.index;
                    oLi.index = temp;
                }else{
                    animate(obj, {left: distanceL[obj.index].left, top: distanceL[obj.index].top},10, 0.08);
                    // obj.style.left = arr[obj.index].left+"px";
                    // obj.style.top = arr[obj.index].top+"px";
                }

            }

            //返回false是为了屏蔽h5中图片标签<img>默认的拖拽事件
            return false;
        }
    }



    //  计算最小距离
    function nearLi(obj) {
        let n = 10000000000;
        let hit = '';
        for (let i = 0; i < liItems.length; i++) {
            if (obj != liItems[i] && impact(obj, liItems[i])) {
                // 计算碰撞的li距离
                let c = distance(obj, liItems[i]);
                if (c < n) {
                    n = c;
                    hit = liItems[i];
                }
            }
        }
        return hit;
    }

    //  碰撞检查
    function impact(obj1, obj2) {
        //对象1的各各边距 
        let left1 = obj1.offsetLeft; //左边距
        let top1 = obj1.offsetTop; //上边距
        let right1 = left1 + obj1.offsetWidth; //对象右边距离屏幕左边的距离
        let bottom1 = top1 + obj1.offsetHeight; //对象下边距离屏幕顶端的距离
        //对象2的各各边距
        let left2 = obj2.offsetLeft;
        let top2 = obj2.offsetTop;
        let right2 = left2 + obj2.offsetWidth;
        let bottom2 = top2 + obj2.offsetHeight;

        if (right1 <= left2 || bottom1 <= top2 || left1 >= right2 || top1 >= bottom2) {
            //  console.log("不成功")  // 不成功           
            return false;
        } else {
            //  console.log("成功")  //成功           
            return true;
        }
    }

    //  勾股定理计算斜边
    function distance(obj1, obj2) {
        let a = obj1.offsetLeft - obj2.offsetLeft;
        let b = obj1.offsetTop - obj2.offsetTop;
        return Math.sqrt(a * a + b * b);
    }

    function animate(obj, json, interval, sp, fn) {
        clearInterval(obj.timer);

        function getStyle(obj, arr) {
            if(obj.currentStyle){
                return obj.currentStyle[arr];    //针对ie
            } else {
                return document.defaultView.getComputedStyle(obj, null)[arr]; 
            }
        }
        obj.timer = setInterval(function(){
            let flag = true;
            for(let arr in json) {
                let icur = 0;
                //k++;
                if(arr == "opacity") {
                    icur = Math.round(parseFloat(getStyle(obj, arr))*100);
                } else {
                    icur = parseInt(getStyle(obj, arr));
                }
                let speed = (json[arr] - icur) * sp;
                speed = speed > 0 ? Math.ceil(speed): Math.floor(speed);
                if(icur != json[arr]){
                    flag = false;
                } 
                if(arr == "opacity"){
                    obj.style.filter = "alpha(opacity : '+(icur + speed)+' )";
                    obj.style.opacity = (icur + speed)/100;
                }else {
                    obj.style[arr] = icur + speed + "px";
                }
            }

            if(flag){
                clearInterval(obj.timer);
                if(fn){
                    fn();
                }
            }
        },interval);
    }
    </script>
</body>
</html>```

[可以看码云地址](https://gitee.com/jiang_wei_hao/tuozhuai.git)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值