mirror of
https://gitlab.com/skysthelimit.dev/selenite.git
synced 2025-06-16 02:22:07 -05:00
152 lines
5.7 KiB
JavaScript
152 lines
5.7 KiB
JavaScript
// Add event listener to the canvas to detect element drops
|
|
canvas.addEventListener("mouseup", function (event) {
|
|
const droppedElement = event.target;
|
|
const canvasRect = canvas.getBoundingClientRect();
|
|
const x = event.clientX - canvasRect.left;
|
|
const y = event.clientY - canvasRect.top;
|
|
|
|
// Check if the dropped element is an element on the canvas
|
|
if (droppedElement.classList.contains("element")) {
|
|
// Check if the dropped element overlaps with any other element
|
|
const elements = canvas.querySelectorAll(".element");
|
|
elements.forEach((element) => {
|
|
if (
|
|
element !== droppedElement &&
|
|
isOverlapping(droppedElement, element)
|
|
) {
|
|
// Merge the elements if they can be merged
|
|
const mergedElement = mergeElements(droppedElement, element);
|
|
if (mergedElement) {
|
|
// Remove the original elements
|
|
droppedElement.remove();
|
|
element.remove();
|
|
// Place the merged element at the drop location without snapping
|
|
const mergedElementRect = mergedElement.getBoundingClientRect();
|
|
const offsetX = mergedElementRect.width / 2;
|
|
const offsetY = mergedElementRect.height / 2;
|
|
mergedElement.style.position = "absolute";
|
|
mergedElement.style.left = `${x - offsetX}px`;
|
|
mergedElement.style.top = `${y - offsetY}px`;
|
|
// Add animation
|
|
requestAnimationFrame(() => {
|
|
mergedElement.style.transform = "scale(1.5)";
|
|
mergedElement.style.transition = "transform 0.5s ease";
|
|
});
|
|
// Listen for transition end event
|
|
mergedElement.addEventListener(
|
|
"transitionend",
|
|
function transitionEndHandler() {
|
|
// Remove animation properties after animation is complete
|
|
mergedElement.style.transition = "none";
|
|
mergedElement.style.transform = "scale(1)";
|
|
// Remove event listener
|
|
mergedElement.removeEventListener(
|
|
"transitionend",
|
|
transitionEndHandler
|
|
);
|
|
}
|
|
);
|
|
canvas.appendChild(mergedElement);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
});
|
|
|
|
// Function to check if two elements overlap
|
|
function isOverlapping(element1, element2) {
|
|
const rect1 = element1.getBoundingClientRect();
|
|
const rect2 = element2.getBoundingClientRect();
|
|
return !(
|
|
rect1.right < rect2.left ||
|
|
rect1.left > rect2.right ||
|
|
rect1.bottom < rect2.top ||
|
|
rect1.top > rect2.bottom
|
|
);
|
|
}
|
|
|
|
// Function to merge two elements
|
|
function mergeElements(element1, element2) {
|
|
const element1Type = element1.id;
|
|
const element2Type = element2.id;
|
|
|
|
// Check if merge rule exists for the combination of the two elements
|
|
if (mergeRules[element1Type] && mergeRules[element1Type][element2Type]) {
|
|
const newElementType = mergeRules[element1Type][element2Type];
|
|
// Remove emoji from the merged element type
|
|
const newElementTypeWithoutEmoji = newElementType
|
|
.replace(/[^\x00-\x7F]/g, "")
|
|
.replace(" ", "")
|
|
.toLowerCase(); // Remove non-ASCII characters (emojis)
|
|
// Create a new element representing the merged result
|
|
const mergedElement = document.createElement("div");
|
|
mergedElement.classList.add("element");
|
|
mergedElement.id = newElementTypeWithoutEmoji
|
|
.replace(" ", "")
|
|
.toLowerCase(); // Assign the ID without emoji
|
|
mergedElement.textContent = newElementType;
|
|
|
|
// Add the merged element to the sidebar if it doesn't already exist
|
|
const sidebar = document.getElementById("sidebar");
|
|
const elemId = `#${newElementTypeWithoutEmoji
|
|
.replace(" ", "")
|
|
.toLowerCase()}`;
|
|
if (!sidebar.querySelector(elemId)) {
|
|
const newElementDiv = document.createElement("div");
|
|
newElementDiv.classList.add("element");
|
|
newElementDiv.id = newElementTypeWithoutEmoji
|
|
.replace(" ", "")
|
|
.toLowerCase();
|
|
newElementDiv.textContent = newElementType;
|
|
sidebar.appendChild(newElementDiv);
|
|
|
|
newElementDiv.addEventListener("mousedown", function (event) {
|
|
createDraggableClone(newElementDiv, event);
|
|
});
|
|
}
|
|
|
|
// Return the merged element
|
|
return mergedElement;
|
|
} else if (
|
|
mergeRules[element2Type] &&
|
|
mergeRules[element2Type][element1Type]
|
|
) {
|
|
const newElementType = mergeRules[element2Type][element1Type];
|
|
// Remove emoji from the merged element type
|
|
const newElementTypeWithoutEmoji = newElementType
|
|
.replace(/[^\x00-\x7F]/g, "")
|
|
.replace(" ", "")
|
|
.toLowerCase(); // Remove non-ASCII characters (emojis)
|
|
// Create a new element representing the merged result
|
|
const mergedElement = document.createElement("div");
|
|
mergedElement.classList.add("element");
|
|
mergedElement.id = newElementTypeWithoutEmoji
|
|
.replace(" ", "")
|
|
.toLowerCase(); // Assign the ID without emoji
|
|
mergedElement.textContent = newElementType;
|
|
|
|
// Add the merged element to the sidebar if it doesn't already exist
|
|
const sidebar = document.getElementById("sidebar");
|
|
const elemId = `#${newElementTypeWithoutEmoji
|
|
.replace(" ", "")
|
|
.toLowerCase()}`;
|
|
if (!sidebar.querySelector(elemId)) {
|
|
const newElementDiv = document.createElement("div");
|
|
newElementDiv.classList.add("element");
|
|
newElementDiv.id = newElementTypeWithoutEmoji
|
|
.replace(" ", "")
|
|
.toLowerCase();
|
|
newElementDiv.textContent = newElementType;
|
|
sidebar.appendChild(newElementDiv);
|
|
|
|
newElementDiv.addEventListener("mousedown", function (event) {
|
|
createDraggableClone(newElementDiv, event);
|
|
});
|
|
}
|
|
|
|
return mergedElement;
|
|
} else {
|
|
// No merge rule exists for the combination of the two elements
|
|
return null;
|
|
}
|
|
} |