繼之前發表的文章——元素拖拽之后,終於完成了最終效果,拖拽替換,並且對之前的代碼進行了優化。也算有始有終了。
之前只是將代碼大概貼了出來,沒有進行詳細講解。這次也會彌補上一次的不足之處,將代碼產生的一個大概過程闡述一下。一來提升自己,而來希望也能幫助到別人。
插句題外話,自入行以來,真心覺得程序猿大多都特別慷慨,從來不吝嗇自己所知道的技術。多少有些感動,沒有那么多人不吝嗇的指點,我也不會成長成現在這樣
回歸正題。
第一步是搭建數據庫,先在前台界面把內容展示出來
這里不做過多贅述,如果對於數據庫與前台界面展示數據不清楚的,可以先看之前的文章wex5 ——— 前台界面展示數據庫內容
搭建一個名為drag的數據庫,在數據庫中件名為items的表,字段如下。
新建drag服務,並在前台界面調用。在界面添加baasData數據庫,綁定drag服務。
並用list數據組件對數據進行展示
圖為對數據進行初次展示的效果。
下面主要講解實現效果的代碼:
js實現的大概思路還是主要包括三部分:開始——移動——結束
手指觸屏對應touchstart
手指移動對應touchmove
手指松開對應touchend
當然在這之前還得做一下准備工作——定義一些全局參數用於承載被拖動的元素,被替換的元素和一些坐標點等
var Model = function(){ this.callParent(); this.curTarget = null;//被拖動的元素 this.curPos = null;//坐標點 this.dropTarget = null;//被替換的元素 this.iMouseDown = null;//手指是否觸屏 this.lMouseState = null;//狀態 this.dragreplaceCont = [];//將遍歷的元素放於此數組中 this.mouseOffset = null;//鼠標得偏移 this.callbackFunc = null;//回調函數 };
在modelLoad中,新建一個div用於承載被拖動的元素
並且遍歷要拖動的元素,將他們放置在數組中,用於之后的匹配元素做准備,且設置他們為可拖動狀態
Model.prototype.modelLoad = function(event){ //輔助層用來顯示拖拽 dragHelper = document.createElement('DIV'); dragHelper.setAttribute("class",'dragHelper czYfqmm ') dragHelper.style.cssText = 'position:absolute;display:none;'; document.body.appendChild(dragHelper); var dragitems = document.getElementById('displayRoom').getElementsByTagName("a");//獲取可拖動的所有元素 for(var i=0;i<dragitems.length;i++){//遍歷可拖動的元素 this.dragreplaceCont.push(dragitems[i]); dragitems[i].setAttribute('candrag', '1'); } };
給元素綁定以上三個事件
首先當然是在start中記錄狀態值,
Model.prototype.start = function(event){ //記錄變量狀態 this.iMouseDown = true; };
接下來就是移動的動作:
1、先獲取當前鼠標點擊的元素
2、判斷當前是否為可拖動狀態
3、將當前元素賦值給之前定義的全局參數this.curTarget
4、獲取元素的坐標點,以及按下的坐標點對於元素左上角的偏移量
5、清空之前在modelload中定義的輔助層dragHelper,將當前元素this.curTarget放進去,設置dragHelper為可見狀態,當前元素this.curTarget不可見,
6、記錄起始坐標點並且,如果處於移動狀態,則設置輔助層dragHelper的top和left值,使其實時移動(使用css的position達到移動效果)
7、遍歷各個元素,看當前在移動的元素是否與其中某個除自己之外的元素重合,
8、如果重合,則將被重合的元素賦值給全局變量this.dropTarget,並給this.dropTarget添加被選中的樣式
最后是鼠標松開的動作:
1、判斷是否有被選中的元素和要被替換的元素
2、獲取兩個元素所在的行數據,並分別設置兩個行數據的值,即對兩個值進行替換
3、判斷兩個行數據是否被改變過,如果有則保存數據,並對一些全局參數進行還原,以備下一次的拖動替換
不知道怎么上傳壓縮包,所以就用笨方法上傳代碼了。
下面附上完整的代碼
1 define(function(require){ 2 var $ = require("jquery"); 3 var justep = require("$UI/system/lib/justep"); 4 5 var Model = function(){ 6 this.callParent(); 7 8 this.curTarget = null; 9 this.curPos = null; 10 this.dropTarget = null; 11 this.iMouseDown = null; 12 this.lMouseState = null; 13 this.dragreplaceCont = []; 14 this.mouseOffset = null; 15 this.callbackFunc = null; 16 }; 17 18 Model.prototype.modelLoad = function(event){ 19 //輔助層用來顯示拖拽 20 dragHelper = document.createElement('DIV'); 21 dragHelper.setAttribute("class",'dragHelper czYfqmm ') 22 dragHelper.style.cssText = 'position:absolute;display:none;'; 23 document.body.appendChild(dragHelper); 24 25 var dragitems = document.getElementById('displayRoom').getElementsByTagName("a");//獲取可拖動的所有元素 26 for(var i=0;i<dragitems.length;i++){//遍歷可拖動的元素 27 this.dragreplaceCont.push(dragitems[i]); 28 dragitems[i].setAttribute('candrag', '1'); 29 } 30 }; 31 32 Model.prototype.start = function(event){ 33 //記錄變量狀態 34 this.iMouseDown = true; 35 }; 36 37 Model.prototype.move = function(event){ 38 ev = event || window.event; 39 var target = ev.target || ev.srcElement; 40 var mousePos = this.mouseCoords(ev); 41 //如果當前元素可拖拽 42 var dragObj = target.getAttribute('candrag'); 43 if (dragObj != null) { 44 if (this.iMouseDown && !this.lMouseState) { 45 //剛開始拖拽 46 this.curTarget = target; 47 this.curPos = this.getPosition(target); 48 this.mouseOffset = this.getMouseOffset(target, ev); 49 // 清空輔助層 50 for (var i = 0; i < dragHelper.childNodes.length; i++) dragHelper.removeChild(dragHelper.childNodes[i]); 51 //克隆元素到輔助層,並移動到鼠標位置 52 dragHelper.appendChild(this.curTarget.cloneNode(true)); 53 dragHelper.style.display = 'block'; 54 dragHelper.firstChild.removeAttribute('data-bind'); 55 dragHelper.firstChild.removeAttribute('candrag'); 56 dragHelper.firstChild.setAttribute("class","czYfqmm"); 57 //記錄拖拽元素的位置信息 58 this.curTarget.setAttribute('startWidth', parseInt(this.curTarget.offsetWidth)); 59 this.curTarget.setAttribute('startHeight', parseInt(this.curTarget.offsetHeight)); 60 this.curTarget.style.background = 'none'; 61 //記錄每個可接納元素的位置信息,這里一次記錄以后多次調用,獲取更高性能 62 for (var i = 0; i < this.dragreplaceCont.length; i++) { 63 with (this.dragreplaceCont[i]) { 64 if (this.dragreplaceCont[i] == this.curTarget) 65 continue; 66 var pos = this.getPosition(this.dragreplaceCont[i]); 67 setAttribute('startWidth', parseInt(offsetWidth)); 68 setAttribute('startHeight', parseInt(offsetHeight)); 69 setAttribute('startLeft', pos.x); 70 setAttribute('startTop', pos.y); 71 } 72 } 73 } 74 } 75 //正在拖拽 76 if (this.curTarget != null) { 77 // move our helper div to wherever the mouse is (adjusted by mouseOffset) 78 dragHelper.style.top = mousePos.y -this.mouseOffset.y + "px"; 79 dragHelper.style.left = mousePos.x -this.mouseOffset.x + "px"; 80 //拖拽元素的中點 81 var xPos = mousePos.x; 82 var yPos = mousePos.y; 83 var havedrop = false; 84 for (var i = 0; i < this.dragreplaceCont.length; i++) { 85 with (this.dragreplaceCont[i]) { 86 if (this.dragreplaceCont[i] == this.curTarget) 87 continue; 88 if ((parseInt(getAttribute('startLeft')) < xPos) && (parseInt(getAttribute('startTop')) < yPos) && ((parseInt(getAttribute('startLeft')) + parseInt(getAttribute('startWidth'))) > xPos) && ((parseInt(getAttribute('startTop')) + parseInt(getAttribute('startHeight'))) > yPos)) { 89 90 this.dropTarget = this.dragreplaceCont[i]; 93 havedrop = true; 94 this.dropTarget.className = 'czYfqmm usr catch'; 97 break; 98 } 99 } 100 } 101 if (!havedrop && this.dropTarget != null) { 102 this.dropTarget.className = 'czYfqmm usr'; 103 this.dropTarget = null; 104 } 105 }//正在拖拽end 106 this.lMouseState = this.iMouseDown; 107 if (this.curTarget) return false; //阻止其它響應(如:鼠標框選文本) 108 }; 109 110 Model.prototype.end = function(event){ 111 if (this.curTarget) { 112 dragHelper.style.display = 'none'; //隱藏輔助層 113 if (this.dropTarget != null) { 114 //有元素接納,兩者互換 115 var datass = this.comp("itemsData"); 116 var rows = datass.find(['name'], [this.curTarget.innerHTML])[0]; 117 var rows1 = datass.find(['name'], [this.dropTarget.innerHTML])[0]; 118 var rowsname = this.curTarget.innerHTML; 119 var rows1name = this.dropTarget.innerHTML; 120 rows.val("name",rows1name); 121 rows1.val("name",rowsname); 122 this.dropTarget.className = 'czYfqmm usr'; 123 this.dropTarget = null; 124 if (this.callbackFunc != null) { 125 this.callbackFunc(this.curTarget); 126 } 127 //如果兩者已替換,則保存數據庫 128 if(rows.row.name.changed && rows1.row.name.changed){ 129 datass.saveData({ 130 "onSuccess" : function(event){ 131 console.log("替換成功"); 132 } 133 }) 134 } 135 } 136 this.curTarget.style.background = 'green'; 137 this.curTarget.style.visibility = 'visible'; 138 this.curTarget.setAttribute('candrag', '1'); 139 } 140 this.curTarget = null; 141 this.iMouseDown = false; 142 this.lMouseState = false; 143 }; 144 145 Model.prototype.mouseCoords = function(ev){//返回鼠標相對頁面左上角的坐標 146 if (ev.pageX || ev.pageY) { 147 return { x: ev.pageX, y: ev.pageY }; 148 } 149 return { 150 x:ev.originalEvent.touches[0].pageX, 151 y:ev.originalEvent.touches[0].pageY 152 }; 153 } 154 Model.prototype.getPosition = function(e){//返回當前item相對頁面左上角的坐標 155 var left = 0; 156 var top = 0; 157 while (e.offsetParent) { 158 left += e.offsetLeft + (e.currentStyle ? (parseInt(e.currentStyle.borderLeftWidth)).NaN0() : 0); 159 top += e.offsetTop + (e.currentStyle ? (parseInt(e.currentStyle.borderTopWidth)).NaN0() : 0); 160 e = e.offsetParent; 161 } 162 return { x: left, y: top }; 163 } 164 Model.prototype.getMouseOffset = function(target, ev){//鼠標位置相對於item的偏移量 165 ev = ev || window.event; 166 var docPos = this.getPosition(target); 167 var mousePos = this.mouseCoords(ev); 168 return { x: mousePos.x - docPos.x, y: mousePos.y - docPos.y }; 169 } 170 171 172 return Model; 173 });
效果圖
如需轉載,請注明出處。