一步一步實現JS拖拽外掛程式

來源:互聯網
上載者:User

一步一步實現JS拖拽外掛程式
閱讀目錄 一、js拖拽外掛程式的原理二、根據原理實現的最基本效果三、代碼抽象與最佳化四、擴充:有效拖拽元素五、效能最佳化和總結六、jquery外掛程式化js拖拽是常見的網頁效果,本文將從零開始實現一個簡單的js外掛程式。 回到頂部一、js拖拽外掛程式的原理常見的拖拽操作是什麼樣的呢?整過過程大概有下面幾個步驟:   1、用滑鼠點擊被拖拽的元素   2、按住滑鼠不放,移動滑鼠   3、拖拽元素到一定位置,放開滑鼠 這裡的過程涉及到三個dom事件:onmousedown,onmousemove,onmouseup。所以拖拽的基本思路就是:   1、用滑鼠點擊被拖拽的元素觸發onmousedown     (1)設定當前元素的可拖拽為true,表示可以拖拽     (2)記錄當前滑鼠的座標x,y     (3)記錄當前元素的座標x,y   2、移動滑鼠觸發onmousemove     (1)判斷元素是否可拖拽,如果是則進入步驟2,否則直接返回     (2)如果元素可拖拽,則設定元素的座標       元素的x座標 = 滑鼠移動的橫向距離+元素本來的x座標 = 滑鼠現在的x座標 - 滑鼠之前的x座標 + 元素本來的x座標       元素的y座標 = 滑鼠移動的橫向距離+元素本來的y座標 = 滑鼠現在的y座標 - 滑鼠之前的y座標 + 元素本來的y座標   3、放開滑鼠觸發onmouseup     (1)將滑鼠的可拖拽狀態設定成false 回到頂部二、根據原理實現的最基本效果在實現基本的效果之前,有幾點需要說明的:   1、元素想要被拖動,它的postion屬性一定要是relative或absolute   2、通過event.clientX和event.clientY擷取滑鼠的座標   3、onmousemove是綁定在document元素上而不是拖拽元素本身,這樣能解決快速拖動造成的延遲或停止移動的問題 代碼如下:  

 1 var dragObj = document.getElementById("test"); 2         dragObj.style.left = "0px"; 3         dragObj.style.top = "0px"; 4  5         var mouseX, mouseY, objX, objY; 6         var dragging = false; 7  8         dragObj.onmousedown = function (event) { 9             event = event || window.event;10 11             dragging = true;12             dragObj.style.position = "relative";13 14 15             mouseX = event.clientX;16             mouseY = event.clientY;17             objX = parseInt(dragObj.style.left);18             objY = parseInt(dragObj.style.top);19         }20 21         document.onmousemove = function (event) {22             event = event || window.event;23             if (dragging) {24 25                 dragObj.style.left = parseInt(event.clientX - mouseX + objX) + "px";26                 dragObj.style.top = parseInt(event.clientY - mouseY + objY) + "px";27             }28 29         }30 31         document.onmouseup = function () {32             dragging = false;33         } 

 

   回到頂部三、代碼抽象與最佳化上面的代碼要做成外掛程式,要將其抽象出來,基本結構如下:  
