摘要:類似于吸附效果代碼修改組件之間的沖突檢測(cè)首先是組件之間的沖突檢測(cè),組件與組件的邊界檢測(cè)需要一個(gè)標(biāo)記進(jìn)行判斷。是否開啟元素對(duì)齊當(dāng)調(diào)用對(duì)齊時(shí),用來(lái)設(shè)置組件與組件之間的對(duì)齊距離,以像素為單位。如果發(fā)現(xiàn)什么或者可以將代碼優(yōu)化的地方請(qǐng)勞煩告知我。
Vue 用于可調(diào)整大小和可拖動(dòng)元素的組件并支持組件之間的沖突檢測(cè)與組件對(duì)齊更新2.0版本
說(shuō)明:組件基于vue-draggable-resizable進(jìn)行二次開發(fā)
距離上1.7版本版本的修改已經(jīng)過(guò)去快一年的時(shí)間了,原版組件在之前已經(jīng)更新到了2.0版本。
雖然之前適配過(guò)舊版組件,但是因?yàn)?.0版本原作者對(duì)代碼進(jìn)行了重構(gòu),原來(lái)修改的代碼照搬是不可能的了。
所以也就一直沒(méi)有將沖突檢測(cè)以及吸附對(duì)齊功能適配到2.0版本,最近正好有時(shí)間就適配一下。
新增特征
沖突檢測(cè)
吸附對(duì)齊
默認(rèn)樣式優(yōu)化
功能預(yù)覽 項(xiàng)目地址https://github.com/gorkys/vue...
如果喜歡該項(xiàng)目,歡迎Star前言
17年就應(yīng)用此組件到了項(xiàng)目中,當(dāng)時(shí)正式版的功能不能滿足項(xiàng)目需求,還拉取了dev分支的測(cè)試版進(jìn)行了簡(jiǎn)單的更改。(項(xiàng)目中主要功能之一需要用到此組件)特征
今年因?yàn)樾枨笞兏?,?xiàng)目重構(gòu)(手動(dòng)淚奔),然后去看了看github,該組件的正式版本更新到了1.7.x,于是把正式版拉下來(lái)根據(jù)自己的需求進(jìn)行了修改并發(fā)布新版到npm上。
沒(méi)有依賴
可拖動(dòng),可調(diào)整大小或者兩者都行
擁有用于調(diào)整大小的控制點(diǎn)
限制組件調(diào)整大小和移動(dòng)超出父元素
自定義網(wǎng)格移動(dòng)
將拖動(dòng)限制為垂直或水平移動(dòng)
新增特征
組件之間的沖突檢測(cè)(不允許組件之間重疊)
組件與組件之間進(jìn)行對(duì)齊(類似于吸附效果)
項(xiàng)目地址原組件地址:vue-draggable-resizable
新組件地址:vue-draggable-resizable
npm install --save vue-draggable-resizable-gorkys
更多API請(qǐng)?jiān)陧?xiàng)目說(shuō)明文檔中查看
DemoDemo
修改過(guò)程記錄 提出建議在原組件的Issues中提出了建議,作者表示不打算讓此組件進(jìn)行跨越組件之外的操作。Clone項(xiàng)目
好吧,既然作者不打算進(jìn)行這方面的支持,那只好自己動(dòng)手了。
Fork項(xiàng)目到自己的倉(cāng)庫(kù),然后Clone項(xiàng)目到本地進(jìn)行修改。
需求說(shuō)明1.組件之間的沖突檢測(cè)
兩個(gè)組件不允許重疊,如果重疊,將回到移動(dòng)或縮放前位置
2.組件與組件之間進(jìn)行對(duì)齊(參照J(rèn)query UI的draggable)
用戶移動(dòng)一個(gè)組件到另一個(gè)組件邊緣的時(shí)候,進(jìn)行對(duì)齊操作。類似于吸附效果代碼修改 1.組件之間的沖突檢測(cè)
首先是組件之間的沖突檢測(cè),組件與組件的邊界檢測(cè)需要一個(gè)標(biāo)記進(jìn)行判斷。
先在props中加入一個(gè)isConflictCheck,讓使用者自己選擇是否使用此功能。
props:{ /* 定義組件是否開啟沖突檢測(cè) */ isConflictCheck: { type: Boolean, default: false } ... }
當(dāng)我們拿到isConflictCheck后,在setConflictCheck方法中給組件的Dom設(shè)置一個(gè)data-*的屬性。
setConflictCheck: function () { if (this.isConflictCheck) { this.$el.setAttribute("data-is-check", "true") } else { this.$el.setAttribute("data-is-check", "false") } }
然后就是如何去檢測(cè)組件之間的沖突,代碼如下,此代碼是在測(cè)試版本中使用的,看到這些判斷都可怕,為了頭發(fā),就沒(méi)有去優(yōu)化了(反正能使用)。
conflictCheck: function () { if (this.isConflictCheck) { let p = this.$el.parentNode.childNodes // 獲取當(dāng)前父節(jié)點(diǎn)下所有子節(jié)點(diǎn) if (p.length > 1) { for (let i = 0; i < p.length; i++) { if (p[i] !== this.$el && p[i].className !== undefined && p[i].getAttribute("data-is-check") !== "false") { let tw = p[i].offsetWidth let th = p[i].offsetHeight let tl = p[i].offsetLeft let tt = p[i].offsetTop // 如果沖突,就將回退到移動(dòng)前的位置 if (this.top >= tt && this.left >= tl && tt + th > this.top && tl + tw > this.left || this.top <= tt && this.left < tl && this.top + this.height > tt && this.left + this.width > tl) { /* 左上角與右下角重疊 */ this.top = this.restoreY this.left = this.restoreX this.width = this.restoreW this.height = this.restoreH } else if (this.left <= tl && this.top >= tt && this.left + this.width > tl && this.top < tt + th || this.top < tt && this.left > tl && this.top + this.height > tt && this.left < tl + tw) { /* 右上角與左下角重疊 */ this.top = this.restoreY this.left = this.restoreX this.width = this.restoreW this.height = this.restoreH } else if (this.top < tt && this.left <= tl && this.top + this.height > tt && this.left + this.width > tl || this.top > tt && this.left >= tl && this.top < tt + th && this.left < tl + tw) { /* 下邊與上邊重疊 */ this.top = this.restoreY this.left = this.restoreX this.width = this.restoreW this.height = this.restoreH } else if (this.top <= tt && this.left >= tl && this.top + this.height > tt && this.left < tl + tw || this.top >= tt && this.left <= tl && this.top < tt + th && this.left > tl + tw) { /* 上邊與下邊重疊(寬度不一樣) */ this.top = this.restoreY this.left = this.restoreX this.width = this.restoreW this.height = this.restoreH } else if (this.left >= tl && this.top >= tt && this.left < tl + tw && this.top < tt + th || this.top > tt && this.left <= tl && this.left + this.width > tl && this.top < tt + th) { /* 左邊與右邊重疊 */ this.top = this.restoreY this.left = this.restoreX this.width = this.restoreW this.height = this.restoreH } else if (this.top <= tt && this.left >= tl && this.top + this.height > tt && this.left < tl + tw || this.top >= tt && this.left <= tl && this.top < tt + th && this.left + this.width > tl) { /* 左邊與右邊重疊(高度不一樣) */ this.top = this.restoreY this.left = this.restoreX this.width = this.restoreW this.height = this.restoreH } } } } } }, // 沖突檢測(cè)
最后就是在停止移動(dòng)和縮放時(shí)調(diào)用上面的方法就可以了(代碼精簡(jiǎn)過(guò))。
handleUp: function (e) { this.handle = null if (this.resizing) { this.resizing = false this.conflictCheck() // 沖突檢測(cè) } if (this.dragging) { this.dragging = false this.conflictCheck() // 沖突檢測(cè) } } // 鼠標(biāo)松開2.組件與組件之間進(jìn)行對(duì)齊
與沖突檢測(cè)一樣的套路。
先在props中加入一個(gè)snap,讓使用者自己選擇是否使用此功能。為了更靈活,這里多添加了一個(gè)snapTolerance,當(dāng)調(diào)用對(duì)齊時(shí),用來(lái)設(shè)置組件與組件之間的對(duì)齊距離,以像素為單位。
/* 是否開啟元素對(duì)齊 */ snap: { type: Boolean, default: false }, /* 當(dāng)調(diào)用對(duì)齊時(shí),用來(lái)設(shè)置組件與組件之間的對(duì)齊距離,以像素為單位。 */ snapTolerance: { type: Number, default: 5, validator: function (val) { return typeof val === "number" }
然后就是設(shè)置data-*屬性
setSnap: function () { if (this.snap) { this.$el.setAttribute("data-is-snap", "true") } else { this.$el.setAttribute("data-is-snap", "false") } }, // 設(shè)置對(duì)齊元素
再然后就是主要方法snapCheck的編寫。這里我翻看了一下JQuery UI中的draggable源碼,并近乎copy的借鑒了過(guò)來(lái)。
snapCheck: function () { if (this.snap) { let p = this.$el.parentNode.childNodes // 獲取當(dāng)前父節(jié)點(diǎn)下所有子節(jié)點(diǎn) if (p.length > 1) { let x1 = this.left let x2 = this.left + this.width let y1 = this.top let y2 = this.top + this.height for (let i = 0; i < p.length; i++) { if (p[i] !== this.$el && p[i].className !== undefined && p[i].getAttribute("data-is-snap") !== "false") { let l = p[i].offsetLeft // 對(duì)齊目標(biāo)的left let r = l + p[i].offsetWidth // 對(duì)齊目標(biāo)右側(cè)距離窗口的left let t = p[i].offsetTop// 對(duì)齊目標(biāo)的top let b = t + p[i].offsetHeight // 對(duì)齊目標(biāo)右側(cè)距離窗口的top let ts = Math.abs(t - y2) <= this.snapTolerance let bs = Math.abs(b - y1) <= this.snapTolerance let ls = Math.abs(l - x2) <= this.snapTolerance let rs = Math.abs(r - x1) <= this.snapTolerance if (ts) { this.top = t - this.height } if (bs) { this.top = b } if (ls) { this.left = l - this.width } if (rs) { this.left = r } } } } } }, // 檢測(cè)對(duì)齊元素
好了,最后就是在鼠標(biāo)移動(dòng)組件時(shí)及時(shí)調(diào)用就可以了。
handleMove: function (e) { ... this.snapCheck() this.$emit("dragging", this.left, this.top) } }, // 鼠標(biāo)移動(dòng)總結(jié)
這次的修改還算是非常順利,順便還把之前的一些代碼進(jìn)行了優(yōu)化。
如果發(fā)現(xiàn)什么bug或者可以將代碼優(yōu)化的地方請(qǐng)勞煩告知我。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/97874.html
摘要:注意點(diǎn)在鼠標(biāo)操作拖放期間,有一些事件可能觸發(fā)多次,比如和??赏献г?,建議使用,設(shè)定可拖拽元素的鼠標(biāo)游標(biāo),提升交互。在中使用拖拽中使用可以直接綁定到組件上。 什么是 Drag and Drop (拖放)? 簡(jiǎn)單來(lái)說(shuō),HTML5 提供了 Drag and Drop API,允許用戶用鼠標(biāo)選中一個(gè)可拖動(dòng)元素,移動(dòng)鼠標(biāo)拖放到一個(gè)可放置到元素的過(guò)程。 我相信每個(gè)人都或多或少接觸過(guò)拖放,比如瀏覽...
摘要:哪吒別人的看法都是狗屁,你是誰(shuí)只有你自己說(shuō)了才算,這是爹教我的道理。哪吒去他個(gè)鳥命我命由我,不由天是魔是仙,我自己決定哪吒白白搭上一條人命,你傻不傻敖丙不傻誰(shuí)和你做朋友太乙真人人是否能夠改變命運(yùn),我不曉得。我只曉得,不認(rèn)命是哪吒的命。 showImg(https://segmentfault.com/img/bVbwiGL?w=900&h=378); 出處 查看github最新的Vue...
摘要:最近公司新加需求實(shí)現(xiàn)彈窗可拖拽還要拖拽寬高變化國(guó)際慣例先上圖瀏覽器下作的有幾個(gè)點(diǎn)需要注意一下每個(gè)彈窗都要有唯一可操作指令可以做到拖拽時(shí)要添加可拖拽區(qū)塊由于組件在設(shè)計(jì)時(shí)寬度用了百分比這里不同瀏覽器有兼容性問(wèn)題實(shí)現(xiàn)拖拽寬高時(shí)獲取邊緣問(wèn)題定位設(shè) 最近公司新加需求, 實(shí)現(xiàn)彈窗可拖拽, 還要拖拽寬高變化. 國(guó)際慣例先上圖: edge瀏覽器下作的gif http://www.lano...
摘要:利用實(shí)現(xiàn)圖片裁剪效果圖實(shí)現(xiàn)思路打開圖片并將圖片繪制到中利用的函數(shù)來(lái)裁剪圖片將轉(zhuǎn)化為即可。巨坑轉(zhuǎn)化為圖片確認(rèn)截圖確認(rèn)截圖參考文章我是,年輕的前端攻城獅一枚,愛(ài)專研,愛(ài)技術(shù),愛(ài)分享。文章有任何問(wèn)題歡迎大家指出,也歡迎大家一起交流前端各種問(wèn)題 利用Canvas實(shí)現(xiàn)圖片裁剪 效果圖 showImg(https://segmentfault.com/img/bVburJ2?w=864&h=706...
閱讀 3107·2021-11-25 09:43
閱讀 1073·2021-11-24 10:22
閱讀 1421·2021-09-22 15:26
閱讀 735·2019-08-30 15:44
閱讀 2518·2019-08-29 16:33
閱讀 3783·2019-08-26 18:42
閱讀 960·2019-08-23 18:07
閱讀 1887·2019-08-23 17:55