vue3 座位選座矩陣布局的實現(xiàn)方法(可點擊選中拖拽調(diào)換位置)
概述
由于公司項目需求需要做一個線上設(shè)置考場相關(guān)的座位布局用于給學(xué)生考機(jī)排號考試,實現(xiàn)教室考場座位布局的矩陣布局,可點擊選中標(biāo)記是否有座無座拖拽調(diào)換位置橫向縱向排列,這塊的邏輯與ui網(wǎng)上很少有參考的價值,作者把這塊邏輯實現(xiàn)了供大家參考
提示:使用vue3+ts實現(xiàn),其邏輯原理也適用于其他技術(shù)棧
代碼邏輯也適用于電影選座矩陣布局等其他項目
先上效果
說明
以公司項目考場座位布局,實現(xiàn)新增矩陣布局需要把考場位置編號等信息通過調(diào)整位置標(biāo)記座位是否有座橫向縱向排列等功能最后把所有修改后的位置數(shù)據(jù)提交給服務(wù)器。
具體需求如下圖:
詳細(xì)
- 思考如何html布局
- 如何生成矩陣、如何給座位標(biāo)記,拖拽調(diào)整位置編號,排列橫向縱向,編輯座位布局時需要帶入后臺座位id標(biāo)識等邏輯處理 實現(xiàn)步驟思路
1. html布局
以左上角為軸,x軸 從左到右方向為列 y軸 從上到下為行 代碼如下:例:x=8,y=8
<div v-for="(row, rowX) in 8" :key="row" class="x"> <div class="y"> <div v-for="(column, columnY) in 8" :key="column" class="site-item"> {{ `${rowX}, ${columnY}` }} </div> </div> </div>
通過html布局,座位有對應(yīng)的(x,y)坐標(biāo),那么對應(yīng)的有座無座標(biāo)記只是控制div背景顯示隱藏,對應(yīng)的拖拽換位編輯以及代入的座位數(shù)據(jù)給服務(wù)器都是操作的數(shù)據(jù)源
2. 生成矩陣
代碼生成(x,y)坐標(biāo)數(shù)據(jù)源model對象數(shù)組 縱向布局
type SiteModel = { x: number y: number seatNo: number //座位號 == 如果沒有賦值為無座 seatId: '' | number //后臺生成的id編號 status?: number //座位狀態(tài) } const sites:Array<SiteModel> = [] for (let x = 0; x < 8; x++) { for (let y = 0; y < 8; y++) { sites.push({ x: x, y: y, seatNo: i + 1, seatId: '' }) } }
注:這里的數(shù)據(jù)源為8*8的縱向布局?jǐn)?shù)據(jù)并且數(shù)據(jù)都有座
3. 座位標(biāo)記
有座無座 因后臺只接受有座位的坐標(biāo)數(shù)據(jù),因此獲取到數(shù)據(jù)源后標(biāo)記無座需要刪除數(shù)據(jù)對應(yīng)的model對象,同理點擊div標(biāo)記有座時需要在數(shù)據(jù)源插入應(yīng)用的此div坐標(biāo)的model對象
以下思路:
1. 創(chuàng)建數(shù)據(jù)源對象數(shù)組時設(shè)置一個Map集合將mode對象中的x,y作為鍵,對象設(shè)置為值
設(shè)置Map是在html布局中需要獲取model對象,不設(shè)置Map也能實現(xiàn),通過x,y坐標(biāo)去遍歷循環(huán)坐標(biāo)數(shù)據(jù)源但這種方式對性能消耗很大
代碼如下:
const _map: Map<string, ExamSiteType> = new Map(); //全局定義一個_map對象 生成矩陣代碼... _map.clear() sites.value.forEach((item) => { _map.set(`${item.x},${item.y}`, item) })
2.有了_map數(shù)據(jù)集合后,就可以在html布局中 實現(xiàn)div點擊事件傳入x,y代碼’標(biāo)記無座’|'標(biāo)記有座’邏輯
const didSeletedItemAction = ( x: number, y: number) => { if (!_map.value.get(`${x},${y}`)) { //添加 sites.value.push({ x: x, y: y, seatNo: 0, seatId: '' }) } else { //刪除.. const item = _map.get(`${x},${y}`) if (item) sites.value.splice(examsits.value.indexOf(item), 1) } }
3.拖拽調(diào)整位置編號
這里需要獲取拖拽相關(guān)事件邏輯,最后只是在拖拽的div以及拖拽到的目標(biāo)上調(diào)換model對象的seatNo編號
實現(xiàn)拖拽相關(guān)代碼
定義starTarget開始拖拽的坐標(biāo){x,y}對象 以及拖拽后的目標(biāo)對象dropTarget
const starTarget = ref({ x: 0, y: 0 }) const dropTarget = ref({ x: 0, y: 0 })
設(shè)置html中draggable=true 綁定事件dragstart dragend drop
//html布局中 <div v-for="(row, rowX) in 8" :key="row" class="x"> <div class="y"> <div v-for="(column, columnY) in 8" :key="column" class="site-item" draggable @dragstart="dragStart($event, rowX, columnY)" @dragend="dragEnd($event, rowX, columnY)" @drop="drop($event, rowX, columnY)"> {{ `${rowX}, ${columnY}` }} </div> </div> </div> <script setup lang="ts"> function dragStart(event: MouseEvent, x: number, y: number) { starTarget.value.x = x starTarget.value.y = y } function dragEnd(event: MouseEvent, x: number, y: number) { starTarget.value.x = 0 starTarget.value.y = 0 } function drop(event: MouseEvent, x: number, y: number) { if (_map.value.get(`${x},${y}`)) { dropTarget.value.x = x dropTarget.value.y = y changeTarget() } } const changeTarget = () => { const site = _map.value.get(`${starTarget.value.x},${starTarget.value.y}`) const dropSite = _map.value.get(`${dropTarget.value.x},${dropTarget.value.y}`) if (site && dropSite) { const temp = site.seatNo site.seatNo = dropSite?.seatNo dropSite.seatNo = temp } } </script>
排列橫向縱向
切換橫向縱向布局主要理解到html布局與div上的x,y坐標(biāo)是不變的,變化的只是座位號碼,故:只需要操作坐標(biāo)對象的數(shù)組通過排序以x (0,0)(1,0),(2,0)... 以y(0,0)(0,1)(0,2)的排列給坐標(biāo)對象重新設(shè)置編號即可
const x_layout = ref(false) //定義是否是橫向布局ref 生成矩陣代碼... if (x_layout.value) { sites.value.sort((a, b) => { if (a.y !== b.y) { return a.y - b.y; } else { return a.x - b.x; } }) } else { sites.value.sort((a, b) => { if (a.x !== b.x) { return a.x - b.x; } else { return a.y - b.y; } }) } //通過排序,重新賦值座位編號 for (let index = 0; index < sites.value.length; index++) { const item = sites.value[index]; item.seatNo = index + 1 }
編輯后臺返回數(shù)據(jù)源時
這里拿到后臺返回的數(shù)據(jù)源遍歷循環(huán)通過_map集合的鍵(x,y)找到model并賦值id即可
if (props.item.examSites) { //后臺服務(wù)器數(shù)據(jù) props.item.examSites.forEach((item) => { const site = _map.get(`${item.x},${item.y}`) if (site) { site.seatId = item.seatId } }) }
最后html布局代碼
通過_map集合獲取(x,y)是否有值動態(tài)賦值class控制顯隱即可 最近發(fā)現(xiàn)不少童鞋私信我源碼,這里我把核心源碼提供出來參考,其余核心參考上面邏輯代碼即可
代碼點擊頂部即可下載 注:部分邏輯已刪除
(刪除的代碼參考文章上面的邏輯即可),代碼可根據(jù)需求自行修改
代碼使用釋列
//使用3 種方式參考: <ExamLayout :items="datas" :type="1" :map="_map"></ExamLayout> <ExamLayout :items="datas" :type="2" :map="_map" :call-back="editExamItem"></ExamLayout> <ExamLayout :items="datas" :type="3" :map="_map" ></ExamLayout> -----------------------------解釋用法:---------------------------------- 使用 `ExamLayout`組件 type //1不能編輯 2可標(biāo)記無座有座 3可拖拽座位 傳入的數(shù)據(jù)源 datas 參考上面邏輯代碼 type ExamSiteType = { coordinateX: number //x坐標(biāo)位置 coordinateY: number //y坐標(biāo)位置 seatNo: number //座位號 == 如果沒有賦值為無座 seatId: '' | number //真實的考試機(jī)器坐標(biāo)位置 status?: number //座位考試狀態(tài) 被舉報 異常 死機(jī)等 } // 數(shù)據(jù)源1 const datas = ref<Array<ExamSiteType>>([ ]) // 初始化 數(shù)據(jù)源 如8行8列 總機(jī)考數(shù) 16臺 function initExamData() { const row: number = 4 const column = 4 const total = 16 examsits.value = [] let i = 0 for (let x = 0; x < row; x++) { for (let y = 0; y < column; y++) { if (i < total) { datas.value.push({ coordinateX: x, coordinateY: y, seatNo: i + 1, seatId: '' }) i++ } } } } initExamData()
到此這篇關(guān)于vue3 座位選座,矩陣布局,可點擊選中拖拽調(diào)換位置的文章就介紹到這了,更多相關(guān)vue3矩陣布局內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
useEffect理解React、Vue設(shè)計理念的不同
這篇文章主要為大家介紹了useEffect理解React、Vue設(shè)計理念的不同詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-09-09Vue調(diào)試工具vue-devtools的安裝與使用
vue-devtools是專門調(diào)試vue項目的調(diào)試工具,安裝成功之后,右邊會出現(xiàn)一個vue,就可以在線可以調(diào)試vue了,下面這篇文章主要給大家介紹了關(guān)于Vue調(diào)試工具vue-devtools的安裝與使用的相關(guān)資料,需要的朋友可以參考下2022-07-07vue中的provide/inject的學(xué)習(xí)使用
本篇文章主要介紹了vue中的provide/inject的學(xué)習(xí)使用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-05-05vue中input標(biāo)簽上傳本地文件或圖片后獲取完整路徑的解決方法
本文給大家介紹vue中input標(biāo)簽上傳本地文件或圖片后獲取完整路徑,如E:\medicineOfCH\stageImage\xxx.jpg,本文給大家分享完美解決方案,感興趣的朋友跟隨小編一起看看吧2023-04-04詳解本地Vue項目請求本地Node.js服務(wù)器的配置方法
本文只針對自己需要本地模擬接口于是搭建一個本地node服務(wù)器供自己測試使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2022-03-03使用Vue+Django+Ant Design做一個留言評論模塊的示例代碼
這篇文章主要介紹了使用Vue+Django+Ant Design做一個留言評論模塊,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06Vue與.net?Core?接收List<T>泛型參數(shù)
這篇文章主要介紹了Vue與.net?Core?接收List<T>泛型參數(shù),文章圍繞主題展開詳細(xì)的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-04-04