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实现无刷新更新数据的详细步骤 asp
Dec 26 Javascript
JavaScript中发布/订阅模式的简单实例
Nov 05 Javascript
JS实现网页上随机产生超链接地址的方法
Nov 09 Javascript
jquery拖拽效果完整实例(附demo源码下载)
Jan 14 Javascript
js实现页面刷新滚动条位置不变
Nov 27 Javascript
JS实现的验证身份证及获取地区功能示例
Jan 16 Javascript
Vue中计算属性computed的示例解读
Jul 26 Javascript
原生javascript实现的全屏滚动功能示例
Sep 19 Javascript
BACKBONE.JS 简单入门范例
Oct 17 Javascript
详解Vue单元测试Karma+Mocha学习笔记
Jan 31 Javascript
jquery实现直播弹幕效果
Nov 28 jQuery
vue实现把接口单独存放在一个文件方式
Aug 13 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中is_file不能替代file_exists的理由
2014/03/04 PHP
刷新PHP缓冲区为你的站点加速
2015/10/10 PHP
学习php设计模式 php实现备忘录模式(Memento)
2015/12/09 PHP
php使用正则验证中文
2016/04/06 PHP
php通过两层过滤获取留言内容的方法
2016/07/11 PHP
php利用ob_start()清除输出和选择性输出的方法
2018/01/18 PHP
详解PHP版本兼容之openssl调用参数
2018/07/25 PHP
THINKPHP5.1 Config的配置与获取详解
2020/06/08 PHP
使用EXT实现无刷新动态调用股票信息
2008/11/01 Javascript
JS小功能(列表页面隔行变色)简单实现
2013/11/28 Javascript
jQuery实现的图文高亮滚动切换特效实例
2015/08/10 Javascript
浅谈JavaScript超时调用和间歇调用
2015/08/30 Javascript
js中的关联数组与普通数组详解
2016/07/27 Javascript
详谈jQuery中的一些正则匹配表达式
2017/03/08 Javascript
vue快捷键与基础指令详解
2017/06/01 Javascript
WebStorm ES6 语法支持设置&amp;babel使用及自动编译(详解)
2017/09/08 Javascript
vue 实现类似淘宝星级评分的示例
2018/03/01 Javascript
React key值的作用和使用详解
2018/08/23 Javascript
微信小程序设置全局请求URL及封装wx.request请求操作示例
2019/04/02 Javascript
vue实现户籍管理系统
2020/05/29 Javascript
Python查看多台服务器进程的脚本分享
2014/06/11 Python
python去除空格和换行符的实现方法(推荐)
2017/01/04 Python
python用Pygal如何生成漂亮的SVG图像详解
2017/02/10 Python
Python 爬虫图片简单实现
2017/06/01 Python
python实现AdaBoost算法的示例
2020/10/03 Python
利用异或运算实现两个无符号数的加法运算
2013/12/20 面试题
学校交通安全责任书
2014/08/25 职场文书
2015年招聘工作总结
2014/12/12 职场文书
教师考核评语大全
2014/12/31 职场文书
施工员岗位职责
2015/02/10 职场文书
预备党员个人总结
2015/02/14 职场文书
500字小学生检讨书
2015/02/19 职场文书
2016年3月份红领巾广播稿
2015/12/21 职场文书
如何开发一个渐进式Web应用程序PWA
2021/05/10 Javascript
基于PostgreSQL/openGauss 的分布式数据库解决方案
2021/12/06 PostgreSQL
一起来学习Python的元组和列表
2022/03/13 Python