찾다
웹 프론트엔드JS 튜토리얼JavaScript는 PC 웹 페이지에서 드래그 앤 드롭 효과를 구현합니다_javascript 기술

몇 년 전 저는 부동산 웹사이트 프로젝트의 디자인과 개발에 참여했는데, 프로젝트 매니저의 요구 사항이 상대적으로 높기 때문에 부동산의 우수한 기능을 많이 언급했습니다. 다른 사람들의 우수한 디자인과 아이디어를 수집하고 싶었고, 그 당시의 디자인 초안과 기능 구현은 단순히 변경만 반복되었습니다. 오늘 얻은 좋은 효과는 다음 날로 미루어야 할 수도 있습니다. 그 얘기는 하지말고 오늘 설명드릴 사건에 대해서 얘기해보겠습니다.(광고는 전혀 의심되지 않습니다.) 약간의 광고비?), 제품 관리자가 특히 좋아하는 기능이 하나 있는데, 바로 다음과 같습니다.

이것은 현재 효과이며, 약간의 변경이 있을 수 있습니다. 원래 효과는 내부의 그림을 상하좌우로 드래그할 수 있고, 그러면 집에 표시되는 건물 번호도 그림과 함께 이동한다는 것입니다. time,js 능력이 부족해서 프로젝트 매니저의 요구사항을 충족하지 못했는데 나중에 프로젝트 매니저가 이 효과를 거부하고 다른 효과로 교체했습니다

프로젝트 매니저가 이런 효과를 원하지 않았음에도 불구하고, 그 당시 제 마음에 뭉클하게 남아서 지금도 잊혀지지 않습니다.

좋아, 이것이 오늘 이 블로그를 쓰는 나의 원래 의도입니다. 이런 종류의 드래그 효과를 얻고 싶지만 그것을 달성하는 방법을 모르는 학생들에게 아이디어를 제공할 수 있기를 바랍니다. 물론 드래그 앤 드롭을 구현하는 방법은 다양합니다. 여기서는 JavaScript로 한 가지 방법만 소개하고 그 원리를 천천히 이해하겠습니다!

자, 농담은 끝났습니다. 우선 드래그가 무엇인지 이해해야 합니다. 여러분도 알고 있고 저도 알고 있지만 그래도 설명하고 싶습니다.

드래그 앤 드롭은 마우스를 사용하여 페이지에서 드래그할 수 있습니다. 정확한 설명은 마우스를 컨테이너로 이동한 다음 마우스를 놓지 않도록 주의하세요. 그런 다음 마우스를 놓으면 컨테이너가 마우스를 따라갈 수 있습니다. 실제 예는 테이블 위에 상자가 있는 경우입니다. 상자. 손이 멈추면 상자가 멈춥니다. 치우세요. 상자가 움직이지 않습니다. 헤헤, 이해해요!

위 내용이 너무 말도 안된다고 생각하지 마세요. 여기서 많은 정보를 얻을 수 있습니다. 요약은 다음과 같습니다.

드래그 = 마우스 다운 + 마우스 이동 + 마우스 업

이렇게 드래그 앤 드롭 작업이 완료되었습니다. 그런데 이것이 드래그 앤 드롭의 원리라는 것이 밝혀졌습니다. 드래그 앤 드롭을 구현하려면 위의 세 가지 동작을 자연스럽게 구현하여 드래그 앤 드롭 효과를 시뮬레이션할 수 있습니다. . 이는 JavaScript의 구문에 해당합니다.

다음 3가지 작업을 구현하면 됩니다.

onmousedown, onmousemove, onmouseup

구현된 코드는 다음과 같아야 합니다.

obj.onmousedown = function(ev){
   obj.onmousemove = function(ev){
 
   } ;
   obj.onmouseup = function(ev){
   
   };
   
}

다음 두 액션을 왜 작성해야 할까요? 잘 생각해 봅시다. 첫 번째 단계의 일반적인 아이디어는 다음 단계에서 마우스로 개체를 이동시키는 방법을 고려하는 것입니다. 아이디어는 아마도 다음과 같을 것입니다:

