在本文中將會用Vue完成九宮格拖拽效果,同時介紹一下網格佈局。具體代碼以及demo能夠點如下超連接進入css
傳送門:Demo以及完整代碼鏈接vue
CSS網格佈局(又稱「網格」),是一種二維網格佈局系統。CSS在處理網頁佈局方面一直作的不是很好。一開始咱們用的是table(表格)佈局,而後用float(浮動),position(定位)和inline-block(行內塊)佈局,可是這些方法本質上是hack,遺漏了不少功能,例如垂直居中。後來出了flexbox(盒子佈局),解決了不少佈局問題,可是它僅僅是一維佈局,而不是複雜的二維佈局,實際上它們(flexbox與grid)能很好的配合使用。Grid佈局是第一個專門爲解決佈局問題而建立的CSS模塊.
display:app
grid-template-columns佈局
grid-template-rows學習
grid-template-areasflex
grid-column-gap動畫
grid-row-gapthis
grid-gapflexbox
justify-itemsspa
align-items
固然,若是看不懂也沒關係,這裏有一篇我的十分喜歡的網格佈局的文章。裏面介紹得十分詳細。能夠供你們深刻學習網格佈局內容。
傳送門:Grid佈局指南
Demo地址: Demo以及完整代碼
/*css*/ .container{ position: relative; /*實現定位,使得滑塊定位相對於此*/ display: grid; /*定義網格佈局*/ width: 300px; height: 300px; grid-template-columns: 100px 100px 100px; /*實現九宮格,行列各三*/ grid-template-rows: 100px 100px 100px; grid-template-areas: "head1 head2 head3" /*定義個格子的名稱,方便計算*/ "main1 main2 main3" "footer1 footer2 footer3"; border: 1px solid #000; margin: 0 auto; } .block{ position: absolute; /*相對於container定位*/ width: 100px; height: 100px; display: flex; /*flex佈局,使得文字在中央*/ justify-content: center; justify-items: center; align-items: center; align-content: center; user-select: none; /*用戶不可選定文字*/ background: olivedrab; border: 1px solid #000 }
//app.vue <div id="app"> <div class="container"> <transition > <div class="block animated" :style="{top:this.positionY,left:this.positionX,gridArea:'main2'}" @mousedown="move" ref="block"> {{positionX}} {{positionY}} </div> </transition> </div> </div>
在這裏我選取一些核心代碼出來說解。代碼有所省略,由於代碼着實有點長,太佔篇幅並且沒多大意義,若是須要瀏覽所有代碼能夠點擊上面的Demo鏈接。
<script> //引入animate.css 沒有手撕css動畫,直接用了animate.css實現咱們的動畫效果 import animate from 'animate.css'; export default { name: 'app', data () { return { positionX:0, //定義方塊的兩個座標 positionY:0, } }, methods:{ move(e){ let oDiv = e.target; //獲取點擊的目標元素 let gDiv = e.path[1]; //獲取點擊元素的父級元素 /*獲取點擊時的偏移位置,在這裏要注意一下 **因爲咱們用的是網格佈局,每在一個格子中相對位置都是相對格子來算的,不是相對於父級盒子左上角 **也就是說當你把方塊移動到九個格子中任意一個時,方塊的位置都是top:0和left:0 */ //因此這裏咱們直接取鼠標點擊的位置減去點擊盒子的偏移位置,也就是0 let disX = e.clientX - 0; let disY = e.clientY - 0; document.onmousemove = (e)=>{ //當拖動時,算出的值就恰好是方塊的top和left值 let left = e.clientX - disX; let top = e.clientY - disY; switch (oDiv.style.gridArea){ case "head1 / head1 / head1 / head1":this.rangeOfHead1(left,top,oDiv);break; //實現head1的移動範圍 case "head2 / head2 / head2 / head2":this.rangeOfHead2(left,top,oDiv);break; //實現head2的移動範圍 case "head3 / head3 / head3 / head3":this.rangeOfHead3(left,top,oDiv);break; //實現head3的移動範圍 case "main1 / main1 / main1 / main1":this.rangeOfMain1(left,top,oDiv);break; //實現main1的移動範圍 ... } }; document.onmouseup = (e)=>{ //當鼠標擡起時,咱們要作的事 //經過點擊位置和父級元素的偏移判斷方塊在哪一個區域 if(e.clientY-gDiv.offsetTop<100&&e.clientX-gDiv.offsetLeft<100){ //將方塊移動到該區域中 this.changeBlock("head1",oDiv); }else if(e.clientY-gDiv.offsetTop>100&&e.clientX-gDiv.offsetLeft<100&&e.clientY-gDiv.offsetTop<200){ this.changeBlock("main1",oDiv); }else if(e.clientY-gDiv.offsetTop>200&&e.clientX-gDiv.offsetLeft<100){ this.changeBlock("footer1",oDiv); }else if(e.clientY-gDiv.offsetTop<100&&e.clientX-gDiv.offsetLeft>100&&e.clientX-gDiv.offsetLeft<200){ this.changeBlock("head2",oDiv); }else if(e.clientY-gDiv.offsetTop<100&&e.clientX-gDiv.offsetLeft>200){ this.changeBlock("head3",oDiv); }else if(e.clientY-gDiv.offsetTop>100&&e.clientX-gDiv.offsetLeft>200&&e.clientY-gDiv.offsetTop<200){ this.changeBlock("main3",oDiv); }else if(e.clientY-gDiv.offsetTop>200&&e.clientX-gDiv.offsetLeft>200){ this.changeBlock("footer3",oDiv); }else if(e.clientY-gDiv.offsetTop>200&&e.clientX-gDiv.offsetLeft>100&&e.clientX-gDiv.offsetLeft<200){ this.changeBlock("footer2",oDiv); }else { this.changeBlock("main2",oDiv); } document.onmousemove=null; //須要把事件監聽取消 document.onmousedown = null; //須要把事件監聽取消 //固然,不能忘記咱們的動畫hhh oDiv.className = "block animated wobble"; let removeClass = setTimeout(()=>{ oDiv.className = "block animated"; },500); }; }, rangeOfHead1(x,y,oDiv){ //判斷head1格子中的能夠移動範圍 if(x>=200){ x=200; }else if(x<=0){ x=0; } if(y>=200){ y=200; }else if(y<=0){ y=0; } oDiv.style.left = x + 'px'; oDiv.style.top = y + 'px'; this.positionX = x; this.positionY = y; }, rangeOfHead2(x,y,oDiv){ //判斷head2格子中的能夠移動範圍 if(x>=100){ x=100; }else if(x<=-100){ x=-100; } if(y>=200){ y=200; }else if(y<=0){ y=0; } oDiv.style.left = x + 'px'; oDiv.style.top = y + 'px'; this.positionX = x; this.positionY = y; }, ... changeBlock(blockName,oDiv){ //將方塊移入到對應的區域中 this.positionX = 0; this.positionY = 0; oDiv.style.gridArea=blockName; } }, } </script>
到這裏咱們把九宮格拖拽實現了,同時學習了Grid(網格佈局)。總的作下來,發現用網格佈局作網格拖拽更加費事,可是爲了後續能夠方便一些,也只好搗鼓下來了。到這裏咱們就把基於Vue的九宮格拖拽實現了,有問題或者發現錯誤的請指正,謝謝你們
珍惜淡定的心境,苦事後更加清