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动画效果类封装代码
Aug 28 Javascript
JSON 编辑器实现代码
Dec 06 Javascript
javascript 获取url参数和script标签中获取url参数函数代码
Jan 22 Javascript
Html中JS脚本执行顺序简单举例说明
Jun 19 Javascript
Javascript中获取出错代码所在文件及行数的代码
Sep 23 Javascript
jQuery阻止冒泡和HTML默认操作
Nov 17 Javascript
jquery简单实现网页层的展开与收缩效果
Aug 07 Javascript
JS代码实现根据时间变换页面背景效果
Jun 16 Javascript
Node.js dgram模块实现UDP通信示例代码
Sep 26 Javascript
详解vue.js数据传递以及数据分发slot
Jan 20 Javascript
详解ES6 Promise的生命周期和创建
Aug 18 Javascript
JavaScript 判断数据类型的4种方法
Sep 11 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中文字符串截取函数
2013/11/12 PHP
php中curl使用指南
2015/02/05 PHP
php实现的递归提成方案实例
2015/11/14 PHP
基于jQuery+HttpHandler实现图片裁剪效果代码(适用于论坛, SNS)
2011/09/02 Javascript
getElementByIdx_x js自定义getElementById函数
2012/01/24 Javascript
javascript jscroll模拟html元素滚动条
2012/12/18 Javascript
7个JS基础知识总结
2014/03/05 Javascript
javascript中加var和不加var的区别 你真的懂吗
2016/01/06 Javascript
前端弹出对话框 js实现ajax交互
2016/09/09 Javascript
JS取模、取商及取整运算方法示例
2016/10/13 Javascript
JS定时器实现数值从0到10来回变化
2016/12/09 Javascript
js实现鼠标左右移动,图片也跟着移动效果
2017/01/25 Javascript
Angular2生命周期钩子函数的详细介绍
2017/07/10 Javascript
vue组件父子间通信详解(三)
2017/11/07 Javascript
AngularJS监听ng-repeat渲染完成的两种方法
2018/01/16 Javascript
JS滚轮控制图片缩放大小和拖动的实例代码
2018/11/20 Javascript
js中async函数结合promise的小案例浅析
2019/04/14 Javascript
vue 使用外部JS与调用原生API操作示例
2019/12/02 Javascript
Vue自定义全局弹窗组件操作
2020/08/11 Javascript
pyv8学习python和javascript变量进行交互
2013/12/04 Python
深入解析Python中的lambda表达式的用法
2015/08/28 Python
Python和Perl绘制中国北京跑步地图的方法
2016/03/03 Python
Tensorflow简单验证码识别应用
2017/05/25 Python
matplotlib subplots 调整子图间矩的实例
2018/05/25 Python
Django使用中间件解决前后端同源策略问题
2019/09/02 Python
Django集成celery发送异步邮件实例
2019/12/17 Python
python通过文本在一个图中画多条线的实例
2020/02/21 Python
如何将json数据转换为python数据
2020/09/04 Python
Python爬虫简单运用爬取代理IP的实现
2020/12/01 Python
一款纯css3实现的颜色渐变按钮的代码教程
2014/11/12 HTML / CSS
中国医药集团国药在线:国药网
2017/02/06 全球购物
为数据库创建索引都需要注意些什么
2012/07/17 面试题
大专毕业生自我鉴定
2013/11/21 职场文书
2014年安全员工作总结
2014/11/13 职场文书
2014年机关后勤工作总结
2014/12/16 职场文书
介绍信范文大全
2015/05/07 职场文书