1         ; (function (window, undefined) {            2 3             function Drag(ele) {}4 5             window.Drag = Drag;6         })(window, undefined);

 

 用自執行匿名函數將程式碼封裝起來,內部定義Drag方法並暴露到全域中,直接調用Drag,傳入被拖拽的元素。 首先對一些常用的方法進行簡單的封裝:  
 1         ; (function (window, undefined) { 2             var dom = { 3                 //綁定事件 4                 on: function (node, eventName, handler) { 5                     if (node.addEventListener) { 6                         node.addEventListener(eventName, handler); 7                     } 8                     else { 9                         node.attachEvent("on" + eventName, handler);10                     }11                 },12                 //擷取元素的樣式13                 getStyle: function (node, styleName) {14                     var realStyle = null;15                     if (window.getComputedStyle) {16                         realStyle = window.getComputedStyle(node, null)[styleName];17                     }18                     else if (node.currentStyle) {19                         realStyle = node.currentStyle[styleName];20                     }21                     return realStyle;22                 },23                 //擷取設定元素的樣式24                 setCss: function (node, css) {25                     for (var key in css) {26                         node.style[key] = css[key];27                     }28                 }29             };30           31             window.Drag = Drag;32         })(window, undefined);

 

  在一個拖拽操作中,存在著兩個對象:被拖拽的對象和滑鼠對象,我們定義了下面的兩個對象以及它們對應的操作: 首先的拖拽對象,它包含一個元素節點和拖拽之前的座標x和y:  
 1             function DragElement(node) { 2                 this.node = node;//被拖拽的元素節點 3                 this.x = 0;//拖拽之前的x座標 4                 this.y = 0;//拖拽之前的y座標 5             } 6             DragElement.prototype = { 7                 constructor: DragElement, 8                 init: function () {                     9                     this.setEleCss({10                         "left": dom.getStyle(node, "left"),11                         "top": dom.getStyle(node, "top")12                     })13                     .setXY(node.style.left, node.style.top);14                 },15                 //設定當前的座標16                 setXY: function (x, y) {17                     this.x = parseInt(x) || 0;18                     this.y = parseInt(y) || 0;19                     return this;20                 },21                 //設定元素節點的樣式22                 setEleCss: function (css) {23                     dom.setCss(this.node, css);24                     return this;25                 }26             } 

 

   還有一個對象是滑鼠,它主要包含x座標和y座標:  
1             function Mouse() {2                 this.x = 0;3                 this.y = 0;4             }5             Mouse.prototype.setXY = function (x, y) {6                 this.x = parseInt(x);7                 this.y = parseInt(y);8             }         

 

這是在拖拽操作中定義的兩個對象。   如果一個頁面可以有多個拖拽元素,那應該注意什麼: 1、每個元素對應一個拖拽對象執行個體 2、每個頁面只能有一個正在拖拽中的元素 為此,我們定義了唯一一個對象用來儲存相關的配置: 
 1             var draggableConfig = {2                 zIndex: 1,3                 draggingObj: null,4                 mouse: new Mouse()5             };

 

 這個對象中有三個屬性: (1)zIndex:用來賦值給拖拽對象的zIndex屬性,有多個拖拽對象時,當兩個拖拽對象重疊時,會造成當前拖拽對象有可能被擋住,通過設定zIndex使其顯示在最頂層 (2)draggingObj:用來儲存正在拖拽的對象,在這裡去掉了前面的用來判斷是否可拖拽的變數,通過draggingObj來判斷當前是否可以拖拽以及擷取相應的拖拽對象 (3)mouse:唯一的滑鼠對象,用來儲存當前滑鼠的座標等資訊   最後是綁定onmousedown,onmouseover,onmouseout事件,整合上面的代碼如下:  
  1         ; (function (window, undefined) {  2             var dom = {  3                 //綁定事件  4                 on: function (node, eventName, handler) {  5                     if (node.addEventListener) {  6                         node.addEventListener(eventName, handler);  7                     }  8                     else {  9                         node.attachEvent("on" + eventName, handler); 10                     } 11                 }, 12                 //擷取元素的樣式 13                 getStyle: function (node, styleName) { 14                     var realStyle = null; 15                     if (window.getComputedStyle) { 16                         realStyle = window.getComputedStyle(node, null)[styleName]; 17                     } 18                     else if (node.currentStyle) { 19                         realStyle = node.currentStyle[styleName]; 20                     } 21                     return realStyle; 22                 }, 23                 //擷取設定元素的樣式 24                 setCss: function (node, css) { 25                     for (var key in css) { 26                         node.style[key] = css[key]; 27                     } 28                 } 29             }; 30  31             //#region 拖拽元素類 32             function DragElement(node) { 33                 this.node = node; 34                 this.x = 0; 35                 this.y = 0; 36             } 37             DragElement.prototype = { 38                 constructor: DragElement, 39                 init: function () {                     40                     this.setEleCss({ 41                         "left": dom.getStyle(node, "left"), 42                         "top": dom.getStyle(node, "top") 43                     }) 44                     .setXY(node.style.left, node.style.top); 45                 }, 46                 setXY: function (x, y) { 47                     this.x = parseInt(x) || 0; 48                     this.y = parseInt(y) || 0; 49                     return this; 50                 }, 51                 setEleCss: function (css) { 52                     dom.setCss(this.node, css); 53                     return this; 54                 } 55             } 56             //#endregion 57  58             //#region 滑鼠元素 59             function Mouse() { 60                 this.x = 0; 61                 this.y = 0; 62             } 63             Mouse.prototype.setXY = function (x, y) { 64                 this.x = parseInt(x); 65                 this.y = parseInt(y); 66             } 67             //#endregion 68  69             //拖拽配置 70             var draggableConfig = { 71                 zIndex: 1, 72                 draggingObj: null, 73                 mouse: new Mouse() 74             }; 75  76             function Drag(ele) { 77                 this.ele = ele; 78  79                 function mouseDown(event) { 80                     var ele = event.target || event.srcElement; 81  82                     draggableConfig.mouse.setXY(event.clientX, event.clientY); 83  84                     draggableConfig.draggingObj = new DragElement(ele); 85                     draggableConfig.draggingObj 86                         .setXY(ele.style.left, ele.style.top) 87                         .setEleCss({ 88                             "zIndex": draggableConfig.zIndex++, 89                             "position": "relative" 90                         }); 91                 }                 92  93                 ele.onselectstart = function () { 94                     //防止拖拽對象內的文字被選中 95                     return false; 96                 } 97                 dom.on(ele, "mousedown", mouseDown); 98             } 99 100             dom.on(document, "mousemove", function (event) {101                 if (draggableConfig.draggingObj) {102                     var mouse = draggableConfig.mouse,103                         draggingObj = draggableConfig.draggingObj;104                     draggingObj.setEleCss({105                         "left": parseInt(event.clientX - mouse.x + draggingObj.x) + "px",106                         "top": parseInt(event.clientY - mouse.y + draggingObj.y) + "px"107                     });108                 }109             })110 111             dom.on(document, "mouseup", function (event) {112                 draggableConfig.draggingObj = null;113             })114 115 116             window.Drag = Drag;117         })(window, undefined);

 

 調用方法:Drag(document.getElementById("obj")); 注意的一點,為了防止選中拖拽元素中的文字,通過onselectstart事件處理常式return false來處理這個問題。  

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.