欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JS拖拽插件實(shí)現(xiàn)步驟

 更新時(shí)間:2015年08月03日 09:52:29   作者:小灰狼的腦瓜  
實(shí)現(xiàn)JS拖拽插件主要從六個(gè)方面做介紹:一、js拖拽插件的原理,二、根據(jù)原理實(shí)現(xiàn)的最基本效果,三、代碼抽象與優(yōu)化,四、擴(kuò)展:有效的拖拽元素,五、性能優(yōu)化和總結(jié),六、jquery插件化 ,需要的朋友可以參考下

這篇文章詳細(xì)介紹了JS拖拽插件的實(shí)現(xiàn)步驟,主要從以下六步做詳細(xì)分析,具體內(nèi)容如下:

一、js拖拽插件的原理
二、根據(jù)原理實(shí)現(xiàn)的最基本效果
三、代碼抽象與優(yōu)化
四、擴(kuò)展:有效的拖拽元素
五、性能優(yōu)化和總結(jié)
六、jquery插件化
js拖拽是常見的網(wǎng)頁效果,本文將從零開始實(shí)現(xiàn)一個(gè)簡單的js插件。


一、js拖拽插件的原理
常見的拖拽操作是什么樣的呢?整過過程大概有下面幾個(gè)步驟:

  1、用鼠標(biāo)點(diǎn)擊被拖拽的元素

  2、按住鼠標(biāo)不放,移動(dòng)鼠標(biāo)

  3、拖拽元素到一定位置,放開鼠標(biāo)

這里的過程涉及到三個(gè)dom事件:onmousedown,onmousemove,onmouseup。所以拖拽的基本思路就是:

  1、用鼠標(biāo)點(diǎn)擊被拖拽的元素觸發(fā)onmousedown

   ?。?)設(shè)置當(dāng)前元素的可拖拽為true,表示可以拖拽

    (2)記錄當(dāng)前鼠標(biāo)的坐標(biāo)x,y

   ?。?)記錄當(dāng)前元素的坐標(biāo)x,y

  2、移動(dòng)鼠標(biāo)觸發(fā)onmousemove

    (1)判斷元素是否可拖拽,如果是則進(jìn)入步驟2,否則直接返回

    (2)如果元素可拖拽,則設(shè)置元素的坐標(biāo)

      元素的x坐標(biāo) = 鼠標(biāo)移動(dòng)的橫向距離+元素本來的x坐標(biāo) = 鼠標(biāo)現(xiàn)在的x坐標(biāo) - 鼠標(biāo)之前的x坐標(biāo) + 元素本來的x坐標(biāo)

      元素的y坐標(biāo) = 鼠標(biāo)移動(dòng)的橫向距離+元素本來的y坐標(biāo) = 鼠標(biāo)現(xiàn)在的y坐標(biāo) - 鼠標(biāo)之前的y坐標(biāo) + 元素本來的y坐標(biāo)

  3、放開鼠標(biāo)觸發(fā)onmouseup

   ?。?)將鼠標(biāo)的可拖拽狀態(tài)設(shè)置成false

回到頂部
二、根據(jù)原理實(shí)現(xiàn)的最基本效果
在實(shí)現(xiàn)基本的效果之前,有幾點(diǎn)需要說明的:

  1、元素想要被拖動(dòng),它的postion屬性一定要是relative或absolute

  2、通過event.clientX和event.clientY獲取鼠標(biāo)的坐標(biāo)

  3、onmousemove是綁定在document元素上而不是拖拽元素本身,這樣能解決快速拖動(dòng)造成的延遲或停止移動(dòng)的問題

代碼如下:

var dragObj = document.getElementById("test");
   dragObj.style.left = "px";
   dragObj.style.top = "px";
 
   var mouseX, mouseY, objX, objY;
   var dragging = false;
 
   dragObj.onmousedown = function (event) {
    event = event || window.event;
 
    dragging = true;
    dragObj.style.position = "relative";
 
 
    mouseX = event.clientX;
    mouseY = event.clientY;
    objX = parseInt(dragObj.style.left);
    objY = parseInt(dragObj.style.top);
   }
 
   document.onmousemove = function (event) {
    event = event || window.event;
    if (dragging) {
 
     dragObj.style.left = parseInt(event.clientX - mouseX + objX) + "px";
     dragObj.style.top = parseInt(event.clientY - mouseY + objY) + "px";
    }
 
   }
 
   document.onmouseup = function () {
    dragging = false;
   }


