Untitled
unknown
javascript
4 months ago
6.1 kB
1
Indexable
<template> <div class="main-container"> <h3>Панель элементов</h3> <div class="elements-panel"> <div v-for="element in elements" :key="element.id" class="panel-item" :style="{ width: element.width * 50 + 'px' }" draggable="true" @dragstart="onDragStart($event, element.id, true)" @dragend="onDragEnd" > {{ element.id }} </div> </div> <h3>Сетка</h3> <div class="grid-container"> <div v-for="(cell, index) in grid" :key="index" class="grid-cell" @dragover.prevent @drop="onDrop($event, index)" ></div> <div v-for="(cell, index) in grid" :key="'item-' + index" v-if="cell !== null" class="grid-item" :style="{ left: cell.pos * 50 + 'px', width: (cell.width * 50) + 'px' }" draggable="true" @dragstart="onDragStart($event, cell.id, false)" @dragend="onDragEnd" @click="selectElement(cell)" > {{ cell.id }} </div> </div> <div v-if="selectedElement" class="form-container"> <h3>Редактирование: {{ selectedElement.id }}</h3> <label> Ширина (ячейки): <input type="number" v-model.number="newWidth" min="1" max="12" /> </label> <button @click="applyWidthChange">Применить</button> <button @click="removeElement">Удалить</button> </div> </div> </template> <script> export default { data() { return { grid: Array(12).fill(null), elements: [ { id: "a", width: 2 }, { id: "b", width: 1 }, { id: "c", width: 3 }, ], draggedElement: null, draggedFromPanel: false, selectedElement: null, newWidth: null, }; }, methods: { onDragStart(event, id, fromPanel) { if (fromPanel) { this.draggedElement = this.elements.find((el) => el.id === id); this.draggedFromPanel = true; } else { this.draggedElement = this.grid.find((cell) => cell && cell.id === id); this.draggedFromPanel = false; } event.dataTransfer.setData("text/plain", id); event.dataTransfer.effectAllowed = "move"; }, onDragEnd() { this.draggedElement = null; this.draggedFromPanel = false; }, onDrop(event, dropPos) { if (!this.draggedElement) return; const element = this.draggedElement; const { width } = element; if (this.canPlace(dropPos, width, element)) { if (this.draggedFromPanel) { // Убираем элемент из панели this.elements = this.elements.filter((el) => el.id !== element.id); // Создаём новый объект, чтобы реактивно обновить const newElement = { ...element, pos: dropPos }; this.$set(this.grid, dropPos, newElement); } else { // Перемещаем элемент внутри сетки const oldPos = element.pos; this.$set(this.grid, oldPos, null); const updatedElement = { ...element, pos: dropPos }; this.$set(this.grid, dropPos, updatedElement); // Если выбранный элемент был перемещён, обновим ссылку if (this.selectedElement && this.selectedElement.id === element.id) { this.selectedElement = updatedElement; } } this.draggedElement = null; } else { alert("Невозможно разместить элемент здесь!"); } }, canPlace(pos, width, element) { if (pos + width > this.grid.length) return false; for (let i = pos; i < pos + width; i++) { const cellEl = this.grid[i]; if (cellEl !== null && cellEl !== element) { return false; } } return true; }, selectElement(element) { this.selectedElement = element; this.newWidth = element.width; }, applyWidthChange() { if (!this.selectedElement) return; const element = this.selectedElement; const oldWidth = element.width; const oldPos = element.pos; const newW = this.newWidth; // Удаляем с текущей позиции this.$set(this.grid, oldPos, null); const updatedElement = { ...element, width: newW }; if (this.canPlace(oldPos, newW, updatedElement)) { this.$set(this.grid, oldPos, updatedElement); this.selectedElement = updatedElement; // Обновляем ссылку } else { // Откат this.$set(this.grid, oldPos, element); alert("Недостаточно места для новой ширины"); } }, removeElement() { if (!this.selectedElement) return; const element = this.selectedElement; this.$set(this.grid, element.pos, null); this.selectedElement = null; }, }, }; </script> <style scoped> .main-container { font-family: Arial, sans-serif; padding: 20px; } .elements-panel { display: flex; margin-bottom: 20px; } .panel-item { background: #ddd; margin-right: 10px; text-align: center; cursor: grab; height: 50px; line-height: 50px; border: 1px solid #aaa; user-select: none; } .grid-container { position: relative; width: 600px; height: 50px; border: 1px solid #000; box-sizing: border-box; display: flex; flex-wrap: wrap; margin-bottom: 20px; } .grid-cell { width: 50px; height: 50px; border-right: 1px dotted #ccc; box-sizing: border-box; position: relative; } .grid-cell:last-child { border-right: none; } .grid-item { position: absolute; top: 0; height: 50px; background: #8cf; border: 1px solid #44f; display: flex; align-items: center; justify-content: center; cursor: grab; user-select: none; box-sizing: border-box; } .form-container { margin-top: 20px; border: 1px solid #444; padding: 10px; background: #f9f9f9; } </style>
Editor is loading...
Leave a Comment