使用vue-grid-layout完成桌面拖拽佈局功能

最近在用寫公司項目裏的一個桌面佈局功能 須要使用到vue-grid-layout
看了下網上的 基本上只有demo的使用,這個插件雖然挺不錯可是缺陷也很大.
沒有下邊界,發生碰撞的時候塊會無限的往下移動
https://github.com/jbaysoluti...
先擼一遍demo吧css

<template>
  <grid-layout
    :layout="layout"
    :auto-size="false"
    :col-num="20"
    :row-height="50"
    :max-rows="100"
    :is-draggable="true"
    :is-resizable="false"
    :vertical-compact="false"
    :margin="[10, 10]"
    :use-css-transforms="true"
  >

    <grid-item v-for="item in layout" :key="item.i"
               :x="item.x"
               :y="item.y"
               :w="item.w"
               :h="item.h"
               :i="item.i"
               @resize="resizeEvent"
               @move="moveEvent"
               @resized="resizedEvent"
               @moved="movedEvent"
    >
      {{item.i}}
    </grid-item>
  </grid-layout>
</template>

<script>
  import Vue from 'vue'
  import VueGridLayout from 'vue-grid-layout'
  Vue.use(VueGridLayout)

  var testLayout = [
    {"x":0,"y":0,"w":1,"h":1,"i":"0"},
    {"x":0,"y":1,"w":1,"h":1,"i":"1"},
    {"x":0,"y":2,"w":1,"h":1,"i":"2"},
    {"x":0,"y":3,"w":1,"h":1,"i":"3"},
    {"x":1,"y":0,"w":1,"h":1,"i":"4"},
    {"x":1,"y":1,"w":1,"h":1,"i":"5"},
    {"x":1,"y":2,"w":1,"h":1,"i":"6"},
    {"x":1,"y":3,"w":1,"h":1,"i":"7"},
    {"x":2,"y":0,"w":1,"h":1,"i":"8"},
    {"x":2,"y":1,"w":1,"h":1,"i":"9"},
    {"x":2,"y":2,"w":1,"h":1,"i":"10"},
    {"x":2,"y":3,"w":1,"h":1,"i":"11"},
    {"x":3,"y":0,"w":1,"h":1,"i":"12"},
    {"x":3,"y":1,"w":1,"h":1,"i":"13"},
    {"x":3,"y":2,"w":1,"h":1,"i":"14"},
    {"x":3,"y":3,"w":1,"h":1,"i":"15"},
    {"x":4,"y":0,"w":1,"h":1,"i":"16"},
    {"x":4,"y":1,"w":1,"h":1,"i":"17"},
    {"x":4,"y":2,"w":1,"h":1,"i":"18"},
    {"x":4,"y":3,"w":1,"h":1,"i":"19"}
  ];

  var GridLayout = VueGridLayout.GridLayout;
  var GridItem = VueGridLayout.GridItem;

  export default {
    name: 'Layout',
    components: {
      GridLayout,
      GridItem,
    },
    data () {
      return {
        layout: testLayout,
        newX:0,
        newY:0
      }
    },
    mounted () {

    },
    methods:{
      moveEvent: function(i, newX, newY,e){
        //console.log(e)
        //console.log("MOVE i=" + i + ", X=" + newX + ", Y=" + newY);
      },
      resizeEvent: function(i, newH, newW){
        //console.log("RESIZE i=" + i + ", H=" + newH + ", W=" + newW);
      },
      movedEvent: function(i, newX, newY,e){
        //console.log(e)
        //console.log("MOVED i=" + i + ", X=" + newX + ", Y=" + newY);
      },
      resizedEvent: function(i, newH, newW, newHPx, newWPx){
        //console.log("RESIZED i=" + i + ", H=" + newH + ", W=" + newW + ", H(px)=" + newHPx + ", W(px)=" + newWPx);
      }
    }

  }
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
  .vue-grid-layout {
     position: relative;
     width:800px;
     height:450px;
     /*overflow: hidden;*/
     background: url('../../assets/desktop_background.png') no-repeat;
  }
  .vue-grid-layout>div {
     position: absolute;
     background: indianred;
  }
</style>

隨便寫點樣式 頁面大概是這樣
圖片描述
options裏的vue

  • vertical-compact 是 垂直緊湊佈局 就是拖動留空了 若下方有塊會自動往上補
  • use-css-transforms 是否使用css的transforms來排版 通常默認就行了 爲true時是最終頁面是這樣的

圖片描述
若是是否的話是使用絕對佈局來排版的 和使用transforms排版有一點區別git

看下函數

moveEvent: function(i, newX, newY,e){
        //console.log("MOVE i=" + i + ", X=" + newX + ", Y=" + newY);
      },
      resizeEvent: function(i, newH, newW){
        //console.log("RESIZE i=" + i + ", H=" + newH + ", W=" + newW);
      },
      movedEvent: function(i, newX, newY,e){
        //console.log("MOVED i=" + i + ", X=" + newX + ", Y=" + newY);
      },
      resizedEvent: function(i, newH, newW, newHPx, newWPx){
        //console.log("RESIZED i=" + i + ", H=" + newH + ", W=" + newW + ", H(px)=" + newHPx + ", W(px)=" + newWPx);
      }

如今用到的是moveEvent和movedEvent 一個是移動時就觸發 一個是移動完成 鬆開鼠標的時候觸發
能夠經過這兩個事件中的i用來搞事情github

敲黑板劃重點

修改下grid-item裏 增長watchitemsegmentfault

<grid-item v-for="item in layout" :key="item.i"
               :item="watchitem(item)"
               :x="item.x"
               :y="item.y"
               :w="item.w"
               :h="item.h"
               :i="item.i"
               @resize="resizeEvent"
               @move="moveEvent"
               @resized="resizedEvent"
               @moved="movedEvent"
    >
      {{item.i}}
    </grid-item>

在methods 裏增長 watchitem函數

watchitem:function(item) {
        if(item.y>y_max ||item.x>x_max){
            item.y=
            item.x=
        }
        return item
    }

這邊經過移動完後快速遍歷每個item的信息來修改後 達到本身所需的效果佈局

如今的效果是當你移動一個box時 即便你沒鬆開鼠標 每個被你移動中碰撞到的box都會發生改變 這可能不是咱們想要的 能夠建立一個historyLayout 拿來記錄咱們上一步的佈局 咱們在watchitem()裏比較 若是不是當前操做的box 使其的位置保持不變,在moved()中調用一個調整位置的函數 使其能夠達到 兩兩調換的效果 以及其餘的移動效果 想了解的能夠點擊這裏 this

還有一個比較須要注意的是針對對象的操做會比較多 對其操做時須要注意 更改的是自己的值仍是引用值url

最後大概實現成這樣 有能力的大神仍是本身寫一套比較好
圖片描述spa

相關文章
相關標籤/搜索