使用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

相关文章
相关标签/搜索