在此示例中,工作场所由 26 张桌子组成。当员工从顶部框拖出时,我希望他捕捉到红点,并且只能放在红点上。有人可以帮忙吗,谢谢...
const workplace = document.getElementById('workplace');
const employeesContainer = document.getElementById('employees-container');
// Layout based on the provided configuration
const columnWidth = 225;
const rowHeight = 125;
// Greate Office Tables
function createTable(x, y, number) {
const table = document.createElement('div');
table.className = 'table';
table.setAttribute('draggable', false);
table.style.left = `${x}px`;
table.style.top = `${y}px`;
table.textContent = number;
if (number % 2 === 0) {
const dots = ['right'];
dots.forEach((position) => {
const dot = document.createElement('div');
dot.className = 'drop-dot';
dot.dataset.position = position;
table.appendChild(dot);
});
} else {
const dots = ['left'];
dots.forEach((position) => {
const dot = document.createElement('div');
dot.className = 'drop-dot';
dot.dataset.position = position;
table.appendChild(dot);
});
}
workplace.appendChild(table);
}
//Create Employees
function createEmployee(x, y, firstName, lastName, initials) {
const employee = document.createElement('span');
employee.className = 'employee';
employee.style.left = `${x}px`;
employee.style.top = `${y}px`;
employee.textContent = initials;
employee.draggable = true;
// Add drag start event listener
employee.addEventListener('dragstart', (event) => {
event.dataTransfer.setData('text/plain', 'employee'); // Custom data for identification
employee.classList.add('dragging');
});
workplace.appendChild(employee);
}
// Create Employee Avatar
function createEmployeeBox(firstName, lastName) {
const employeeBox = document.createElement('div');
employeeBox.className = 'employee-box';
const initials = `${firstName.charAt(0).toUpperCase()}${lastName.charAt(0).toUpperCase()}`;
employeeBox.textContent = initials;
employeeBox.draggable = true;
employeeBox.dataset.initials = initials; // Add custom data attribute
// Add drag start event listener
employeeBox.addEventListener('dragstart', (event) => {
event.dataTransfer.setData('text/plain', 'employee-box'); // Custom data for identification
employeeBox.classList.add('dragging');
});
employeesContainer.appendChild(employeeBox);
}
// First row
for (let i = 0; i < 10; i += 2) {
createTable(i * (columnWidth / 3), 0, i + 1);
createTable((i + 1) * (columnWidth / 3) - 20, 0, i + 2); // Adjusted spacing
}
// Second row
for (let i = 4; i < 10; i += 2) {
createTable(i * (columnWidth / 3), rowHeight, i + 7);
createTable((i + 1) * (columnWidth / 3) - 20, rowHeight, i + 8); // Adjusted spacing
}
// Third row (same as the first)
for (let i = 0; i < 10; i += 2) {
createTable(i * (columnWidth / 3), 2 * rowHeight, i + 17);
createTable((i + 1) * (columnWidth / 3) - 20, 2 * rowHeight, i + 18); // Adjusted spacing
}
// Add employees
createEmployeeBox('sofia', 'Dhomas');
createEmployeeBox('Cofia', 'Whomas');
createEmployeeBox('Mofia', 'Lhomas');
createEmployeeBox('Cofia', 'Nhomas');
function createEmployee(x, y, firstName, lastName, initials) {
const employee = document.createElement('span');
employee.className = 'employee';
employee.style.left = `${x}px`;
employee.style.top = `${y}px`;
employee.textContent = initials;
employee.draggable = true;
// Add drag start event listener
employee.addEventListener('dragstart', (event) => {
event.dataTransfer.setData('text/plain', 'employee'); // Custom data for identification
employee.classList.add('dragging');
});
workplace.appendChild(employee);
}
// Event listeners for drag-and-drop
workplace.addEventListener('dragover', (event) => {
event.preventDefault();
});
workplace.addEventListener('drop', (event) => {
event.preventDefault();
const dataType = event.dataTransfer.getData('text/plain');
const offsetX = event.clientX - workplace.getBoundingClientRect().left;
const offsetY = event.clientY - workplace.getBoundingClientRect().top;
if (dataType === 'employee') {
const employee = document.querySelector('.employee.dragging');
if (employee) {
console.log('employee')
const nearestTable = findNearestTable(offsetX, offsetY);
if (nearestTable) {
console.log('nearestTable')
const tableRect = nearestTable.getBoundingClientRect();
const snappedX = tableRect.left + tableRect.width / 2 - employee.clientWidth / 2;
const snappedY = tableRect.top + tableRect.height / 2 - employee.clientHeight / 2;
// Remove the corresponding employee box
const initials = employee.textContent;
const employeeBox = document.querySelector(`.employee-box[data-initials='${initials}']`);
if (employeeBox) {
employeesContainer.removeChild(employeeBox);
}
employee.style.left = `${snappedX}px`;
employee.style.top = `${snappedY}px`;
employee.classList.remove('dragging');
}
// Move employee to new position
//employee.style.left = `${offsetX - 12.5}px`; // Adjust for centering
//employee.style.top = `${offsetY - 12.5}px`; // Adjust for centering
}
} else if (dataType === 'employee-box') {
console.log('employee-box')
// Remove the dragged employee box
const nearestTable = findNearestTable(offsetX, offsetY);
if (nearestTable) {
console.log('nearestTable');
}
const employeeBox = document.querySelector('.employee-box.dragging');
if (employeeBox) {
employeesContainer.removeChild(employeeBox);
}
// Create new employee at the dropped position
const initials = employeeBox.textContent;
createEmployee(offsetX - 12.5, offsetY - 12.5, 'New', 'Employee', initials);
}
}); // Orginal
// Double-click to return employee to the employee box
workplace.addEventListener('dblclick', (event) => {
if (event.target.classList.contains('employee')) {
const employee = event.target;
const initials = employee.textContent;
// Remove the employee from the workplace
workplace.removeChild(employee);
// Create a new employee box with the correct initials
createEmployeeBox(initials.charAt(0), initials.charAt(1));
}
});
// FN
// Function to find the nearest table
function findNearestTable(x, y) {
const tables = document.querySelectorAll('.table');
let nearestTable = null;
let minDistance = Infinity;
tables.forEach((table) => {
const tableRect = table.getBoundingClientRect();
console.log(tableRect)
const distance = Math.sqrt((x - tableRect.left - tableRect.width / 2) ** 2 +
(y - tableRect.top - tableRect.height / 2) ** 2);
if (distance < minDistance) {
console.log('tableRect')
minDistance = distance;
nearestTable = table;
}
});
return nearestTable;
}
body {
font-family: "Public Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
font-size: 0.9375rem;
font-wiight: 400;
line-height: 1.47;
display: flex;
flex-direction: column;
align-items: center;
}
.workplace {
position: relative;
width: 740px;
height: 375px;
border: 2px solid #cfd3ec;
margin: 20px;
background-color: #434968;
border-radius: 0.5rem;
}
.table {
position: absolute;
width: 40px;
height: 80px;
background-color: #424659;
border: 2px solid #cfd3ec;
border-radius: 0.2rem;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
margin: 20px;
color: #cfd3ec;
}
.table.highlighted-table {
border: 2px solid yellow;
/* Change the color as needed */
}
.employee {
position: absolute;
width: 25px;
height: 25px;
border: 1px solid black;
border-radius: 50%;
background-color: white;
display: flex;
align-items: center;
justify-content: center;
font-weight: 500;
cursor: move;
user-select: none;
}
.employees-container {
display: flex;
width: 740px;
height: 100px;
background-color: #434968;
border: 2px solid #cfd3ec;
border-radius: 0.3rem;
box-sizing: border-box;
align-items: center;
margin-top: 20px;
flex-wrap: wrap;
}
.employee-box {
width: 25px;
height: 25px;
border: 1px solid #cfd3ec;
border-radius: 50%;
background-color: white;
display: flex;
align-items: center;
justify-content: center;
font-weight: 500;
cursor: move;
user-select: none;
margin: .5rem;
}
.drop-dot {
position: absolute;
width: 10px;
height: 10px;
background-color: red;
border-radius: 50%;
cursor: pointer;
}
.drop-dot[data-position="left"] {
top: 50%;
left: -5px;
transform: translateY(-50%);
}
.drop-dot[data-position="right"] {
top: 50%;
right: -5px;
transform: translateY(-50%);
}
<div class="employees-container" id="employees-container"></div>
<div class="workplace" id="workplace"></div>
在拖拽开始时,您需要有关被拖拽的员工的信息。在拖动时,您可以通过设置类名来更改“放置区域”的样式。在放置事件中,拖动的元素必须移动/附加到新的放置区域。然后必须对拖动的元素进行样式设置,使其就位。
already
对象用于测试员工是否已经在餐桌上。
const workplace = document.getElementById('workplace');
const employeesContainer = document.getElementById('employees-container');
employeesContainer.addEventListener('dragstart', e => {
e.dataTransfer.setData('text/plain', e.target.dataset.initials);
});
workplace.addEventListener('dragstart', e => {
e.dataTransfer.setData('text/plain', e.target.dataset.initials);
});
workplace.addEventListener('dragover', e => {
e.preventDefault();
workplace.querySelectorAll('.drop-dot').forEach(dot => dot.classList.remove('over'));
let table = e.target.closest('.table');
if (table) {
let already = table.querySelector('.employee-box');
let dot = table.querySelector('.drop-dot');
if (dot && !already) {
dot.classList.add('over');
}
}
});
workplace.addEventListener('drop', e => {
e.preventDefault();
let table = e.target.closest('.table');
if (table) {
let already = table.querySelector('.employee-box');
if (!already) {
let dot = table.querySelector('.drop-dot');
let initials = e.dataTransfer.getData('text/plain');
let employee = document.querySelector(`div[data-initials="${initials}"]`);
employee.classList.add(dot.dataset.position);
table.appendChild(employee);
}
}
workplace.querySelectorAll('.drop-dot').forEach(dot => dot.classList.remove('over'));
});
body {
font-family: "Public Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;
font-size: 0.9375rem;
font-wiight: 400;
line-height: 1.47;
display: flex;
flex-direction: column;
align-items: center;
}
.workplace {
position: relative;
width: 740px;
height: 375px;
border: 2px solid #cfd3ec;
margin: 20px;
background-color: #434968;
border-radius: 0.5rem;
}
.table {
position: absolute;
width: 40px;
height: 80px;
background-color: #424659;
border: 2px solid #cfd3ec;
border-radius: 0.2rem;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
margin: 20px;
color: #cfd3ec;
}
.table.highlighted-table {
border: 2px solid yellow;
/* Change the color as needed */
}
.employee {
position: absolute;
width: 25px;
height: 25px;
border: 1px solid black;
border-radius: 50%;
background-color: white;
display: flex;
align-items: center;
justify-content: center;
font-weight: 500;
cursor: move;
user-select: none;
}
.employees-container {
display: flex;
width: 740px;
height: 100px;
background-color: #434968;
border: 2px solid #cfd3ec;
border-radius: 0.3rem;
box-sizing: border-box;
align-items: center;
margin-top: 20px;
flex-wrap: wrap;
}
.employee-box {
width: 25px;
height: 25px;
border: 1px solid #cfd3ec;
border-radius: 50%;
background-color: white;
display: flex;
align-items: center;
justify-content: center;
font-weight: 500;
cursor: move;
user-select: none;
margin: .5rem;
}
.drop-dot {
position: absolute;
width: 10px;
height: 10px;
background-color: red;
border-radius: 50%;
cursor: pointer;
}
.drop-dot.over {
width: 30px;
height: 30px;
}
.drop-dot[data-position="left"] {
top: 50%;
left: -5px;
transform: translateY(-50%);
}
.drop-dot[data-position="right"] {
top: 50%;
right: -5px;
transform: translateY(-50%);
}
.table .employee-box.right {
position: absolute;
right: -25px;
}
.table .employee-box.left {
position: absolute;
left: -25px;
}
<div class="employees-container" id="employees-container">
<div class="employee-box" draggable="true" data-initials="SD">SD</div>
<div class="employee-box" draggable="true" data-initials="CW">CW</div>
<div class="employee-box" draggable="true" data-initials="ML">ML</div>
<div class="employee-box" draggable="true" data-initials="CN">CN</div>
</div>
<div class="workplace" id="workplace">
<div class="table" style="left: 0px; top: 0px;">1
<div class="drop-dot" data-position="left"></div>
</div>
<div class="table" style="left: 55px; top: 0px;">2
<div class="drop-dot" data-position="right"></div>
</div>
<div class="table" style="left: 150px; top: 0px;">3
<div class="drop-dot" data-position="left"></div>
</div>
<div class="table" style="left: 205px; top: 0px;">4
<div class="drop-dot" data-position="right"></div>
</div>
<div class="table" style="left: 300px; top: 0px;">5
<div class="drop-dot" data-position="left"></div>
</div>
<div class="table" style="left: 355px; top: 0px;">6
<div class="drop-dot" data-position="right"></div>
</div>
</div>