Newer
Older
<div
@dragover.prevent="handleDragOver"
@drop.prevent="handleDrop"
class="grid"
>
<DragContainer
v-for="item in items"
:key="item.key"
:x="item.x"
:y="item.y"
:w="item.w"
:h="item.h"
>
</DragContainer>
import DragContainer from "./DragContainer.vue";
name: "Grid",
components: {
DragContainer,
},
posValidation: {
type: Function,
required: false,
},
positionAllowed(x, y, key) {
for (let item of this.items) {
if (key === item.key) continue;
if (x >= item.x && x < item.x + item.w) {
if (y >= item.y && y < item.y + item.h) {
return false;
}
}
}
if (this.posValidation) return this.posValidation(x, y);
return true;
},
handleDragOver(event) {
let data = event.dataTransfer.getData("vueDrag/gridItem");
let element = JSON.parse(data);
let coords = this.getCoords(event.layerX, event.layerY);
let newPositionValid = true;
for (let x = coords.x; x < coords.x + element.w; x++) {
for (let y = coords.y; y < coords.y + element.h; y++) {
newPositionValid = this.positionAllowed(x, y, element.key);
if (!newPositionValid) break;
}
}
if (!newPositionValid) {
this.$refs.highlight.style.display = "none";
return;
}
this.$refs.highlight.style.display = "block";
this.$refs.highlight.style.gridColumnStart = coords.x + "";
this.$refs.highlight.style.gridRowStart = coords.y + "";
this.$refs.highlight.style.gridColumnEnd = "span " + element.w;
this.$refs.highlight.style.gridRowEnd = "span " + element.h;
},
let data = event.dataTransfer.getData("vueDrag/gridItem");
let element = JSON.parse(data);
console.log(element);
let coords = this.getCoords(event.layerX, event.layerY);
let newPositionValid = true;
for (let x = coords.x; x < coords.x + element.w; x++) {
for (let y = coords.y; y < coords.y + element.h; y++) {
newPositionValid = this.positionAllowed(x, y, element.key);
if (!newPositionValid) break;
}
}
if (!newPositionValid) return;
this.items.splice(
this.items.findIndex((i) => {
return i.key === element.key;
}),
1
);
getCoords(x, y) {
return {
x: Math.ceil(x / (this.$el.offsetWidth / this.cols)),
y: Math.ceil(y / (this.$el.offsetHeight / this.rows)),
};
},
},
data() {
return {
items: [
{ x: 3, y: 3, w: 1, h: 1, key: "obj1" },
{ x: 1, y: 1, w: 1, h: 1, key: "obj2" },
{ x: 4, y: 3, w: 2, h: 2, key: "obj3" },
],
};
},
};
</script>
<style scoped>
#highlight {
background: darkgrey;
border: grey dashed 2px;
display: none;
transition: all 2s ease-in-out;
z-index: -1;
pointer-events: none;
user-select: none;
.grid {
display: grid;
grid-template-columns: repeat(v-bind(cols), 1fr);
grid-template-rows: repeat(v-bind(rows), 1fr);
width: 100%;
height: 100%;
min-width: 100px;
min-height: 100px;
gap: 1em;
}