먼저 개체를 이동하려면 왼쪽 및 위쪽 값을 조작해야 하기 때문에 개체의 위치를 ​​지정해야 합니다. 그런 다음 마우스 변위 자체에 거리가 있어야 합니다. 마우스가 움직인 것을 알 수 있습니다. 그러면 개체에 이 거리가 부여됩니다. 개체가 마우스와 같은 거리로 이동합니까? ㅎㅎ 아이디어가 좀 있고 귀엽네요~ 이제 문제는 마우스의 거리를 어떻게 구하느냐 입니다. 더 알고 싶으시면 박스 모델을 검토해 보세요. 여기서는 다루지 않겠습니다. 많은 마스터들도 관련 블로그를 가지고 있습니다. 제가 사용하는 블로그는 다음과 같습니다.

설명: 파란색 상자는 화면의 너비와 높이, 두꺼운 검은색 상자는 브라우저의 가시 영역의 너비와 높이(브라우저 축소 효과), 얇은 검은색 상자는 마우스로 드래그할 개체입니다. , 그림과 같이 마우스 좌표를 얻으려면 event.clientX, event.clientY를 사용하여 얻을 수 있습니다.

일반적인 계산 원리는 아래 그림을 참조하세요.

설명: 왼쪽은 초기 위치, 오른쪽은 대상 위치, 원점은 마우스 위치, 큰 검은색 상자는 브라우저에 표시되는 너비, 작은 검은색 상자는 드래그 개체, 상태를 확인하세요. 개체를 대상 위치로 드래그하고 마우스의 최종 위치를 얻은 다음 마우스와 개체의 차이를 뺀 다음 개체의 위쪽 및 왼쪽 값에 할당합니다. 마우스의 위치 차이를 얻은 다음 초기 위쪽 및 왼쪽 값에 차이를 추가할 수도 있습니다. 두 번째 종류도 가능합니다. 직접 시도해 보세요.

 obj.onmousedown = function(ev){
  var ev = ev || event;
  var disX = ev.clientX - this.offsetLeft,disY = ev.clientY - this.offsetTop;
 
  document.onmousemove = function(ev){
    var ev = ev || event;
    obj.style.left = ev.clientX - disX + 'px';
    obj.style.top = ev.clientY - disY + 'px';
  };
  document.onmouseup = function(ev){
    var ev = ev || event;
    document.onmousemove = document.onmouseup = null;
  };
}

这里说明一下:onmousemove和onmouseup之所以用document对象而不用obj对象,是因为如果用obj对象,鼠标在obj内部还好,如果在obj外面的话,拖拽会很怪异,你也可以改成obj体会一下,最后我们在鼠标弹起的时候将事件都清空;

上面的基本拖拽就算完成了,但是细心的同学一定会问,如果页面上有文字的话,拖拽物体会将文字选中,这效果岂不是怪怪的,没错,这是因为拖拽的时候触发了浏览器的默认选择事件,所以,在拖拽的时候,我们要清除这个默认事件,那怎么清除呢?

下面给一个兼容性写法:

if(ev.stopPropagation){
   ev.stopPropagation();
}else{
  ev.cancelBubble = true; //兼容IE
}
//简写成
ev.stopPropagation ? ev.stopPropagation() : ev.cancelBubble = true;

将上面的代码放在onmousedown下,鼠标按下就清除浏览器默认事件,文字就不会被选中了,好了,一个简单的拖拽效果就完成了,当然你现在是看不到效果,之所以不给demo链接是为了让你自己试着写一写,这样印象更深刻,

好了,那问题又来了,到这里就这样完了吗?。。。。。。按本人的风格,当然没有,干货还在后面!

如果我想实现这样一个效果,就是这一个大的容器里面(可以是box,也可以是document),怎么样能让我们的拖拽对象不跑出去呢,换句话说,拖到边缘就拖不动了,耶,是不是很多人想要实现的效果,哈哈,我们看看实现的原理是什么:

现实生活中,一个物体在一个盒子里跑不出去,是因为有堵墙,那我们只要能模拟出这堵墙,就可以把物体框起来,那这堵墙要怎么做呢?我们可以换个思路,当拖拽对象拖到边缘的时候,比如说拖到右边,我们将它的left固定住,是不是就不能再往右了,因为left值不能再加了,那么拖到底部,同理我们将top值固定住,就不能再往下拖了,理解吗?

最终的结果就是如下:

