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 相关文章推荐
javascript[js]获取url参数的代码
Oct 17 Javascript
javascript 通用简单的table选项卡实现
May 07 Javascript
Ext JS 4实现带week(星期)的日期选择控件(实战一)
Aug 21 Javascript
JavaScript事件处理的方式(三种)
Apr 26 Javascript
微信小程序 Tab页切换更新数据
Jan 05 Javascript
layui radio单选限制下一个radio单选的实例
Sep 03 Javascript
jquery轻量级数字动画插件countUp.js使用详解
Oct 17 jQuery
js实现图片无缝循环轮播
Oct 28 Javascript
JavaScript实现移动端弹窗后禁止滚动
May 25 Javascript
Jquery使用each函数实现遍历及数组处理
Jul 14 jQuery
详解vue中v-on事件监听指令的基本用法
Jul 22 Javascript
解决vue+webpack项目接口跨域出现的问题
Aug 10 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
WordPress开发中用于获取近期文章的PHP函数使用解析
2016/01/05 PHP
PHP上传图片、删除图片简单实例
2016/11/12 PHP
在Javascript中为String对象添加trim,ltrim,rtrim方法
2006/09/22 Javascript
JavaScript中使用正则匹配多条,且获取每条中的分组数据
2010/11/30 Javascript
尝试在让script的type属性等于text/html
2013/01/15 Javascript
ExtJS下 Ext.Direct加载和提交过程排错小结
2013/04/02 Javascript
清除div下面的所有标签的方法
2014/02/17 Javascript
js触发select onchange事件的小技巧
2014/08/05 Javascript
JavaScript中获取样式的原生方法小结
2014/10/08 Javascript
浅谈Javascript变量作用域问题
2014/12/16 Javascript
JQuery实现鼠标滚轮滑动到页面节点
2015/07/28 Javascript
jQuery带时间的日期控件代码分享
2015/08/26 Javascript
js实现将json数组显示前台table中
2017/01/10 Javascript
Node.js 8 中的重要新特性
2017/06/28 Javascript
Vue props 单向数据流的实现
2018/11/06 Javascript
bootstrap table插件动态加载表头
2019/07/19 Javascript
JavaScript代码压缩工具UglifyJS和Google Closure Compiler的基本用法
2020/04/13 Javascript
Python通过select实现异步IO的方法
2015/06/04 Python
Python中使用OpenCV库来进行简单的气象学遥感影像计算
2016/02/19 Python
Python实现简单网页图片抓取完整代码实例
2017/12/15 Python
CentOS6.9 Python环境配置(python2.7、pip、virtualenv)
2019/05/06 Python
python爬虫-模拟微博登录功能
2019/09/12 Python
Python字符串中删除特定字符的方法
2020/01/15 Python
Python Pillow(PIL)库的用法详解
2020/09/19 Python
html5利用canvas绘画二级树形结构图的示例
2017/09/27 HTML / CSS
如何避免常见的6种HTML5错误用法
2017/11/06 HTML / CSS
解析浏览器的一些“滚动”行为鉴赏
2019/09/16 HTML / CSS
Kathmandu新西兰官网:新西兰户外运动品牌
2019/07/27 全球购物
对外汉语专业大学生职业生涯规划书
2014/10/11 职场文书
2015年团支部工作总结
2015/04/03 职场文书
人工作失职检讨书
2015/05/05 职场文书
Python djanjo之csrf防跨站攻击实验过程
2021/05/14 Python
MySQL 5.7常见数据类型
2021/07/15 MySQL
python实现对doc、txt、xls等文档的读写操作
2022/04/02 Python
vue实现列表拖拽排序的示例代码
2022/04/08 Vue.js
Win11 PC上的Outlook搜索错误怎么办?
2022/07/15 数码科技