本文演示 vue-grid-layout 外部拖入单元格。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>vue-grid-layout vue umd版本</title>
<meta name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=no, minimal-ui">
<script src="https://www.itxst.com/package/vue/vue.min.js"></script>
<script src="https://www.itxst.com/package/vue-grid-layout/vue-grid-layout.umd.min.js"></script>
</head>
<body style="padding:10px;">
<div id="app">
<div @drag="drag" @dragend="dragend" class="droppable-element" draggable="true" unselectable="on">点击拖动me</div>
<div id="content">
<grid-layout ref="gridlayout" :layout.sync="layout" :col-num="12" :row-height="30">
<grid-item v-for="item in layout" :x="item.x" :y="item.y" :w="item.w" :h="item.h" :i="item.i"
:key="item.i">
{{item.i}}
</grid-item>
</grid-layout>
</div>
</div>
<script>
let mouseXY = { "x": null, "y": null };
let DragPos = { "x": null, "y": null, "w": 1, "h": 1, "i": null };
var app = new Vue({
el: '#app',
components: {
GridLayout: VueGridLayout.GridLayout,
GridItem: VueGridLayout.GridItem
},
data() {
return {
layout: [
{ "x": 0, "y": 0, "w": 2, "h": 2, "i": "0" },
{ "x": 2, "y": 0, "w": 2, "h": 2, "i": "1" },
{ "x": 4, "y": 0, "w": 2, "h": 2, "i": "2" },
{ "x": 0, "y": 1, "w": 6, "h": 2, "i": "3" },
]
};
},
mounted() {
document.addEventListener("dragover", function (e) {
mouseXY.x = e.clientX;
mouseXY.y = e.clientY;
}, false);
},
beforeDestroy() {
},
methods: {
drag: function (e) {
let parentRect = document.getElementById('content').getBoundingClientRect();
let mouseInGrid = false;
if (((mouseXY.x > parentRect.left) && (mouseXY.x < parentRect.right)) && ((mouseXY.y > parentRect.top) && (mouseXY.y < parentRect.bottom))) {
mouseInGrid = true;
}
if (mouseInGrid === true && (this.layout.findIndex(item => item.i === 'drop')) === -1) {
this.layout.push({
x: (this.layout.length * 2) % (this.colNum || 12),
y: this.layout.length + (this.colNum || 12), // puts it at the bottom
w: 1,
h: 1,
i: 'drop',
});
}
let index = this.layout.findIndex(item => item.i === 'drop');
if (index !== -1) {
try {
this.$refs.gridlayout.$children[this.layout.length].$refs.item.style.display = "none";
} catch {
}
let el = this.$refs.gridlayout.$children[index];
el.dragging = { "top": mouseXY.y - parentRect.top, "left": mouseXY.x - parentRect.left };
let new_pos = el.calcXY(mouseXY.y - parentRect.top, mouseXY.x - parentRect.left);
if (mouseInGrid === true) {
this.$refs.gridlayout.dragEvent('dragstart', 'drop', new_pos.x, new_pos.y, 1, 1);
DragPos.i = String(index);
DragPos.x = this.layout[index].x;
DragPos.y = this.layout[index].y;
}
if (mouseInGrid === false) {
this.$refs.gridlayout.dragEvent('dragend', 'drop', new_pos.x, new_pos.y, 1, 1);
this.layout = this.layout.filter(obj => obj.i !== 'drop');
}
}
},
dragend: function (e) {
let parentRect = document.getElementById('content').getBoundingClientRect();
let mouseInGrid = false;
if (((mouseXY.x > parentRect.left) && (mouseXY.x < parentRect.right)) && ((mouseXY.y > parentRect.top) && (mouseXY.y < parentRect.bottom))) {
mouseInGrid = true;
}
if (mouseInGrid === true) {
alert(`Dropped element props:\n${JSON.stringify(DragPos, ['x', 'y', 'w', 'h'], 2)}`);
this.layout = this.layout.filter(obj => obj.i !== 'drop');
//************ 添加到拖动的目标位置
this.layout.push({
x: DragPos.x,
y: DragPos.y,
w: 1,
h: 1,
i: DragPos.i,
});
this.$refs.gridLayout.dragEvent('dragend', DragPos.i, DragPos.x, DragPos.y, 1, 1);
try {
this.$refs.gridLayout.$children[this.layout.length].$refs.item.style.display = "block";
} catch {
}
}
},
}
});
</script>
<style scoped>
.droppable-element {
width: 120px;
text-align: center;
background: #fdd;
border: 1px solid black;
margin: 10px 0;
padding: 10px;
}
.vue-grid-layout {
background: #eee;
}
.vue-grid-item:not(.vue-grid-placeholder) {
background: #ccc;
border: 1px solid black;
}
.vue-grid-item .resizing {
opacity: 0.9;
}
.vue-grid-item .static {
background: #cce;
}
.vue-grid-item .text {
font-size: 24px;
text-align: center;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
margin: auto;
height: 100%;
width: 100%;
}
.vue-grid-item .no-drag {
height: 100%;
width: 100%;
}
.vue-grid-item .minMax {
font-size: 12px;
}
.vue-grid-item .add {
cursor: pointer;
}
.vue-draggable-handle {
position: absolute;
width: 20px;
height: 20px;
top: 0;
left: 0;
background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='10'><circle cx='5' cy='5' r='5' fill='#999999'/></svg>") no-repeat;
background-position: bottom right;
padding: 0 8px 8px 0;
background-repeat: no-repeat;
background-origin: content-box;
box-sizing: border-box;
cursor: pointer;
}
</style>
</body>
</html>