//左侧
if(obj.offsetLeft <=0){
  obj.style.left = 0;
};
//右侧
if(obj.offsetLeft >= pWidth - oWidth){
  obj.style.left = pWidth - oWidth + 'px'; 
};
//上面
if(obj.offsetTop <= 0){
  obj.style.top = 0; 
};
//下面
if(obj.offsetTop >= pHeight - oHeight){
  obj.style.top = pHeight - oHeight + 'px'; 
};

说明:pWidth,pHeight 表示父级元素的宽高(这里是表示相对于父级的宽高限制),oWidth,oHeigt表示拖拽元素的宽高

最后,我将整个拖拽代码整理了一下:

/*
      参数说明:
      元素绝对定位,父级相对定位,如果父级为window,则可以不用
      传一个参数,表示父级为window,物体相对于window范围拖动
      传2个参数,则父级为第二个参数,物体相对于父级范围拖动
      参数为id值
    */
    function drag(obj,parentNode){
      var obj = document.getElementById(obj);
      if(arguments.length == 1){
        var parentNode = window.self; 
        var pWidth = parentNode.innerWidth,pHeight = parentNode.innerHeight;  
      }else{
        var parentNode = document.getElementById(parentNode);
        var pWidth = parentNode.offsetWidth,pHeight = parentNode.offsetHeight;
      }
      obj.onmousedown = function(ev){
        var ev = ev || event;
        var disX = ev.clientX - this.offsetLeft,disY = ev.clientY - this.offsetTop;
        var oWidth = obj.offsetWidth,oHeight = obj.offsetHeight;
         
        //阻止冒泡时间
        ev.stopPropagation &#63; ev.stopPropagation() : ev.cancelBubble = true;
       
         
        document.onmousemove = function(ev){
          var ev = ev || event;
          obj.style.left = ev.clientX - disX + 'px';
          obj.style.top = ev.clientY - disY + 'px';
           
          //左侧
          if(obj.offsetLeft <=0){
            obj.style.left = 0;
          };
          //右侧
          if(obj.offsetLeft >= pWidth - oWidth){
            obj.style.left = pWidth - oWidth + 'px'; 
          };
          //上面
          if(obj.offsetTop <= 0){
            obj.style.top = 0; 
          };
          //下面
          if(obj.offsetTop >= pHeight - oHeight){
            obj.style.top = pHeight - oHeight + 'px'; 
          };
        };
        document.onmouseup = function(ev){
          var ev = ev || event;
          document.onmousemove = document.onmouseup = null;
        };
      }
         
    }

说明:我这里处理的效果是,如果传一个参数,表示相对的对象是window对象,如果传2个参数,第一个是拖拽对象,第二个为相对父级

开篇就说了,搜房网的那个图片拖拽效果是我的一个心结,我写了一个类似的效果,供大家参考,因为自己没有买服务器,所以效果我就不展示了,直接把代码贴出来,供大家参考:

css:

<style>
.box{
  width:600px;
  height:400px;
  margin:50px auto;
  position:relative;
  overflow:hidden;
}
#box{
  width:1000px;
  height:800px;
  position:absolute;
  left:50%;
  top:50%;
  margin:-400px 0 0 -500px;
}
#pic{ width:800px; height:600px; background:url(images/pic1.jpg) no-repeat; position:absolute; left:100px; top:100px; }
#pic:hover{
  cursor:move;
}
</style>

html:

<div class="box">
    <div id="box">
      <div id="pic"></div>
    </div>
  </div>

javascript:

window.onload = function(){
     
    drag("pic","box");
    function drag(obj,parentNode){
      var obj = document.getElementById(obj);
      if(arguments.length == 1){
        var parentNode = window.self; 
        var pWidth = parentNode.innerWidth,pHeight = parentNode.innerHeight;  
      }else{
        var parentNode = document.getElementById(parentNode);
        var pWidth = parentNode.offsetWidth,pHeight = parentNode.offsetHeight;
      }
      obj.onmousedown = function(ev){
        var ev = ev || event;
        var disX = ev.clientX - this.offsetLeft,disY = ev.clientY - this.offsetTop;
        var oWidth = obj.offsetWidth,oHeight = obj.offsetHeight;
         
        //阻止冒泡时间
        ev.stopPropagation &#63; ev.stopPropagation() : ev.cancelBubble = true;
       
         
        document.onmousemove = function(ev){
          var ev = ev || event;
          obj.style.left = ev.clientX - disX + 'px';
          obj.style.top = ev.clientY - disY + 'px';
           
          //左侧
          if(obj.offsetLeft <=0){
            obj.style.left = 0;
          };
          //右侧
          if(obj.offsetLeft >= pWidth - oWidth){
            obj.style.left = pWidth - oWidth + 'px'; 
          };
          //上面
          if(obj.offsetTop <= 0){
            obj.style.top = 0; 
          };
          //下面
          if(obj.offsetTop >= pHeight - oHeight){
            obj.style.top = pHeight - oHeight + 'px'; 
          };
        };
        document.onmouseup = function(ev){
          var ev = ev || event;
          document.onmousemove = document.onmouseup = null;
        };
      }
         
    }
     
     
  }