三、代碼抽象與優(yōu)化
上面的代碼要做成插件,要將其抽象出來,基本結(jié)構(gòu)如下:

 

復(fù)制代碼 代碼如下:

 ; (function (window, undefined) {           
 
             function Drag(ele) {}
 
             window.Drag = Drag;
         })(window, undefined);

用自執(zhí)行匿名函數(shù)將代碼包起來,內(nèi)部定義Drag方法并暴露到全局中,直接調(diào)用Drag,傳入被拖拽的元素。

首先對(duì)一些常用的方法進(jìn)行簡單的封裝:

; (function (window, undefined) {
    var dom = {
     //綁定事件
     on: function (node, eventName, handler) {
      if (node.addEventListener) {
       node.addEventListener(eventName, handler);
      }
      else {
       node.attachEvent("on" + eventName, handler);
      }
     },
     //獲取元素的樣式
     getStyle: function (node, styleName) {
      var realStyle = null;
      if (window.getComputedStyle) {
       realStyle = window.getComputedStyle(node, null)[styleName];
      }
      else if (node.currentStyle) {
       realStyle = node.currentStyle[styleName];
      }
      return realStyle;
     },
     //獲取設(shè)置元素的樣式
     setCss: function (node, css) {
      for (var key in css) {
       node.style[key] = css[key];
      }
     }
    };
    window.Drag = Drag;
   })(window, undefined);

在一個(gè)拖拽操作中,存在著兩個(gè)對(duì)象:被拖拽的對(duì)象和鼠標(biāo)對(duì)象,我們定義了下面的兩個(gè)對(duì)象以及它們對(duì)應(yīng)的操作:

首先的拖拽對(duì)象,它包含一個(gè)元素節(jié)點(diǎn)和拖拽之前的坐標(biāo)x和y:

 function DragElement(node) {
     this.node = node;//被拖拽的元素節(jié)點(diǎn)
     this.x = ;//拖拽之前的x坐標(biāo)
     this.y = ;//拖拽之前的y坐標(biāo)
    }
    DragElement.prototype = {
     constructor: DragElement,
     init: function () {     
      this.setEleCss({
       "left": dom.getStyle(node, "left"),
       "top": dom.getStyle(node, "top")
      })
      .setXY(node.style.left, node.style.top);
     },
     //設(shè)置當(dāng)前的坐標(biāo)
     setXY: function (x, y) {
      this.x = parseInt(x) || ;
      this.y = parseInt(y) || ;
      return this;
     },
     //設(shè)置元素節(jié)點(diǎn)的樣式
     setEleCss: function (css) {
      dom.setCss(this.node, css);
      return this;
     }
    }

還有一個(gè)對(duì)象是鼠標(biāo),它主要包含x坐標(biāo)和y坐標(biāo):  

function Mouse() {
     this.x = ;
     this.y = ;
    }
    Mouse.prototype.setXY = function (x, y) {
     this.x = parseInt(x);
     this.y = parseInt(y);
    }  

這是在拖拽操作中定義的兩個(gè)對(duì)象。

如果一個(gè)頁面可以有多個(gè)拖拽元素,那應(yīng)該注意什么:

1、每個(gè)元素對(duì)應(yīng)一個(gè)拖拽對(duì)象實(shí)例

2、每個(gè)頁面只能有一個(gè)正在拖拽中的元素

為此,我們定義了唯一一個(gè)對(duì)象用來保存相關(guān)的配置:

 

復(fù)制代碼 代碼如下:

var draggableConfig = {
                 zIndex: ,
                 draggingObj: null,
                 mouse: new Mouse()
             };

這個(gè)對(duì)象中有三個(gè)屬性:

(1)zIndex:用來賦值給拖拽對(duì)象的zIndex屬性,有多個(gè)拖拽對(duì)象時(shí),當(dāng)兩個(gè)拖拽對(duì)象重疊時(shí),會(huì)造成當(dāng)前拖拽對(duì)象有可能被擋住,通過設(shè)置zIndex使其顯示在最頂層

(2)draggingObj:用來保存正在拖拽的對(duì)象,在這里去掉了前面的用來判斷是否可拖拽的變量,通過draggingObj來判斷當(dāng)前是否可以拖拽以及獲取相應(yīng)的拖拽對(duì)象

(3)mouse:唯一的鼠標(biāo)對(duì)象,用來保存當(dāng)前鼠標(biāo)的坐標(biāo)等信息

