JS实现图片拖拽交换效果

JS实现图片拖拽交换效果

WEB前端javascript企业实战班 公开课,用JS实现了图片拖拽交换的目的;感谢老师的讲解。

实现要点

  • 鼠标点击onmousedown:获取鼠标在页面上可视区域的位置(clientX, clientY)和元素外边框距已定位父元素容器的位置(offsetLeft,offsetTop);
  • 鼠标移动onmousemove: 获取鼠标在页面上可视区域的位置(clientX, clientY),并实时改变目标元素位置;进行碰撞检测,同时计算被碰撞元素与目标元素中心点距离,将距离最小的定位交换元素;
  • 鼠标释放onmouseup: 进行元素交换

注意点

  • 排除没有碰撞成功的情况,进行特殊讨论;
  • 覆盖html5原有的图片拖拽功能,通过return false返回;
  • 交换时同时勿忘记交换图片的索引;

小技巧

  • 进行碰撞检测时,可以进行逆向思维,检测未碰撞的情况,即判断目标元素是否超过碰撞元素的边界(如:目标元素的右侧是否超过被碰撞元素的左侧)
  • 计算元素中心位置时,可以改为计算元素左上角之间的距离,从而转变为计算 (offsetLeft1,offsetTop1) (offsetLefti , offsetTopi) 的距离,以简化计算;

实现

HTML

    <div id="photo">
        <ul>
            <li><img src="" alt=""></li>
            <li><img src="" alt=""></li>
            <li><img src="" alt=""></li>
            <li><img src="" alt=""></li>
            <li><img src="" alt=""></li>
            <li><img src="" alt=""></li>
            <li><img src="" alt=""></li>
            <li><img src="" alt=""></li>
            <li><img src="" alt=""></li>
        </ul>
    </div>

CSS

* {
            margin:0;
            padding: 0;
        }
        body {
            user-select: none;   /*阻止文本选中*/
        }
        #photo {
            width: 600px;
            height: 600px;
            border: 2px solid #000;
            margin: 20px auto;
        }
        #photo ul li {
            list-style:none;
            width: 180px;
            height: 180px;
            margin: 10px;
            float: left;
        }
        #photo ul li:hover {
            background: #c0c;
        }
        #photo ul li img {
            width: 180px;
            height: 180px;
            border: 1px solid #ccc;
        }

JS

var photo = document.getElementById("photo");
        var oUl = photo.getElementsByTagName("ul")[0];
        var aLi = oUl.getElementsByTagName("li");
        var z = 2;

        var arr = [];
        for (var i = 0; i < aLi.length; i++) {
            arr.push([aLi[i].offsetLeft, aLi[i].offsetTop]);
        }

        for (var i = 0; i < aLi.length; i++) {
            aLi[i].style.position = "absolute";
            aLi[i].style.left = arr[i][0] + "px";
            aLi[i].style.top = arr[i][1] + "px";
            aLi[i].style.margin = 0;
        }

        for (var i = 0; i < aLi.length; i++) {
            aLi[i].index = i;
            drag(aLi[i]);
        }

        function drag(obj) {
            obj.onmousedown = function(ev) {
                ev = ev || window.ev;
                var x = ev.clientX;
                var y = ev.clientY;

                var l = obj.offsetLeft;
                var t = obj.offsetTop;

                this.style.zIndex = z++;

                document.onmousemove = function(ev) {
                    ev = ev || window.ev;
                    var _left = ev.clientX - x + l;
                    var _top = ev.clientY - y + t;
                    obj.style.left = _left + "px";
                    obj.style.top = _top + "px";

                    var li = near(obj);
                    for (var i = 0; i < aLi.length; i++) {
                        aLi[i].style.background = "";
                    }
                    if (li) {
                        li.style.background = "#DF971F";
                    }
                }
                document.onmouseup = function() {
                    document.onmousemove = null;
                    document.onmousedown = null;

                    var nearLi = near(obj);
                    var tmp = 0;
                    if (nearLi) {
                        move(nearLi, {left:arr[obj.index][0], top:arr[obj.index][1]});
                        move(obj, {left:arr[nearLi.index][0], top:arr[nearLi.index][1]});
                        nearLi.style.background = "";

                        tmp = obj.index;
                        obj.index = nearLi.index;
                        nearLi.index = tmp;
                    } else {
                        move(obj, {left:arr[obj.index][0], top:arr[obj.index][1]});
                    }
                }
                return false;
            }
        } 
        function impact(obj1, obj2) {
            var L1 = obj1.offsetLeft;
            var R1 = obj1.offsetLeft + obj1.offsetWidth;
            var T1 = obj1.offsetTop;
            var B1 = obj1.offsetTop + obj1.offsetHeight;

            var L2 = obj2.offsetLeft;
            var R2 = obj2.offsetLeft + obj2.offsetWidth;
            var T2 = obj2.offsetTop;
            var B2 = obj2.offsetTop + obj2.offsetHeight;

            if (L2 > R1 || T2 > B1 || R2 < L1 || B2 < T1) {
                return false;
            } else {
                return true;
            }
        }
        function near(obj) {
            var tmp = 5000;
            var oLi = '';
            for (var i = 0; i < aLi.length; i++) {
                if (impact(obj, aLi[i]) && obj != aLi[i]) {
                    var c = disCalc(obj, aLi[i]);

                    if (tmp > c) {
                        tmp = c;
                        oLi = aLi[i];
                    }
                }
            }
            return oLi;
        }
        function disCalc(obj1, obj2) {
            var x = obj1.offsetLeft - obj2.offsetLeft; 
            var y = obj1.offsetTop - obj2.offsetTop;
            return Math.sqrt(x * x + y * y);
        }

move.js


function move(obj, json, endFn) {
    clearInterval(obj.timer);
    obj.timer = setInterval(function() {
        var bBtn = true;
        for (var attr in json) {
            var iCur = 0;
            if (attr == 'opacity') {
                if (Math.round(parseFloat(getStyle(obj,attr)) * 100) == 0) {
                    iCur = Math.round(parseFloat(getStyle(obj,attr)) * 100);
                } else {
                    iCur = Math.round(parseFloat(getStyle(obj,attr)) * 100) || 100;
                }   
            } else {
                iCur = parseInt(getStyle(obj,attr)) || 0;
            }

            var iSpeed = (json[attr] - iCur) / 8;
            iSpeed = iSpeed >0 ? Math.ceil(iSpeed) : Math.floor(iSpeed);
            if (iCur != json[attr]) {
                bBtn = false;
            }

            if (attr == 'opacity') {
                obj.style.filter = 'alpha(opacity=' +(iCur + iSpeed)+ ')';
                obj.style.opacity = (iCur + iSpeed) / 100;
            }
            else {
                obj.style[attr] = iCur + iSpeed + 'px';
            }
        }

        if (bBtn) {
            clearInterval(obj.timer);
            if (endFn) {
                endFn.call(obj);
            }
        }   
    }, 30);
}


function getStyle(obj, attr) {  
    if (obj.currentStyle) {
        return obj.currentStyle[attr];
    } else {
        return getComputedStyle(obj, false)[attr];
    }
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值