效果完全是用的那个封装代码块,引用起来也挺方便,有人会问了,你这用的id获取DOM元素,一个页面只能用一次啊,如果页面多次使用呢,有道理,解决方案之一,那就命名不同的id呗,又不犯法,方案二,获取id的地方改成获取class,但是要注意的是,getElementsByClassName是获取的class集合,需要改写一下,这里我就不写了,有兴趣的同学自行改写一下,好了,到这里真的结束了!

성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
es6数组怎么去掉重复并且重新排序es6数组怎么去掉重复并且重新排序May 05, 2022 pm 07:08 PM

去掉重复并排序的方法:1、使用“Array.from(new Set(arr))”或者“[…new Set(arr)]”语句,去掉数组中的重复元素,返回去重后的新数组;2、利用sort()对去重数组进行排序,语法“去重数组.sort()”。

JavaScript的Symbol类型、隐藏属性及全局注册表详解JavaScript的Symbol类型、隐藏属性及全局注册表详解Jun 02, 2022 am 11:50 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于Symbol类型、隐藏属性及全局注册表的相关问题,包括了Symbol类型的描述、Symbol不会隐式转字符串等问题,下面一起来看一下,希望对大家有帮助。

原来利用纯CSS也能实现文字轮播与图片轮播!原来利用纯CSS也能实现文字轮播与图片轮播!Jun 10, 2022 pm 01:00 PM

怎么制作文字轮播与图片轮播?大家第一想到的是不是利用js,其实利用纯CSS也能实现文字轮播与图片轮播,下面来看看实现方法,希望对大家有所帮助!

JavaScript对象的构造函数和new操作符(实例详解)JavaScript对象的构造函数和new操作符(实例详解)May 10, 2022 pm 06:16 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于对象的构造函数和new操作符,构造函数是所有对象的成员方法中,最早被调用的那个,下面一起来看一下吧,希望对大家有帮助。

JavaScript面向对象详细解析之属性描述符JavaScript面向对象详细解析之属性描述符May 27, 2022 pm 05:29 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于面向对象的相关问题,包括了属性描述符、数据描述符、存取描述符等等内容,下面一起来看一下,希望对大家有帮助。

javascript怎么移除元素点击事件javascript怎么移除元素点击事件Apr 11, 2022 pm 04:51 PM

方法:1、利用“点击元素对象.unbind("click");”方法,该方法可以移除被选元素的事件处理程序;2、利用“点击元素对象.off("click");”方法,该方法可以移除通过on()方法添加的事件处理程序。

整理总结JavaScript常见的BOM操作整理总结JavaScript常见的BOM操作Jun 01, 2022 am 11:43 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于BOM操作的相关问题,包括了window对象的常见事件、JavaScript执行机制等等相关内容,下面一起来看一下,希望对大家有帮助。

foreach是es6里的吗foreach是es6里的吗May 05, 2022 pm 05:59 PM

foreach不是es6的方法。foreach是es3中一个遍历数组的方法,可以调用数组的每个元素,并将元素传给回调函数进行处理,语法“array.forEach(function(当前元素,索引,数组){...})”;该方法不处理空数组。

See all articles

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

뜨거운 도구

ZendStudio 13.5.1 맥

ZendStudio 13.5.1 맥

강력한 PHP 통합 개발 환경

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse용 SAP NetWeaver 서버 어댑터

Eclipse를 SAP NetWeaver 애플리케이션 서버와 통합합니다.

에디트플러스 중국어 크랙 버전

에디트플러스 중국어 크랙 버전

작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음

DVWA

DVWA

DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는

Atom Editor Mac 버전 다운로드

Atom Editor Mac 버전 다운로드

가장 인기 있는 오픈 소스 편집기