最后是綁定onmousedown,onmouseover,onmouseout事件,整合上面的代碼如下:     

 ; (function (window, undefined) {
    var dom = {
     //綁定事件
     on: function (node, eventName, handler) {
      if (node.addEventListener) {
       node.addEventListener(eventName, handler);
      }
      else {
       node.attachEvent("on" + eventName, handler);
      }
     },
     //獲取元素的樣式
     getStyle: function (node, styleName) {
      var realStyle = null;
      if (window.getComputedStyle) {
       realStyle = window.getComputedStyle(node, null)[styleName];
      }
      else if (node.currentStyle) {
       realStyle = node.currentStyle[styleName];
      }
      return realStyle;
     },
     //獲取設(shè)置元素的樣式
     setCss: function (node, css) {
      for (var key in css) {
       node.style[key] = css[key];
      }
     }
    };
    //#region 拖拽元素類
    function DragElement(node) {
     this.node = node;
     this.x = ;
     this.y = ;
    }
    DragElement.prototype = {
     constructor: DragElement,
     init: function () {     
      this.setEleCss({
       "left": dom.getStyle(node, "left"),
       "top": dom.getStyle(node, "top")
      })
      .setXY(node.style.left, node.style.top);
     },
     setXY: function (x, y) {
      this.x = parseInt(x) || ;
      this.y = parseInt(y) || ;
      return this;
     },
     setEleCss: function (css) {
      dom.setCss(this.node, css);
      return this;
     }
    }
    //#endregion
    //#region 鼠標(biāo)元素
    function Mouse() {
     this.x = ;
     this.y = ;
    }
    Mouse.prototype.setXY = function (x, y) {
     this.x = parseInt(x);
     this.y = parseInt(y);
    }
    //#endregion
    //拖拽配置
    var draggableConfig = {
     zIndex: ,
     draggingObj: null,
     mouse: new Mouse()
    };
    function Drag(ele) {
     this.ele = ele;
     function mouseDown(event) {
      var ele = event.target || event.srcElement;
      draggableConfig.mouse.setXY(event.clientX, event.clientY);
      draggableConfig.draggingObj = new DragElement(ele);
      draggableConfig.draggingObj
       .setXY(ele.style.left, ele.style.top)
       .setEleCss({
        "zIndex": draggableConfig.zIndex++,
        "position": "relative"
       });
     }    
     ele.onselectstart = function () {
      //防止拖拽對(duì)象內(nèi)的文字被選中
      return false;
     }
     dom.on(ele, "mousedown", mouseDown);
    }
    dom.on(document, "mousemove", function (event) {
     if (draggableConfig.draggingObj) {
      var mouse = draggableConfig.mouse,
       draggingObj = draggableConfig.draggingObj;
      draggingObj.setEleCss({
       "left": parseInt(event.clientX - mouse.x + draggingObj.x) + "px",
       "top": parseInt(event.clientY - mouse.y + draggingObj.y) + "px"
      });
     }
    })
    dom.on(document, "mouseup", function (event) {
     draggableConfig.draggingObj = null;
    })
    window.Drag = Drag;
   })(window, undefined);

調(diào)用方法:Drag(document.getElementById("obj"));

注意的一點(diǎn),為了防止選中拖拽元素中的文字,通過onselectstart事件處理程序return false來處理這個(gè)問題。


四、擴(kuò)展:有效的拖拽元素
我們常見的一些拖拽效果很有可能是這樣的:

彈框的頂部是可以進(jìn)行拖拽操作的,內(nèi)容區(qū)域是不可拖拽的,怎么實(shí)現(xiàn)這樣的效果呢:

首先優(yōu)化拖拽元素對(duì)象如下,增加一個(gè)目標(biāo)元素target,表示被拖拽對(duì)象,在上圖的登錄框中,就是整個(gè)登錄窗口。

被記錄和設(shè)置坐標(biāo)的拖拽元素就是這個(gè)目標(biāo)元素,但是它并不是整個(gè)部分都是拖拽的有效部分。我們?cè)趆tml結(jié)構(gòu)中為拖拽的有效區(qū)域添加類draggable表示有效拖拽區(qū)域:


    

復(fù)制代碼 代碼如下:

<div id="obj" class="dialog" style="position:relative;left:px">
         <div class="header draggable">
             拖拽的有效元素
         </div>
         <div class="content">
             拖拽對(duì)象
         </div>
     </div>

