1036 lines
38 KiB
JavaScript
1036 lines
38 KiB
JavaScript
document.addEventListener("DOMContentLoaded", function () {
|
|
// Funzione per caricare il contenuto del popup
|
|
async function loadPopupContent(iddatadb, idquotations) {
|
|
const popupContent = document.getElementById("popupContent");
|
|
if (!popupContent) {
|
|
console.error("Elemento popupContent non trovato");
|
|
return;
|
|
}
|
|
try {
|
|
const endpoint = idquotations
|
|
? `photos_popup.php?idquotations=${idquotations}`
|
|
: `photos_popup.php?iddatadb=${iddatadb}`;
|
|
console.log("Caricamento popup da:", endpoint);
|
|
const response = await fetch(endpoint);
|
|
if (!response.ok)
|
|
throw new Error("Errore nella risposta del server");
|
|
popupContent.innerHTML = await response.text();
|
|
attachPhotoEventListeners(iddatadb, idquotations);
|
|
} catch (error) {
|
|
popupContent.innerHTML = `<p>Errore durante il caricamento: ${error.message}</p>`;
|
|
console.error("Errore in loadPopupContent:", error);
|
|
}
|
|
}
|
|
|
|
// Funzione per gestire la webcam
|
|
function setupWebcam(iddatadb, idquotations) {
|
|
const openWebcamBtn = document.getElementById("openWebcamBtn");
|
|
const webcamArea = document.getElementById("webcamArea");
|
|
const webcamVideo = document.getElementById("webcamVideo");
|
|
const captureBtn = document.getElementById("captureBtn");
|
|
const closeWebcamBtn = document.getElementById("closeWebcamBtn");
|
|
const webcamSelect = document.getElementById("webcamSelect");
|
|
let stream = null;
|
|
|
|
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
|
|
console.warn("La webcam non è supportata dal browser.");
|
|
if (openWebcamBtn) openWebcamBtn.style.display = "none";
|
|
return;
|
|
}
|
|
|
|
if (
|
|
!openWebcamBtn ||
|
|
!webcamArea ||
|
|
!webcamVideo ||
|
|
!captureBtn ||
|
|
!closeWebcamBtn ||
|
|
!webcamSelect
|
|
) {
|
|
console.error("Elementi webcam mancanti", {
|
|
openWebcamBtn,
|
|
webcamArea,
|
|
webcamVideo,
|
|
captureBtn,
|
|
closeWebcamBtn,
|
|
webcamSelect,
|
|
});
|
|
return;
|
|
}
|
|
|
|
async function startWebcam(deviceId = null) {
|
|
try {
|
|
if (stream) {
|
|
stream.getTracks().forEach((track) => track.stop());
|
|
stream = null;
|
|
webcamVideo.srcObject = null;
|
|
}
|
|
|
|
const constraints = {
|
|
video: deviceId ? { deviceId: { exact: deviceId } } : true,
|
|
};
|
|
|
|
stream = await navigator.mediaDevices.getUserMedia(constraints);
|
|
webcamVideo.srcObject = stream;
|
|
webcamArea.style.display = "block";
|
|
openWebcamBtn.style.display = "none";
|
|
dropArea.style.display = "none";
|
|
} catch (error) {
|
|
console.error("Errore nell'accesso alla webcam:", error);
|
|
alert("Errore nell'accesso alla webcam: " + error.message);
|
|
webcamArea.style.display = "none";
|
|
openWebcamBtn.style.display = "block";
|
|
dropArea.style.display = "block";
|
|
}
|
|
}
|
|
|
|
async function populateWebcamSelect() {
|
|
try {
|
|
await navigator.mediaDevices.getUserMedia({ video: true });
|
|
const devices = await navigator.mediaDevices.enumerateDevices();
|
|
const videoDevices = devices.filter(
|
|
(device) => device.kind === "videoinput",
|
|
);
|
|
|
|
webcamSelect.innerHTML =
|
|
'<option value="">Select a webcam</option>';
|
|
|
|
videoDevices.forEach((device) => {
|
|
const option = document.createElement("option");
|
|
option.value = device.deviceId;
|
|
option.text =
|
|
device.label || `Webcam ${webcamSelect.options.length}`;
|
|
webcamSelect.appendChild(option);
|
|
});
|
|
|
|
webcamSelect.style.display =
|
|
videoDevices.length > 1 ? "block" : "none";
|
|
|
|
if (videoDevices.length > 0) {
|
|
await startWebcam(videoDevices[0].deviceId);
|
|
} else {
|
|
alert("Nessuna webcam rilevata.");
|
|
webcamArea.style.display = "none";
|
|
openWebcamBtn.style.display = "block";
|
|
dropArea.style.display = "block";
|
|
}
|
|
} catch (error) {
|
|
console.error("Errore nel recupero dei dispositivi:", error);
|
|
alert("Errore nel recupero dei dispositivi: " + error.message);
|
|
webcamSelect.style.display = "none";
|
|
}
|
|
}
|
|
|
|
openWebcamBtn.addEventListener("click", async () => {
|
|
await populateWebcamSelect();
|
|
});
|
|
|
|
webcamSelect.addEventListener("change", async (e) => {
|
|
const deviceId = e.target.value;
|
|
if (deviceId) {
|
|
await startWebcam(deviceId);
|
|
}
|
|
});
|
|
|
|
closeWebcamBtn.addEventListener("click", () => {
|
|
if (stream) {
|
|
stream.getTracks().forEach((track) => track.stop());
|
|
stream = null;
|
|
webcamVideo.srcObject = null;
|
|
}
|
|
webcamArea.style.display = "none";
|
|
openWebcamBtn.style.display = "block";
|
|
dropArea.style.display = "block";
|
|
});
|
|
|
|
captureBtn.addEventListener("click", () => {
|
|
const canvas = document.createElement("canvas");
|
|
canvas.width = webcamVideo.videoWidth;
|
|
canvas.height = webcamVideo.videoHeight;
|
|
canvas
|
|
.getContext("2d")
|
|
.drawImage(webcamVideo, 0, 0, canvas.width, canvas.height);
|
|
|
|
canvas.toBlob(async (blob) => {
|
|
const file = new File(
|
|
[blob],
|
|
`webcam_photo_${Date.now()}.jpg`,
|
|
{ type: "image/jpeg" },
|
|
);
|
|
const loader = document.getElementById("loader");
|
|
if (loader) {
|
|
loader.style.display = "flex";
|
|
}
|
|
await handleFiles([file], iddatadb, idquotations);
|
|
if (stream) {
|
|
stream.getTracks().forEach((track) => track.stop());
|
|
stream = null;
|
|
webcamVideo.srcObject = null;
|
|
}
|
|
webcamArea.style.display = "none";
|
|
openWebcamBtn.style.display = "block";
|
|
dropArea.style.display = "block";
|
|
}, "image/jpeg");
|
|
});
|
|
}
|
|
|
|
async function handleFiles(files, iddatadb, idquotations) {
|
|
const loader = document.getElementById("loader");
|
|
if (!loader) {
|
|
console.error("Elemento loader non trovato");
|
|
return;
|
|
}
|
|
|
|
if (!files || files.length === 0) {
|
|
console.warn("Nessun file da caricare");
|
|
return;
|
|
}
|
|
|
|
for (const file of files) {
|
|
if (!file.type.startsWith("image/")) {
|
|
alert("Per favore, carica solo immagini!");
|
|
continue;
|
|
}
|
|
|
|
loader.style.display = "flex";
|
|
|
|
const formData = new FormData();
|
|
formData.append("photo", file);
|
|
if (idquotations) {
|
|
formData.append("idquotations", idquotations);
|
|
} else {
|
|
formData.append("iddatadb", iddatadb);
|
|
}
|
|
|
|
try {
|
|
const response = await fetch("upload_photo.php", {
|
|
method: "POST",
|
|
body: formData,
|
|
});
|
|
const result = await response.json();
|
|
if (result.success) {
|
|
loadPopupContent(iddatadb, idquotations);
|
|
} else {
|
|
alert("Errore durante il caricamento: " + result.message);
|
|
}
|
|
} catch (error) {
|
|
alert("Errore durante il caricamento: " + error.message);
|
|
} finally {
|
|
loader.style.display = "none";
|
|
}
|
|
}
|
|
}
|
|
|
|
function attachPhotoEventListeners(iddatadb, idquotations) {
|
|
const dropArea = document.getElementById("dropArea");
|
|
const photoInput = document.getElementById("photoInput");
|
|
const photosModal = document.getElementById("photosModal");
|
|
|
|
if (!dropArea || !photoInput || !photosModal) {
|
|
console.error("Elementi mancanti:", {
|
|
dropArea,
|
|
photoInput,
|
|
photosModal,
|
|
});
|
|
return;
|
|
}
|
|
|
|
const preventDefaults = (e) => {
|
|
e.preventDefault();
|
|
e.stopPropagation();
|
|
};
|
|
|
|
["dragenter", "dragover", "dragleave", "drop"].forEach((eventName) => {
|
|
dropArea.addEventListener(eventName, preventDefaults, false);
|
|
});
|
|
|
|
["dragenter", "dragover"].forEach((eventName) => {
|
|
dropArea.addEventListener(
|
|
eventName,
|
|
() => dropArea.classList.add("highlight"),
|
|
false,
|
|
);
|
|
});
|
|
|
|
["dragleave", "drop"].forEach((eventName) => {
|
|
dropArea.addEventListener(
|
|
eventName,
|
|
() => dropArea.classList.remove("highlight"),
|
|
false,
|
|
);
|
|
});
|
|
|
|
dropArea.addEventListener(
|
|
"drop",
|
|
(e) => {
|
|
const files = e.dataTransfer.files;
|
|
if (files.length > 0) {
|
|
handleFiles(files, iddatadb, idquotations);
|
|
}
|
|
},
|
|
false,
|
|
);
|
|
|
|
dropArea.addEventListener(
|
|
"click",
|
|
() => {
|
|
photoInput.click();
|
|
},
|
|
false,
|
|
);
|
|
|
|
photoInput.addEventListener(
|
|
"change",
|
|
(e) => {
|
|
const files = e.target.files;
|
|
if (files.length > 0) {
|
|
handleFiles(files, iddatadb, idquotations);
|
|
}
|
|
e.target.value = "";
|
|
},
|
|
false,
|
|
);
|
|
|
|
document.querySelectorAll(".delete-photo-btn").forEach((button) => {
|
|
button.addEventListener("click", async function () {
|
|
const photoId = this.getAttribute("data-photo-id");
|
|
if (confirm("Sei sicuro di voler eliminare questa foto?")) {
|
|
try {
|
|
const response = await fetch("delete_photo.php", {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type":
|
|
"application/x-www-form-urlencoded",
|
|
},
|
|
body: `photo_id=${photoId}`,
|
|
});
|
|
const result = await response.json();
|
|
if (result.success) {
|
|
loadPopupContent(iddatadb, idquotations);
|
|
} else {
|
|
alert(
|
|
"Errore durante l'eliminazione: " +
|
|
result.message,
|
|
);
|
|
}
|
|
} catch (error) {
|
|
alert(
|
|
"Errore durante l'eliminazione: " + error.message,
|
|
);
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
document.querySelectorAll(".thumbnail").forEach((img) => {
|
|
img.addEventListener("click", function () {
|
|
const enlargedImage = document.getElementById("enlargedImage");
|
|
enlargedImage.src = this.src;
|
|
document.getElementById("imageModal").style.display = "block";
|
|
});
|
|
});
|
|
|
|
const imageCloseBtn = document.querySelector(".image-modal-close");
|
|
if (imageCloseBtn) {
|
|
imageCloseBtn.addEventListener("click", () => {
|
|
document.getElementById("imageModal").style.display = "none";
|
|
});
|
|
}
|
|
document
|
|
.getElementById("imageModal")
|
|
.addEventListener("click", function (event) {
|
|
if (event.target === this) {
|
|
this.style.display = "none";
|
|
}
|
|
});
|
|
|
|
setupWebcam(iddatadb, idquotations);
|
|
|
|
const createCollageBtn = document.getElementById("createCollageBtn");
|
|
if (createCollageBtn) {
|
|
createCollageBtn.addEventListener("click", () => {
|
|
document.getElementById("collageModal").style.display = "block";
|
|
initCollageCanvas();
|
|
});
|
|
}
|
|
|
|
const closeCollageBtn = document.querySelector(".close-collage");
|
|
if (closeCollageBtn) {
|
|
closeCollageBtn.addEventListener("click", () => {
|
|
document.getElementById("collageModal").style.display = "none";
|
|
if (isCropping) {
|
|
exitCropMode();
|
|
}
|
|
if (isRemovingBackground) {
|
|
exitBackgroundRemovalMode();
|
|
}
|
|
});
|
|
}
|
|
|
|
let canvas;
|
|
let cropRect = null;
|
|
let isCropping = false;
|
|
let croppedImage = null;
|
|
let isApplyingCrop = false;
|
|
let isRemovingBackground = false;
|
|
let backgroundRemovalImage = null;
|
|
let history = [];
|
|
const maxHistory = 20;
|
|
|
|
function initCollageCanvas() {
|
|
if (typeof fabric === "undefined") {
|
|
console.error("Fabric.js non è caricato!");
|
|
alert(
|
|
"Errore: Fabric.js non è disponibile. Controlla la connessione al CDN.",
|
|
);
|
|
return;
|
|
}
|
|
canvas = new fabric.Canvas("collageCanvas", {
|
|
backgroundColor: "#fff",
|
|
selection: true,
|
|
});
|
|
fabric.Object.prototype.set({
|
|
cornerColor: "black",
|
|
cornerStrokeColor: "black",
|
|
cornerSize: 12,
|
|
borderColor: "black",
|
|
transparentCorners: false,
|
|
});
|
|
canvas.on("object:modified", () => {
|
|
saveCanvasState();
|
|
updateLayersPanel();
|
|
canvas.renderAll();
|
|
});
|
|
canvas.on("object:added", () => {
|
|
updateLayersPanel();
|
|
});
|
|
canvas.on("object:removed", () => {
|
|
updateLayersPanel();
|
|
});
|
|
canvas.on("selection:created", () => {
|
|
updateButtons();
|
|
});
|
|
canvas.on("selection:updated", () => {
|
|
updateButtons();
|
|
});
|
|
canvas.on("selection:cleared", () => {
|
|
if (!isCropping && !isRemovingBackground) {
|
|
updateButtons();
|
|
} else if (isCropping && cropRect) {
|
|
canvas.setActiveObject(cropRect);
|
|
canvas.renderAll();
|
|
} else if (isRemovingBackground) {
|
|
canvas.setActiveObject(backgroundRemovalImage);
|
|
canvas.renderAll();
|
|
}
|
|
});
|
|
canvas.on("mouse:down", (event) => {
|
|
if (isRemovingBackground && backgroundRemovalImage) {
|
|
handleBackgroundColorSelection(event);
|
|
}
|
|
});
|
|
saveCanvasState();
|
|
updateLayersPanel();
|
|
updateButtons();
|
|
}
|
|
|
|
function updateLayersPanel() {
|
|
const layersList = document.getElementById("layersList");
|
|
if (!layersList) {
|
|
console.error("Elemento layersList non trovato");
|
|
return;
|
|
}
|
|
layersList.innerHTML = "";
|
|
|
|
const images = canvas.getObjects("image");
|
|
images.forEach((img, index) => {
|
|
let thumbSrc;
|
|
try {
|
|
const thumbCanvas = document.createElement("canvas");
|
|
thumbCanvas.width = 50;
|
|
thumbCanvas.height = 50;
|
|
const thumbFabric = new fabric.Canvas(thumbCanvas);
|
|
|
|
const clonedImg = fabric.util.object.clone(img);
|
|
const scaleFactor = Math.min(
|
|
50 / img.width,
|
|
50 / img.height,
|
|
);
|
|
clonedImg.scaleX = scaleFactor;
|
|
clonedImg.scaleY = scaleFactor;
|
|
clonedImg.left = (50 - img.width * scaleFactor) / 2;
|
|
clonedImg.top = (50 - img.height * scaleFactor) / 2;
|
|
clonedImg.setCoords();
|
|
thumbFabric.add(clonedImg);
|
|
thumbFabric.renderAll();
|
|
|
|
thumbSrc = thumbCanvas.toDataURL("image/png");
|
|
thumbFabric.dispose();
|
|
} catch (error) {
|
|
console.warn(
|
|
"Errore nella generazione della thumbnail per immagine",
|
|
index + 1,
|
|
error,
|
|
);
|
|
thumbSrc = img.getSrc(); // Fallback all'URL originale
|
|
}
|
|
|
|
const layerItem = document.createElement("li");
|
|
const thumbImg = document.createElement("img");
|
|
thumbImg.src = thumbSrc;
|
|
thumbImg.title = `Layer ${index + 1}`;
|
|
thumbImg.addEventListener("click", () => {
|
|
canvas.setActiveObject(img);
|
|
canvas.renderAll();
|
|
});
|
|
|
|
layerItem.appendChild(thumbImg);
|
|
layersList.appendChild(layerItem);
|
|
});
|
|
}
|
|
|
|
function saveCanvasState() {
|
|
if (isCropping || isRemovingBackground) {
|
|
return;
|
|
}
|
|
const state = JSON.stringify(
|
|
canvas.toJSON([
|
|
"cornerColor",
|
|
"cornerStrokeColor",
|
|
"cornerSize",
|
|
"borderColor",
|
|
"transparentCorners",
|
|
]),
|
|
);
|
|
history.push(state);
|
|
if (history.length > maxHistory) {
|
|
history.shift();
|
|
}
|
|
updateButtons();
|
|
}
|
|
|
|
function undo() {
|
|
if (history.length <= 1) {
|
|
return;
|
|
}
|
|
history.pop();
|
|
const previousState = history[history.length - 1];
|
|
if (previousState) {
|
|
canvas.clear();
|
|
canvas.loadFromJSON(previousState, () => {
|
|
canvas.renderAll();
|
|
updateLayersPanel();
|
|
updateButtons();
|
|
});
|
|
} else {
|
|
console.warn("Nessuno stato precedente disponibile");
|
|
canvas.clear();
|
|
canvas.setBackgroundColor("#fff");
|
|
canvas.renderAll();
|
|
updateLayersPanel();
|
|
updateButtons();
|
|
}
|
|
}
|
|
|
|
function updateButtons() {
|
|
const cropBtn = document.getElementById("cropImageBtn");
|
|
const applyCropBtn = document.getElementById("applyCropBtn");
|
|
const cancelCropBtn = document.getElementById("cancelCropBtn");
|
|
const removeBackgroundBtn = document.getElementById(
|
|
"removeBackgroundBtn",
|
|
);
|
|
const removeImageBtn = document.getElementById("removeImageBtn");
|
|
const undoBtn = document.getElementById("undoBtn");
|
|
const instruction = document.getElementById(
|
|
"backgroundRemovalInstruction",
|
|
);
|
|
const activeObject = canvas.getActiveObject();
|
|
if (isCropping && cropRect) {
|
|
cropBtn.disabled = true;
|
|
applyCropBtn.disabled = false;
|
|
cancelCropBtn.disabled = false;
|
|
removeBackgroundBtn.disabled = true;
|
|
removeImageBtn.disabled = true;
|
|
undoBtn.disabled = true;
|
|
instruction.style.display = "none";
|
|
} else if (isRemovingBackground && backgroundRemovalImage) {
|
|
cropBtn.disabled = true;
|
|
applyCropBtn.disabled = true;
|
|
cancelCropBtn.disabled = true;
|
|
removeBackgroundBtn.disabled = true;
|
|
removeImageBtn.disabled = true;
|
|
undoBtn.disabled = true;
|
|
instruction.style.display = "block";
|
|
} else if (
|
|
activeObject &&
|
|
activeObject.type === "image" &&
|
|
!isCropping &&
|
|
!isRemovingBackground
|
|
) {
|
|
cropBtn.disabled = false;
|
|
applyCropBtn.disabled = true;
|
|
cancelCropBtn.disabled = true;
|
|
removeBackgroundBtn.disabled = false;
|
|
removeImageBtn.disabled = false;
|
|
undoBtn.disabled = history.length <= 1;
|
|
instruction.style.display = "none";
|
|
} else {
|
|
cropBtn.disabled = true;
|
|
applyCropBtn.disabled = true;
|
|
cancelCropBtn.disabled = true;
|
|
removeBackgroundBtn.disabled = true;
|
|
removeImageBtn.disabled = true;
|
|
undoBtn.disabled = history.length <= 1;
|
|
instruction.style.display = "none";
|
|
}
|
|
}
|
|
|
|
function enterCropMode() {
|
|
const activeObject = canvas.getActiveObject();
|
|
if (!activeObject || activeObject.type !== "image") {
|
|
console.warn("Nessuna immagine selezionata per il ritaglio");
|
|
alert("Seleziona un'immagine prima di attivare il ritaglio!");
|
|
return;
|
|
}
|
|
isCropping = true;
|
|
croppedImage = activeObject;
|
|
canvas.discardActiveObject();
|
|
cropRect = new fabric.Rect({
|
|
left: activeObject.left,
|
|
top: activeObject.top,
|
|
width: activeObject.width * activeObject.scaleX * 0.5,
|
|
height: activeObject.height * activeObject.scaleY * 0.5,
|
|
fill: "rgba(0, 0, 0, 0.3)",
|
|
stroke: "red",
|
|
strokeWidth: 2,
|
|
hasBorders: true,
|
|
hasControls: true,
|
|
lockRotation: true,
|
|
selectable: true,
|
|
cornerColor: "black",
|
|
cornerStrokeColor: "black",
|
|
cornerSize: 12,
|
|
borderColor: "black",
|
|
transparentCorners: false,
|
|
});
|
|
canvas.add(cropRect);
|
|
canvas.setActiveObject(cropRect);
|
|
canvas.renderAll();
|
|
updateButtons();
|
|
}
|
|
|
|
function exitCropMode() {
|
|
if (cropRect) {
|
|
canvas.remove(cropRect);
|
|
cropRect = null;
|
|
}
|
|
isCropping = false;
|
|
croppedImage = null;
|
|
isApplyingCrop = false;
|
|
canvas.discardActiveObject();
|
|
canvas.renderAll();
|
|
updateButtons();
|
|
}
|
|
|
|
function applyCrop() {
|
|
if (isApplyingCrop) {
|
|
return;
|
|
}
|
|
if (!isCropping || !cropRect || !croppedImage) {
|
|
console.warn("Condizioni per il ritaglio non soddisfatte", {
|
|
isCropping,
|
|
cropRect: !!cropRect,
|
|
croppedImage: !!croppedImage,
|
|
});
|
|
alert(
|
|
"Nessun rettangolo di ritaglio attivo o immagine selezionata!",
|
|
);
|
|
exitCropMode();
|
|
return;
|
|
}
|
|
isApplyingCrop = true;
|
|
const img = croppedImage;
|
|
const cropX = (cropRect.left - img.left) / img.scaleX;
|
|
const cropY = (cropRect.top - img.top) / img.scaleY;
|
|
const cropWidth = (cropRect.width * cropRect.scaleX) / img.scaleX;
|
|
const cropHeight = (cropRect.height * cropRect.scaleY) / img.scaleY;
|
|
|
|
fabric.Image.fromURL(
|
|
img.getSrc(),
|
|
(newImg) => {
|
|
newImg.set({
|
|
left: cropRect.left,
|
|
top: cropRect.top,
|
|
scaleX: img.scaleX,
|
|
scaleY: img.scaleY,
|
|
cropX: cropX,
|
|
cropY: cropY,
|
|
width: cropWidth,
|
|
height: cropHeight,
|
|
hasControls: true,
|
|
hasBorders: true,
|
|
cornerColor: "black",
|
|
cornerStrokeColor: "black",
|
|
cornerSize: 12,
|
|
borderColor: "black",
|
|
transparentCorners: false,
|
|
});
|
|
canvas.remove(img);
|
|
canvas.remove(cropRect);
|
|
canvas.add(newImg);
|
|
canvas.setActiveObject(newImg);
|
|
exitCropMode();
|
|
saveCanvasState();
|
|
updateLayersPanel();
|
|
canvas.renderAll();
|
|
},
|
|
{ crossOrigin: "anonymous" },
|
|
);
|
|
}
|
|
|
|
function enterBackgroundRemovalMode() {
|
|
const activeObject = canvas.getActiveObject();
|
|
if (!activeObject || activeObject.type !== "image") {
|
|
console.warn(
|
|
"Nessuna immagine selezionata per la rimozione dello sfondo",
|
|
);
|
|
alert(
|
|
"Seleziona un'immagine prima di attivare la rimozione dello sfondo!",
|
|
);
|
|
return;
|
|
}
|
|
isRemovingBackground = true;
|
|
backgroundRemovalImage = activeObject;
|
|
updateButtons();
|
|
}
|
|
|
|
function exitBackgroundRemovalMode() {
|
|
isRemovingBackground = false;
|
|
backgroundRemovalImage = null;
|
|
canvas.discardActiveObject();
|
|
canvas.renderAll();
|
|
updateButtons();
|
|
}
|
|
|
|
function handleBackgroundColorSelection(event) {
|
|
if (!isRemovingBackground || !backgroundRemovalImage) {
|
|
console.warn(
|
|
"Condizioni per la rimozione dello sfondo non soddisfatte",
|
|
);
|
|
return;
|
|
}
|
|
const pointer = canvas.getPointer(event.e);
|
|
const img = backgroundRemovalImage;
|
|
|
|
const tempCanvas = document.createElement("canvas");
|
|
tempCanvas.width = img.width;
|
|
tempCanvas.height = img.height;
|
|
const ctx = tempCanvas.getContext("2d");
|
|
ctx.drawImage(img.getElement(), 0, 0, img.width, img.height);
|
|
|
|
const imgLeft = img.left;
|
|
const imgTop = img.top;
|
|
const scaleX = img.scaleX;
|
|
const scaleY = img.scaleY;
|
|
const x = (pointer.x - imgLeft) / scaleX;
|
|
const y = (pointer.y - imgTop) / scaleY;
|
|
|
|
const pixelData = ctx.getImageData(x, y, 1, 1).data;
|
|
const targetColor = {
|
|
r: pixelData[0],
|
|
g: pixelData[1],
|
|
b: pixelData[2],
|
|
};
|
|
|
|
removeBackground(img, targetColor);
|
|
}
|
|
|
|
function removeBackground(img, targetColor) {
|
|
const tempCanvas = document.createElement("canvas");
|
|
tempCanvas.width = img.width;
|
|
tempCanvas.height = img.height;
|
|
const ctx = tempCanvas.getContext("2d");
|
|
ctx.drawImage(img.getElement(), 0, 0, img.width, img.height);
|
|
|
|
const imageData = ctx.getImageData(
|
|
0,
|
|
0,
|
|
tempCanvas.width,
|
|
tempCanvas.height,
|
|
);
|
|
const data = imageData.data;
|
|
const tolerance = 50;
|
|
|
|
for (let i = 0; i < data.length; i += 4) {
|
|
const r = data[i];
|
|
const g = data[i + 1];
|
|
const b = data[i + 2];
|
|
if (
|
|
Math.abs(r - targetColor.r) <= tolerance &&
|
|
Math.abs(g - targetColor.g) <= tolerance &&
|
|
Math.abs(b - targetColor.b) <= tolerance
|
|
) {
|
|
data[i + 3] = 0;
|
|
}
|
|
}
|
|
|
|
ctx.putImageData(imageData, 0, 0);
|
|
const newImageUrl = tempCanvas.toDataURL("image/png");
|
|
|
|
fabric.Image.fromURL(
|
|
newImageUrl,
|
|
(newImg) => {
|
|
newImg.set({
|
|
left: img.left,
|
|
top: img.top,
|
|
scaleX: img.scaleX,
|
|
scaleY: img.scaleY,
|
|
hasControls: true,
|
|
hasBorders: true,
|
|
cornerColor: "black",
|
|
cornerStrokeColor: "black",
|
|
cornerSize: 12,
|
|
borderColor: "black",
|
|
transparentCorners: false,
|
|
});
|
|
canvas.remove(img);
|
|
canvas.add(newImg);
|
|
canvas.setActiveObject(newImg);
|
|
exitBackgroundRemovalMode();
|
|
saveCanvasState();
|
|
updateLayersPanel();
|
|
canvas.renderAll();
|
|
},
|
|
{ crossOrigin: "anonymous" },
|
|
);
|
|
}
|
|
|
|
function removeImage() {
|
|
const activeObject = canvas.getActiveObject();
|
|
if (!activeObject || activeObject.type !== "image") {
|
|
console.warn("Nessuna immagine selezionata per la rimozione");
|
|
alert("Seleziona un'immagine da rimuovere!");
|
|
return;
|
|
}
|
|
canvas.remove(activeObject);
|
|
canvas.discardActiveObject();
|
|
saveCanvasState();
|
|
updateLayersPanel();
|
|
canvas.renderAll();
|
|
}
|
|
|
|
const addToCanvasBtn = document.getElementById("addToCanvasBtn");
|
|
if (addToCanvasBtn) {
|
|
addToCanvasBtn.addEventListener("click", () => {
|
|
const checkboxes = document.querySelectorAll(
|
|
".photo-checkbox:checked",
|
|
);
|
|
if (checkboxes.length === 0) {
|
|
alert("Seleziona almeno una foto!");
|
|
return;
|
|
}
|
|
checkboxes.forEach((cb) => {
|
|
const imgPath = cb.getAttribute("data-path");
|
|
fabric.Image.fromURL(
|
|
imgPath,
|
|
(img) => {
|
|
img.set({
|
|
left: Math.random() * 600,
|
|
top: Math.random() * 400,
|
|
scaleX: 0.5,
|
|
scaleY: 0.5,
|
|
hasControls: true,
|
|
hasBorders: true,
|
|
cornerColor: "black",
|
|
cornerStrokeColor: "black",
|
|
cornerSize: 12,
|
|
borderColor: "black",
|
|
transparentCorners: false,
|
|
});
|
|
canvas.add(img);
|
|
canvas.renderAll();
|
|
},
|
|
{ crossOrigin: "anonymous" },
|
|
);
|
|
});
|
|
checkboxes.forEach((cb) => (cb.checked = false));
|
|
saveCanvasState();
|
|
});
|
|
}
|
|
|
|
const saveCollageBtn = document.getElementById("saveCollageBtn");
|
|
if (saveCollageBtn) {
|
|
saveCollageBtn.addEventListener("click", async () => {
|
|
if (
|
|
canvas.getObjects().length === 0 &&
|
|
!canvas.backgroundImage
|
|
) {
|
|
alert("Il canvas è vuoto! Aggiungi almeno una foto.");
|
|
return;
|
|
}
|
|
const dataURL = canvas.toDataURL({
|
|
format: "jpeg",
|
|
quality: 0.8,
|
|
});
|
|
const blob = await (await fetch(dataURL)).blob();
|
|
const file = new File([blob], `collage_${Date.now()}.jpg`, {
|
|
type: "image/jpeg",
|
|
});
|
|
|
|
await handleFiles([file], iddatadb, idquotations);
|
|
document.getElementById("collageModal").style.display = "none";
|
|
loadPopupContent(iddatadb, idquotations);
|
|
});
|
|
}
|
|
|
|
const bringToFrontBtn = document.getElementById("bringToFrontBtn");
|
|
if (bringToFrontBtn) {
|
|
bringToFrontBtn.addEventListener("click", () => {
|
|
const activeObject = canvas.getActiveObject();
|
|
if (activeObject) {
|
|
canvas.bringToFront(activeObject);
|
|
canvas.renderAll();
|
|
saveCanvasState();
|
|
updateLayersPanel();
|
|
} else {
|
|
alert("Seleziona un'immagine sul canvas!");
|
|
}
|
|
});
|
|
}
|
|
|
|
const sendToBackBtn = document.getElementById("sendToBackBtn");
|
|
if (sendToBackBtn) {
|
|
sendToBackBtn.addEventListener("click", () => {
|
|
const activeObject = canvas.getActiveObject();
|
|
if (activeObject) {
|
|
canvas.sendToBack(activeObject);
|
|
canvas.renderAll();
|
|
saveCanvasState();
|
|
updateLayersPanel();
|
|
} else {
|
|
alert("Seleziona un'immagine sul canvas!");
|
|
}
|
|
});
|
|
}
|
|
|
|
const bringForwardBtn = document.getElementById("bringForwardBtn");
|
|
if (bringForwardBtn) {
|
|
bringForwardBtn.addEventListener("click", () => {
|
|
const activeObject = canvas.getActiveObject();
|
|
if (activeObject) {
|
|
canvas.bringForward(activeObject);
|
|
canvas.renderAll();
|
|
saveCanvasState();
|
|
updateLayersPanel();
|
|
} else {
|
|
alert("Seleziona un'immagine sul canvas!");
|
|
}
|
|
});
|
|
}
|
|
|
|
const sendBackwardBtn = document.getElementById("sendBackwardBtn");
|
|
if (sendBackwardBtn) {
|
|
sendBackwardBtn.addEventListener("click", () => {
|
|
const activeObject = canvas.getActiveObject();
|
|
if (activeObject) {
|
|
canvas.sendBackwards(activeObject);
|
|
canvas.renderAll();
|
|
saveCanvasState();
|
|
updateLayersPanel();
|
|
} else {
|
|
alert("Seleziona un'immagine sul canvas!");
|
|
}
|
|
});
|
|
}
|
|
|
|
const cropImageBtn = document.getElementById("cropImageBtn");
|
|
if (cropImageBtn) {
|
|
cropImageBtn.addEventListener("click", () => {
|
|
enterCropMode();
|
|
});
|
|
}
|
|
|
|
const applyCropBtn = document.getElementById("applyCropBtn");
|
|
if (applyCropBtn) {
|
|
applyCropBtn.addEventListener("click", () => {
|
|
applyCrop();
|
|
});
|
|
}
|
|
|
|
const cancelCropBtn = document.getElementById("cancelCropBtn");
|
|
if (cancelCropBtn) {
|
|
cancelCropBtn.addEventListener("click", () => {
|
|
exitCropMode();
|
|
});
|
|
}
|
|
|
|
const removeBackgroundBtn = document.getElementById(
|
|
"removeBackgroundBtn",
|
|
);
|
|
if (removeBackgroundBtn) {
|
|
removeBackgroundBtn.addEventListener("click", () => {
|
|
enterBackgroundRemovalMode();
|
|
});
|
|
}
|
|
|
|
const removeImageBtn = document.getElementById("removeImageBtn");
|
|
if (removeImageBtn) {
|
|
removeImageBtn.addEventListener("click", () => {
|
|
removeImage();
|
|
});
|
|
}
|
|
|
|
const undoBtn = document.getElementById("undoBtn");
|
|
if (undoBtn) {
|
|
undoBtn.addEventListener("click", () => {
|
|
undo();
|
|
});
|
|
}
|
|
|
|
const loader = document.getElementById("loader");
|
|
if (loader) {
|
|
loader.style.display = "none";
|
|
}
|
|
}
|
|
|
|
const photosButtons = document.querySelectorAll(".photos-btn");
|
|
const photosModal = document.getElementById("photosModal");
|
|
const closeBtn = document.querySelector(".close-btn");
|
|
|
|
if (photosButtons.length && photosModal && closeBtn) {
|
|
photosButtons.forEach((button) => {
|
|
button.addEventListener("click", function () {
|
|
const iddatadb = this.getAttribute("data-iddatadb") || null;
|
|
const idquotations =
|
|
this.getAttribute("data-idquotations") || null;
|
|
console.log("Apertura modale foto con:", {
|
|
iddatadb,
|
|
idquotations,
|
|
});
|
|
loadPopupContent(iddatadb, idquotations);
|
|
photosModal.style.display = "block";
|
|
document.querySelector(".overlay").style.display = "none";
|
|
});
|
|
});
|
|
|
|
closeBtn.addEventListener("click", function () {
|
|
photosModal.style.display = "none";
|
|
document.querySelector(".overlay").style.display = "none";
|
|
document.body.style.pointerEvents = "auto";
|
|
});
|
|
|
|
window.addEventListener("click", function (event) {
|
|
if (event.target === photosModal) {
|
|
photosModal.style.display = "none";
|
|
document.querySelector(".overlay").style.display = "none";
|
|
document.body.style.pointerEvents = "auto";
|
|
}
|
|
});
|
|
} else {
|
|
console.error("Elementi mancanti:", {
|
|
photosButtons,
|
|
photosModal,
|
|
closeBtn,
|
|
});
|
|
}
|
|
});
|