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两种function的定义介绍及区别说明
May 02 Javascript
nullJavascript中创建对象的五种方法实例
May 07 Javascript
jQuery动态地获取系统时间实现代码
May 24 Javascript
Bootstrap Table使用心得总结
Nov 29 Javascript
angular实现表单验证及提交功能
Feb 01 Javascript
jquery实现一个全局计时器(商城可用)
Jun 30 jQuery
Vue2.0父组件与子组件之间的事件发射与接收实例代码
Sep 19 Javascript
详解VUE中常用的几种import(模块、文件)引入方式
Jul 03 Javascript
vuex实现像调用模板方法一样调用Mutations方法
Nov 06 Javascript
VUE实现Studio管理后台之鼠标拖放改变窗口大小
Mar 04 Javascript
在Vue中获取自定义属性方法:data-id的实例
Sep 09 Javascript
Vue3中的Refs和Ref详情
Nov 11 Vue.js
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中COOKIES使用示例
2015/07/26 PHP
php函数传值的引用传递注意事项分析
2016/06/25 PHP
kindeditor 加入七牛云上传的实例讲解
2017/11/12 PHP
js+FSO遍历文件夹下文件并显示
2007/03/07 Javascript
jquery中常用的SET和GET
2009/01/13 Javascript
SeaJS 与 RequireJS 的差异对比
2014/12/08 Javascript
jQuery解决input超多的表单提交
2015/08/10 Javascript
jQuery form插件的使用之处理server返回的JSON, XML,HTML数据
2016/01/26 Javascript
AngularJS基础 ng-value 指令简单示例
2016/08/03 Javascript
谈谈JavaScript的New关键字
2016/08/26 Javascript
AngularJS实现树形结构(ztree)菜单示例代码
2016/09/18 Javascript
ajax与json 获取数据并在前台使用简单实例
2017/01/19 Javascript
Vue2学习笔记之请求数据交互vue-resource
2017/02/23 Javascript
微信小程序 使用腾讯地图SDK详解及实现步骤
2017/02/28 Javascript
JS如何判断浏览器类型和详细区分IE各版本浏览器
2017/03/04 Javascript
JavaScript实现设置默认日期范围为最近40天的方法分析
2017/07/12 Javascript
原生JavaScript来实现对dom元素class的操作方法(推荐)
2017/08/16 Javascript
js/jQuery实现全选效果
2019/06/17 jQuery
详解在Angular4中使用ng2-baidu-map的方法
2019/06/19 Javascript
Python缩进和冒号详解
2016/06/01 Python
Golang与python线程详解及简单实例
2017/04/27 Python
python实现pdf转换成word/txt纯文本文件
2018/06/07 Python
python实现两个经纬度点之间的距离和方位角的方法
2019/07/05 Python
Django项目主urls导入应用中views的红线问题解决
2019/08/10 Python
python匿名函数lambda原理及实例解析
2020/02/07 Python
TensorFLow 变量命名空间实例
2020/02/11 Python
使用Django搭建网站实现商品分页功能
2020/05/22 Python
python实现代码审查自动回复消息
2021/02/01 Python
美国婴儿和儿童家具网上商店:ABaby.com
2018/07/02 全球购物
什么是makefile? 如何编写makefile?
2013/01/02 面试题
聚美优品励志广告词
2014/03/14 职场文书
2015秋季运动会通讯稿
2015/07/18 职场文书
公司员工宿舍管理制度
2015/08/03 职场文书
导游词之沈阳清昭陵
2019/12/28 职场文书
vue实现水波涟漪效果的点击反馈指令
2021/05/31 Vue.js
Pygame如何使用精灵和碰撞检测
2021/11/17 Python