然后修改Drag方法如下:

 function drag(ele) {
  var dragNode = (ele.querySelector(".draggable") || ele);
  dom.on(dragNode, "mousedown", function (event) {
   var dragElement = draggableConfig.dragElement = new DragElement(ele);

   draggableConfig.mouse.setXY(event.clientX, event.clientY);
   draggableConfig.dragElement
    .setXY(dragElement.target.style.left, dragElement.target.style.top)
    .setTargetCss({
     "zIndex": draggableConfig.zIndex++,
     "position": "relative"
    });
  }).on(dragNode, "mouseover", function () {
   dom.setCss(this, draggableStyle.dragging);
  }).on(dragNode, "mouseout", function () {
   dom.setCss(this, draggableStyle.defaults);
  });
 }

主要修改的是綁定mousedown的節(jié)點(diǎn)變成了包含draggable類的有效元素,如果不含有draggable,則整個(gè)元素都是有效元素。


五、性能優(yōu)化和總結(jié)
由于onmousemove在一直調(diào)用,會(huì)造成一些性能問題,我們可以通過setTimout來延遲綁定onmousemove事件,改進(jìn)move函數(shù)如下

function move(event) {
   if (draggableConfig.dragElement) {
    var mouse = draggableConfig.mouse,
     dragElement = draggableConfig.dragElement;
    dragElement.setTargetCss({
     "left": parseInt(event.clientX - mouse.x + dragElement.x) + "px",
     "top": parseInt(event.clientY - mouse.y + dragElement.y) + "px"
    });
 
    dom.off(document, "mousemove", move);
    setTimeout(function () {
     dom.on(document, "mousemove", move);
    }, );
   }
  }

總結(jié):

整個(gè)拖拽插件的實(shí)現(xiàn)其實(shí)很簡單,主要是要注意幾點(diǎn)

  1、實(shí)現(xiàn)思路:元素拖拽位置的改變就等于鼠標(biāo)改變的距離,關(guān)鍵在于獲取鼠標(biāo)的變動(dòng)和元素原本的坐標(biāo)

      2、通過setTimeout來延遲加載onmousemove事件來提供性能


六、jquery插件化
簡單地將其封裝成jquery插件,主要是相關(guān)的dom方法替換成jquery方法來操作

 ; (function ($, window, undefined) {
  //#region 拖拽元素類
  function DragElement(node) {
 
   this.target = node;
 
   node.onselectstart = function () {
    //防止拖拽對(duì)象內(nèi)的文字被選中
    return false;
   }
  }
  DragElement.prototype = {
   constructor: DragElement,
   setXY: function (x, y) {
    this.x = parseInt(x) || ;
    this.y = parseInt(y) || ;
    return this;
   },
   setTargetCss: function (css) {
    $(this.target).css(css);
    return this;
   }
  }
  //#endregion
 
  //#region 鼠標(biāo)元素
  function Mouse() {
   this.x = ;
   this.y = ;
  }
  Mouse.prototype.setXY = function (x, y) {
   this.x = parseInt(x);
   this.y = parseInt(y);
  }
  //#endregion
 
  //拖拽配置
  var draggableConfig = {
   zIndex: ,
   dragElement: null,
   mouse: new Mouse()
  };
 
  var draggableStyle = {
   dragging: {
    cursor: "move"
   },
   defaults: {
    cursor: "default"
   }
  }
 
  var $document = $(document);
 
  function drag($ele) {
   var $dragNode = $ele.find(".draggable");
   $dragNode = $dragNode.length > ? $dragNode : $ele;
   
 
   $dragNode.on({
    "mousedown": function (event) {
     var dragElement = draggableConfig.dragElement = new DragElement($ele.get());
 
     draggableConfig.mouse.setXY(event.clientX, event.clientY);
     draggableConfig.dragElement
      .setXY(dragElement.target.style.left, dragElement.target.style.top)
      .setTargetCss({
       "zIndex": draggableConfig.zIndex++,
       "position": "relative"
      });
    },
    "mouseover": function () {
     $(this).css(draggableStyle.dragging);
    },
    "mouseout": function () {
     $(this).css(draggableStyle.defaults);
    }
   })
  }
 
  function move(event) {
   if (draggableConfig.dragElement) {
    var mouse = draggableConfig.mouse,
     dragElement = draggableConfig.dragElement;
    dragElement.setTargetCss({
     "left": parseInt(event.clientX - mouse.x + dragElement.x) + "px",
     "top": parseInt(event.clientY - mouse.y + dragElement.y) + "px"
    });
 
    $document.off("mousemove", move);
    setTimeout(function () {
     $document.on("mousemove", move);
    }, );
   }
  }
 
  $document.on({
   "mousemove": move,
   "mouseup": function () {
    draggableConfig.dragElement = null;
   }
  });
 
  $.fn.drag = function (options) {
   drag(this);
  }
 
 })(jQuery, window, undefined)

