<template> <div @dragover.prevent @drop.prevent="handleDrop" class="grid"> <slot name="highlight"> <div id="highlight"></div> </slot> <DragContainer v-for="item in items" :key="item.key" :drag-i-d="item.key" :x="item.x" :y="item.y" :w="item.w" :h="item.h" > </DragContainer> </div> </template> <script> import DragContainer from "./DragContainer.vue"; export default { name: "Grid", components: { DragContainer, }, props: { rows: { type: Number, required: true, }, cols: { type: Number, required: true, }, }, methods: { handleDrop(event) { let data = event.dataTransfer.getData("vueDrag/gridItem"); let element = JSON.parse(data); console.log(element); this.items.splice( this.items.findIndex((i) => { return i.key === element.key; }), 1 ); element.x = 1 + Math.trunc(event.layerX / (event.target.offsetWidth / this.cols)); element.y = 1 + Math.trunc(event.layerY / (event.target.offsetHeight / this.rows)); this.items.push(element); }, }, 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; } .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; } </style>