摘要:上一周學(xué)了閉包和模塊,這一周仍然是跟著波同學(xué),試著封裝了一個(gè)拖拽模塊。
上一周學(xué)了閉包和模塊,這一周仍然是跟著@波同學(xué),試著封裝了一個(gè)拖拽模塊。過程中經(jīng)歷了一些曲折,最開始我是打算只用style.left的方式,但是這個(gè)需要設(shè)置position:absolute。可能對代碼造成一定影響。雖然CSS的transform會影響兼容,但這里我還是使用了這個(gè)屬性的translate來完成移動。只用style完成的代碼
話不多說,直接上代碼:
html和css,這里必須設(shè)置position,第一次寫這段代碼的時(shí)候忘了,結(jié)果盡管JS寫對了,效果完全出不來....真是短路了
重點(diǎn)!!JS學(xué)習(xí)
; //這個(gè)分號是為了防止其他的模塊最后忘記加分號,導(dǎo)致錯(cuò)誤。 (function() { //構(gòu)造函數(shù),屬于每一個(gè)實(shí)例 function Drag(selector) { this.elem = typeof selector == "object" ? selector : document.getElementById(selector); //鼠標(biāo)初始位置 this.startX = 0; this.startY = 0; //元素初始位置 this.sourceX = 0; this.sourceY = 0; this.init(); } //原型,共有的 Drag.prototype = { constructor: Drag, init: function() { this.setDrag(); }, //用于獲取元素當(dāng)前的位置信息 getPosition: function() { var that = this; var pos = {}; pos = { x: that.elem.offsetLeft, y: that.elem.offsetTop }; return pos; }, //用來設(shè)置當(dāng)前元素的位置 setPosition: function(pos) { this.elem.style.left = pos.x + "px"; this.elem.style.top = pos.y + "px"; }, //該方法用來綁定事件 setDrag: function() { var self = this; this.elem.addEventListener("mousedown", start, false); function start(event) { self.startX = event.pageX; self.startY = event.pageY; var pos = self.getPosition(); self.sourceX = pos.x; self.sourceY = pos.y; document.addEventListener("mousemove", move, false); document.addEventListener("mouseup", end, false); } function move(event) { //總體思想:鼠標(biāo)距瀏覽器距-鼠標(biāo)距元素距離 var currentX = event.pageX; //當(dāng)前的鼠標(biāo)x位置 var currentY = event.pageY; //當(dāng)前的鼠標(biāo)y位置 var distanceX = currentX - self.startX; //鼠標(biāo)移動的距離x var distanceY = currentY - self.startY; //鼠標(biāo)移動的距離y self.setPosition({ x: self.sourceX + distanceX, y: self.sourceY + distanceY }); } function end(event) { document.removeEventListener("mousemove", move); document.removeEventListener("mouseup", end); } } }; //暴露在外 window.Drag = Drag; })(); new Drag("box");
這段代碼是比較好理解的,在一開始看波大神的代碼時(shí),對于translate的運(yùn)用實(shí)際上我沒看太明白,因?yàn)闆]想到為啥要用到正則......
雖然比較簡單,但是我們還是要分析一下這段代碼的原理:
1.自執(zhí)行函數(shù)里有一個(gè)構(gòu)造函數(shù)Drag(),在構(gòu)造函數(shù)里我們設(shè)置的方法和屬性時(shí)每一個(gè)構(gòu)造函數(shù)實(shí)例獨(dú)有的,比如他們的位置信息等。而在原型里的有三個(gè)方法:分別是獲取元素位置信息的getPosition()、設(shè)置元素位置的setPosition()和綁定事件的setDrag(),這三個(gè)因?yàn)槭枪玫模瑸榱斯?jié)省資源,我們就放在原型里了。
2.這段代碼執(zhí)行的原理是:當(dāng)鼠標(biāo)按下時(shí),獲取元素初始位置信息sourceX/Y、鼠標(biāo)初始位置信息startX/Y;當(dāng)鼠標(biāo)移動完成時(shí),獲取鼠標(biāo)新的位置currentX/Y,兩個(gè)鼠標(biāo)位置相減就能得到鼠標(biāo)移動的距離distanceX/Y,這同時(shí)也是元素移動的距離,然后,我們把這個(gè)值賦給元素的style.left/top。元素的拖拽就實(shí)現(xiàn)了。
transform和style的結(jié)合由于技術(shù)的發(fā)展,越來越多的設(shè)備開始支持CSS3了,加上style的資源占用的更多,效率方面存在問題,所以我們考慮使用transform。瀏覽器的兼容寫法
我們首先在函數(shù)Drag()前加上私有屬性:
var transform = getTransform();
在下面再加上私有方法:
function getTransform() { var transform = "", divStyle = document.createElement("div").style, transformArr = ["transform", "webkitTransform", "MozTransform", "msTransform", "oTransform"], i = 0, l = transformArr.length; for (; i < l; i++) { if (transformArr[i] in divStyle) { return transform = transformArr[i]; } } return transform; }PS:記住createElement()這個(gè)方法,下次判斷瀏覽器兼容時(shí)用得著!
我們還需要在getPosition()的下面加上一個(gè)函數(shù),用同樣的形式:
getTranslate: function() { var val = {}; var transformValue = document.defaultView.getComputedStyle(this.elem, false)[transform]; if(transformValue=="none"){ val={x:0,y:0}; }else{ var transformArr = transformValue.match(/-?d+/g); val = { x: Number(transformArr[4]), y: Number(transformArr[5]) }; } return val; },PS:之所以要判斷transformValue是否為none,是因?yàn)樵诔跏蓟癄顟B(tài)是,元素未被設(shè)置transform屬性,這樣正則之后的數(shù)組是找不到[4][5] 的,所以我們讓val的兩個(gè)屬性為0,也就是稍后會成為的transform的translateX和translateY的值。
繼續(xù)寫代碼。上面一段我們用來提取translate的X、Y值。看下面一段:
getPosition: function() { var that = this; var pos = {}; if(transform){ var val=this.getTranslate(); pos={ x:val.x, y:val.y }; }else{ pos = { x: that.elem.offsetLeft, y: that.elem.offsetTop }; } return pos; },注意上面一段代碼我們修改的的內(nèi)容,在這里我們增加了一個(gè)判斷:即當(dāng)支持transform屬性的瀏覽器存在時(shí),我們會用transform屬性修改元素的值,把之前在getTranslate中得到的x、y賦值給pos的x、y。
在上面一段代碼中,我們會根據(jù)瀏覽器的情況,用不同的方法取到相同的值,val的值來自getTranslate(),是我們從元素的transform中提取出來的。同樣,在下面的setPosition()中,我們也要設(shè)置if判斷。
setPosition: function(pos) { if (transform) { this.elem.style[transform] = "translate(" + pos.x + "px" + "," + pos.y + "px)"; } else { this.elem.style.left = pos.x + "px"; this.elem.style.top = pos.y + "px"; } },
這一段沒什么好講的,就是用不同的形式賦值而已。
到這里,這個(gè)模塊就封裝完畢了。接下來讓我們看看完整代碼:
; (function() { //私有屬性 var transform = getTransform(); //構(gòu)造函數(shù),屬于每一個(gè)實(shí)例 function Drag(selector) { this.elem = typeof selector == "object" ? selector : document.getElementById(selector); //鼠標(biāo)初始位置 this.startX = 0; this.startY = 0; //元素初始位置 this.sourceX = 0; this.sourceY = 0; this.init(); } //原型,共有的 Drag.prototype = { constructor: Drag, init: function() { this.setDrag(); }, //用于獲取元素當(dāng)前的位置信息 getPosition: function() { var that = this; var pos = {}; if(transform){ var val=this.getTranslate(); pos={ x:val.x, y:val.y }; }else{ pos = { x: that.elem.offsetLeft, y: that.elem.offsetTop }; } return pos; }, //獲取translate值 getTranslate: function() { var val = {}; var transformValue = document.defaultView.getComputedStyle(this.elem, false)[transform]; if(transformValue=="none"){ val={x:0,y:0}; }else{ var transformArr = transformValue.match(/-?d+/g); val = { x: Number(transformArr[4]), y: Number(transformArr[5]) }; } return val; }, //用來設(shè)置當(dāng)前元素的位置 setPosition: function(pos) { if (transform) { this.elem.style[transform] = "translate(" + pos.x + "px" + "," + pos.y + "px)"; } else { this.elem.style.left = pos.x + "px"; this.elem.style.top = pos.y + "px"; } }, //該方法用來綁定事件 setDrag: function() { var self = this; this.elem.addEventListener("mousedown", start, false); function start(event) { self.startX = event.pageX; self.startY = event.pageY; var pos = self.getPosition(); self.sourceX = pos.x; self.sourceY = pos.y; document.addEventListener("mousemove", move, false); document.addEventListener("mouseup", end, false); } function move(event) { //總體思想:鼠標(biāo)距瀏覽器距-鼠標(biāo)距元素距離 var currentX = event.pageX; //當(dāng)前的鼠標(biāo)x位置 var currentY = event.pageY; //當(dāng)前的鼠標(biāo)y位置 var distanceX = currentX - self.startX; //鼠標(biāo)移動的距離x var distanceY = currentY - self.startY; //鼠標(biāo)移動的距離y self.setPosition({ x: self.sourceX + distanceX, y: self.sourceY + distanceY }); } function end(event) { document.removeEventListener("mousemove", move); document.removeEventListener("mouseup", end); } } }; //私有方法,用來獲取transform的兼容寫法 function getTransform() { var transform = "", divStyle = document.createElement("div").style, transformArr = ["transform", "webkitTransform", "MozTransform", "msTransform", "oTransform"], i = 0, l = transformArr.length; for (; i < l; i++) { if (transformArr[i] in divStyle) { return transform = transformArr[i]; } } return transform; } //暴露在外 window.Drag = Drag; })(); new Drag("box");
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/107087.html
摘要:一背景業(yè)務(wù)組件化或者叫模塊化作為移動端應(yīng)用架構(gòu)的主流方式之一,近年來一直是業(yè)界積極探索和實(shí)踐的方向。有贊移動團(tuán)隊(duì)自年起也在不斷嘗試各種組件化方案,在有贊微商城,有贊零售,有贊美業(yè)等多個(gè)應(yīng)用中進(jìn)行了實(shí)踐。相比組件,個(gè)人感覺稱之為模塊更為合適。 一、背景 業(yè)務(wù)組件化(或者叫模塊化)作為移動端應(yīng)用架構(gòu)的主流方式之一,近年來一直是業(yè)界積極探索和實(shí)踐的方向。有贊移動團(tuán)隊(duì)自16年起也在不斷嘗試各種...
摘要:前面幾篇文章,我跟大家分享了的一些基礎(chǔ)知識,這篇文章,將會進(jìn)入第一個(gè)實(shí)戰(zhàn)環(huán)節(jié)利用前面幾章的所涉及到的知識,封裝一個(gè)拖拽對象。不封裝對象直接實(shí)現(xiàn)利用原生封裝拖拽對象通過擴(kuò)展來實(shí)現(xiàn)拖拽對象。 showImg(https://segmentfault.com/img/remote/1460000008699587); 前面幾篇文章,我跟大家分享了JavaScript的一些基礎(chǔ)知識,這篇文章,...
摘要:也是的獨(dú)特性,使得組件化成為了可能。簡單的說就是組件內(nèi)部標(biāo)簽對內(nèi)語義化,組件自定義標(biāo)簽對外語義化對內(nèi)語義化保存自定義標(biāo)簽具有正確的語義,自定義標(biāo)簽對外語義是對內(nèi)部標(biāo)簽組合出的功能概括。 組件化 這里首先介紹WebComponents標(biāo)準(zhǔn),以下為騰訊alloyteam團(tuán)隊(duì)的一篇文章里的內(nèi)容。 模板能力,WebComponent提供原生的模板能力 ShadowDOm封裝組件獨(dú)立的內(nèi)部結(jié)構(gòu)...
摘要:重試會增加的響應(yīng)時(shí)間。提供了輔助方法來為包含遠(yuǎn)程調(diào)用的函數(shù)式接口或表達(dá)式創(chuàng)建裝飾器。如果我們想創(chuàng)建一個(gè)裝飾器并在代碼庫的不同位置重用它,我們將使用。 在本文中,我們將從快速介紹 Resilience4j 開始,然后深入探討其 Retry 模塊。我們將了解何時(shí)、如何使用它,以及它提供的功能。在此過程中,我們還將學(xué)...
摘要:下面列舉了游戲開發(fā)中常見的崗位以及兩條常見的協(xié)作開發(fā)的流水線其實(shí)學(xué)習(xí)游戲引擎,前期對于任何崗位來說路線都是相似的,基本上就是一個(gè)熟悉基本操作理解基本概念拓展專業(yè)知識的過程。當(dāng)然這不是絕對的,任何引擎的開始階段和大成階段都是相似的。 這是【游戲開發(fā)那些事】第51篇原創(chuàng) 前言:游戲引擎,表面...
閱讀 3095·2021-10-13 09:40
閱讀 3945·2021-09-22 15:51
閱讀 1493·2021-09-22 15:48
閱讀 1060·2021-09-06 15:00
閱讀 1790·2019-08-30 15:43
閱讀 2356·2019-08-29 18:35
閱讀 1667·2019-08-29 16:18
閱讀 3612·2019-08-29 12:49