以上就是本文對(duì)JS拖拽插件實(shí)現(xiàn)步驟的詳細(xì)介紹,希望對(duì)大家有所幫助。

相關(guān)文章

  • 在TypeScript項(xiàng)目中搭配Axios封裝后端接口調(diào)用

    在TypeScript項(xiàng)目中搭配Axios封裝后端接口調(diào)用

    這篇文章主要介紹了在TypeScript項(xiàng)目中搭配Axios封裝后端接口調(diào)用,本文記錄一下在?TypeScript?項(xiàng)目里封裝?axios?的過程,之前在開發(fā)?StarBlog-Admin?的時(shí)候已經(jīng)做了一次封裝,不過那時(shí)是JavaScript跟TypeScript還是有些區(qū)別的,需要的朋友可以參考下
    2024-01-01
  • 詳解JavaScript的懶加載是如何實(shí)現(xiàn)的

    詳解JavaScript的懶加載是如何實(shí)現(xiàn)的

    懶加載(Lazy Loading)是一種在軟件開發(fā)中常用的優(yōu)化技術(shù),它主要用于延遲加載資源,直到真正需要使用的時(shí)候才進(jìn)行加載,這樣可以減少初始加載的時(shí)間和資源消耗,并提升用戶體驗(yàn),本文給大家詳細(xì)介紹了JavaScript的懶加載是如何實(shí)現(xiàn)的,需要的朋友可以參考下
    2024-01-01
  • html2canvas圖片跨域問題圖文詳解

    html2canvas圖片跨域問題圖文詳解

    我們?cè)谶M(jìn)行圖片保存的時(shí)候經(jīng)常會(huì)發(fā)現(xiàn)圖片跨域了,下面下面這篇文章主要給大家介紹了關(guān)于html2canvas圖片跨域問題的相關(guān)資料,需要的朋友可以參考下
    2023-03-03
  • [JS源碼]超長文章自動(dòng)分頁(客戶端版)

    [JS源碼]超長文章自動(dòng)分頁(客戶端版)

    [JS源碼]超長文章自動(dòng)分頁(客戶端版)...
    2007-01-01
  • 非正則實(shí)現(xiàn)的只能輸入漢字的輸入框

    非正則實(shí)現(xiàn)的只能輸入漢字的輸入框

    非正則實(shí)現(xiàn)的只能輸入漢字的輸入框...
    2007-03-03
  • 判斷是否存在子節(jié)點(diǎn)的實(shí)現(xiàn)代碼

    判斷是否存在子節(jié)點(diǎn)的實(shí)現(xiàn)代碼

    下面小編就為大家?guī)硪黄袛嗍欠翊嬖谧庸?jié)點(diǎn)的實(shí)現(xiàn)代碼。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-05-05
  • 微信sdk實(shí)現(xiàn)禁止微信分享(使用原生php實(shí)現(xiàn))

    微信sdk實(shí)現(xiàn)禁止微信分享(使用原生php實(shí)現(xiàn))

    這篇文章主要介紹了微信sdk實(shí)現(xiàn)禁止微信分享(使用原生php實(shí)現(xiàn)),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11
  • 用DIV完美模擬createPopup 彈出窗口(腳本之家修正版),支持Firefox,ie,chrome

    用DIV完美模擬createPopup 彈出窗口(腳本之家修正版),支持Firefox,ie,chrome

    最近要重構(gòu)公司的一個(gè)站,有一個(gè)拾色器只支持IE,不支持FIREFOX CHROME等瀏覽器,花了點(diǎn)時(shí)間對(duì)照原來的重寫了個(gè)。完美實(shí)現(xiàn)createPopup方法的彈窗效果,歡迎大家拍磚!
    2009-09-09
  • 微信小程序調(diào)用wx.getImageInfo遇到的坑解決

    微信小程序調(diào)用wx.getImageInfo遇到的坑解決

    這篇文章主要介紹了微信小程序調(diào)用wx.getImageInfo遇到的坑解決,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-05-05
  • 淺談addEventListener和attachEvent的區(qū)別

    淺談addEventListener和attachEvent的區(qū)別

    下面小編就為大家?guī)硪黄獪\談addEventListener和attachEvent的區(qū)別。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2016-07-07

最新評(píng)論