JS实现图片拖拽交换效果


Posted in Javascript onNovember 30, 2018

JS实现图片拖拽交换效果,供大家参考,具体内容如下

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

实现要点

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

注意点

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

小技巧

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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
Jquery 滑入滑出效果实现代码
Mar 27 Javascript
Jquery实现鼠标移上弹出提示框、移出消失思路及代码
May 19 Javascript
使用JavaScript修改浏览器URL地址栏的实现代码
Oct 21 Javascript
jquery组件WebUploader文件上传用法详解
Oct 23 Javascript
Bootstrap实现渐变顶部固定自适应导航栏
Aug 27 Javascript
JavaScript正则表达式和级联效果
Sep 14 Javascript
JS实现websocket长轮询实时消息提示的效果
Oct 10 Javascript
Node.js搭建小程序后台服务
Jan 03 Javascript
Vue绑定内联样式问题
Oct 17 Javascript
koa2实现登录注册功能的示例代码
Dec 03 Javascript
IE浏览器下JS脚本提交表单后,不能自动提示问题解决方法
Jun 04 Javascript
vue 使用 canvas 实现手写电子签名
Mar 06 Javascript
Vue+Webpack完美整合富文本编辑器TinyMce的方法
Nov 30 #Javascript
jQuery实现网页拼图游戏
Apr 22 #jQuery
vue 双向数据绑定的实现学习之监听器的实现方法
Nov 30 #Javascript
基于jquery实现九宫格拼图小游戏
Nov 30 #jQuery
微信小程序canvas.drawImage完全显示图片问题的解决
Nov 30 #Javascript
vue 实现左右拖拽元素并且不超过他的父元素的宽度
Nov 30 #Javascript
微信小程序实现保存图片到相册功能
Nov 30 #Javascript
You might like
php类的定义与继承用法实例
2015/07/07 PHP
php获取英文姓名首字母的方法
2015/07/13 PHP
THINKPHP截取中文字符串函数实例代码
2017/03/20 PHP
HTML node相关的一些资料整理
2010/01/01 Javascript
JavaScript中清空数组的三种方法分享
2011/04/07 Javascript
jquery 结合C#后台的数组对文章的关键字自动添加链接的代码
2011/07/15 Javascript
JavaScript将Table导出到Excel实现思路及代码
2013/03/13 Javascript
jquery图片轮播插件仿支付宝2013版全屏图片幻灯片
2014/04/03 Javascript
JavaScript两种跨域技术全面介绍
2014/04/16 Javascript
JavaScript中实现单体模式分享
2015/01/29 Javascript
javaScript的函数对象的声明详解
2015/02/06 Javascript
JS实现超精简响应鼠标显示二级菜单代码
2015/09/12 Javascript
JavaScript对象数组排序函数及六个用法
2015/12/23 Javascript
基于JS组件实现拖动滑块验证功能(代码分享)
2016/11/18 Javascript
树结构之JavaScript
2017/01/24 Javascript
jquery mobile实现可折叠的导航按钮
2017/03/11 Javascript
详解如何用webpack打包一个网站应用项目
2017/07/12 Javascript
layui从数据库中获取复选框的值并默认选中方法
2018/08/15 Javascript
jQuery 同时获取多个标签的指定内容并储存为数组
2018/11/20 jQuery
微信小程序scroll-view点击项自动居中效果的实现
2020/03/25 Javascript
vue 重塑数组之修改数组指定index的值操作
2020/08/09 Javascript
Python3实现的简单验证码识别功能示例
2018/05/02 Python
Python for循环及基础用法详解
2019/11/08 Python
使用python快速在局域网内搭建http传输文件服务的方法
2019/11/14 Python
Python高级特性——详解多维数组切片(Slice)
2019/11/26 Python
python给图像加上mask,并提取mask区域实例
2020/01/19 Python
Python加速程序运行的方法
2020/07/29 Python
python matplotlib库的基本使用
2020/09/23 Python
CSS3关于z-index不生效问题的解决
2020/02/19 HTML / CSS
计算机本科生自荐信
2013/10/15 职场文书
大学生军训自我鉴定
2014/02/12 职场文书
生日宴会主持词
2014/03/20 职场文书
《富饶的西沙群岛》教学反思
2014/04/09 职场文书
农村文化活动总结
2014/08/28 职场文书
民主生活会主持词
2015/07/01 职场文书
运动会报道稿大全
2015/07/23 职场文书