Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3aa2504f3c | |||
| c1a396f246 | |||
| a45ba1c8b3 |
@@ -31,6 +31,6 @@ Content-Length: 51
|
||||
< strict-transport-security: max-age=2592000
|
||||
< x-powered-by: ASP.NET
|
||||
< x-content-type-options: nosniff
|
||||
< date: Mon, 08 Sep 2025 06:40:14 GMT
|
||||
< date: Mon, 08 Sep 2025 11:59:10 GMT
|
||||
<
|
||||
* Connection #0 to host 93.43.5.102 left intact
|
||||
|
||||
@@ -10,16 +10,16 @@
|
||||
* issuer: C=US; O=Corporation Service Company; CN=Corporation Service Company RSA OV SSL CA
|
||||
* SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
|
||||
* using HTTP/2
|
||||
* [HTTP/2] [1] OPENED stream for https://93.43.5.102/limsapi/api/odata/CommessaWeb(529435)
|
||||
* [HTTP/2] [1] OPENED stream for https://93.43.5.102/limsapi/api/odata/CustomField(1083)?$expand=CustomFieldsValues
|
||||
* [HTTP/2] [1] [:method: GET]
|
||||
* [HTTP/2] [1] [:scheme: https]
|
||||
* [HTTP/2] [1] [:authority: 93.43.5.102]
|
||||
* [HTTP/2] [1] [:path: /limsapi/api/odata/CommessaWeb(529435)]
|
||||
* [HTTP/2] [1] [authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1laWRlbnRpZmllciI6IjQ5MiIsIlhhZlNlY3VyaXR5QXV0aFBhc3NlZCI6IlhhZlNlY3VyaXR5QXV0aFBhc3NlZCIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL25hbWUiOiJXZWJBcGlVc2VyIiwiWGFmU2VjdXJpdHkiOiJYYWZTZWN1cml0eSIsIlhhZkxvZ29uUGFyYW1zIjoicTFZS0xVNHQ4a3ZNVFZXeVVncFBUWElzeUFRSktPa29CU1FXRjVmbkY2VUF4Y3RUa3hJTE1rdUI0Z2FHU3JVQSIsImV4cCI6MTc1NzMyMDgxNCwiaXNzIjoiTXkiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjQyMDAifQ.enjh2WJVy0NQ8zEDX5S09glaAOamuzcG33TM_fTgTMo]
|
||||
* [HTTP/2] [1] [:path: /limsapi/api/odata/CustomField(1083)?$expand=CustomFieldsValues]
|
||||
* [HTTP/2] [1] [authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1laWRlbnRpZmllciI6IjQ5MiIsIlhhZlNlY3VyaXR5QXV0aFBhc3NlZCI6IlhhZlNlY3VyaXR5QXV0aFBhc3NlZCIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL25hbWUiOiJXZWJBcGlVc2VyIiwiWGFmU2VjdXJpdHkiOiJYYWZTZWN1cml0eSIsIlhhZkxvZ29uUGFyYW1zIjoicTFZS0xVNHQ4a3ZNVFZXeVVncFBUWElzeUFRSktPa29CU1FXRjVmbkY2VUF4Y3RUa3hJTE1rdUI0Z2FHU3JVQSIsImV4cCI6MTc1NzMzOTk1MSwiaXNzIjoiTXkiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjQyMDAifQ.JywaxXVFGeXH44RCOZUPfDGuEr5dt0cHAWN_vmIiFaw]
|
||||
* [HTTP/2] [1] [accept: application/json]
|
||||
> GET /limsapi/api/odata/CommessaWeb(529435) HTTP/2
|
||||
> GET /limsapi/api/odata/CustomField(1083)?$expand=CustomFieldsValues HTTP/2
|
||||
Host: 93.43.5.102
|
||||
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1laWRlbnRpZmllciI6IjQ5MiIsIlhhZlNlY3VyaXR5QXV0aFBhc3NlZCI6IlhhZlNlY3VyaXR5QXV0aFBhc3NlZCIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL25hbWUiOiJXZWJBcGlVc2VyIiwiWGFmU2VjdXJpdHkiOiJYYWZTZWN1cml0eSIsIlhhZkxvZ29uUGFyYW1zIjoicTFZS0xVNHQ4a3ZNVFZXeVVncFBUWElzeUFRSktPa29CU1FXRjVmbkY2VUF4Y3RUa3hJTE1rdUI0Z2FHU3JVQSIsImV4cCI6MTc1NzMyMDgxNCwiaXNzIjoiTXkiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjQyMDAifQ.enjh2WJVy0NQ8zEDX5S09glaAOamuzcG33TM_fTgTMo
|
||||
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1laWRlbnRpZmllciI6IjQ5MiIsIlhhZlNlY3VyaXR5QXV0aFBhc3NlZCI6IlhhZlNlY3VyaXR5QXV0aFBhc3NlZCIsImh0dHA6Ly9zY2hlbWFzLnhtbHNvYXAub3JnL3dzLzIwMDUvMDUvaWRlbnRpdHkvY2xhaW1zL25hbWUiOiJXZWJBcGlVc2VyIiwiWGFmU2VjdXJpdHkiOiJYYWZTZWN1cml0eSIsIlhhZkxvZ29uUGFyYW1zIjoicTFZS0xVNHQ4a3ZNVFZXeVVncFBUWElzeUFRSktPa29CU1FXRjVmbkY2VUF4Y3RUa3hJTE1rdUI0Z2FHU3JVQSIsImV4cCI6MTc1NzMzOTk1MSwiaXNzIjoiTXkiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjQyMDAifQ.JywaxXVFGeXH44RCOZUPfDGuEr5dt0cHAWN_vmIiFaw
|
||||
Accept: application/json
|
||||
|
||||
< HTTP/2 200
|
||||
@@ -30,6 +30,6 @@ Accept: application/json
|
||||
< odata-version: 4.0
|
||||
< x-powered-by: ASP.NET
|
||||
< x-content-type-options: nosniff
|
||||
< date: Mon, 08 Sep 2025 06:40:14 GMT
|
||||
< date: Mon, 08 Sep 2025 11:59:14 GMT
|
||||
<
|
||||
* Connection #0 to host 93.43.5.102 left intact
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
# Swagger Codegen Ignore
|
||||
# Generated by swagger-codegen https://github.com/swagger-api/swagger-codegen
|
||||
|
||||
# Use this file to prevent files from being overwritten by the generator.
|
||||
# The patterns follow closely to .gitignore or .dockerignore.
|
||||
|
||||
# As an example, the C# client generator defines ApiClient.cs.
|
||||
# You can make changes and tell Swagger Codgen to ignore just this file by uncommenting the following line:
|
||||
#ApiClient.cs
|
||||
|
||||
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
|
||||
#foo/*/qux
|
||||
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
|
||||
|
||||
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
|
||||
#foo/**/qux
|
||||
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
|
||||
|
||||
# You can also negate patterns with an exclamation (!).
|
||||
# For example, you can ignore all files in a docs folder with the file extension .md:
|
||||
#docs/*.md
|
||||
# Then explicitly reverse the ignore rule for a single file:
|
||||
#!docs/README.md
|
||||
@@ -0,0 +1 @@
|
||||
3.0.34
|
||||
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
+573
-13
@@ -396,11 +396,32 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
closeCollageBtn.addEventListener("click", () => {
|
||||
console.log("Chiusura modale collage");
|
||||
document.getElementById("collageModal").style.display = "none";
|
||||
if (isCropping) {
|
||||
console.log(
|
||||
"Chiusura modale durante ritaglio, esco dalla modalità ritaglio",
|
||||
);
|
||||
exitCropMode();
|
||||
}
|
||||
if (isRemovingBackground) {
|
||||
console.log(
|
||||
"Chiusura modale durante rimozione sfondo, esco dalla modalità",
|
||||
);
|
||||
exitBackgroundRemovalMode();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Inizializza canvas con Fabric.js
|
||||
let canvas;
|
||||
let cropRect = null;
|
||||
let isCropping = false;
|
||||
let croppedImage = null; // Memorizza l'immagine da ritagliare
|
||||
let isApplyingCrop = false; // Flag per prevenire duplicazioni
|
||||
let isRemovingBackground = false; // Flag per modalità rimozione sfondo
|
||||
let backgroundRemovalImage = null; // Immagine in modalità rimozione sfondo
|
||||
let history = []; // Pila per salvare gli stati del canvas
|
||||
const maxHistory = 20; // Limite massimo di stati nella pila
|
||||
|
||||
function initCollageCanvas() {
|
||||
if (typeof fabric === "undefined") {
|
||||
console.error("Fabric.js non è caricato!");
|
||||
@@ -413,8 +434,467 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
backgroundColor: "#fff",
|
||||
selection: true,
|
||||
});
|
||||
// Imposta stile globale per i controlli
|
||||
fabric.Object.prototype.set({
|
||||
cornerColor: "black",
|
||||
cornerStrokeColor: "black",
|
||||
cornerSize: 12,
|
||||
borderColor: "black",
|
||||
transparentCorners: false,
|
||||
});
|
||||
// Abilita ridimensionamento e trascinamento
|
||||
canvas.on("object:modified", () => canvas.renderAll());
|
||||
canvas.on("object:modified", () => {
|
||||
console.log("Oggetto modificato nel canvas");
|
||||
saveCanvasState();
|
||||
canvas.renderAll();
|
||||
});
|
||||
// Gestisci selezione per abilitare/disabilitare pulsanti
|
||||
canvas.on("selection:created", () => {
|
||||
console.log("Evento selection:created triggerato");
|
||||
updateButtons();
|
||||
});
|
||||
canvas.on("selection:updated", () => {
|
||||
console.log("Evento selection:updated triggerato");
|
||||
updateButtons();
|
||||
});
|
||||
canvas.on("selection:cleared", () => {
|
||||
console.log("Evento selection:cleared triggerato");
|
||||
if (!isCropping && !isRemovingBackground) {
|
||||
updateButtons();
|
||||
} else if (isCropping && cropRect) {
|
||||
console.log(
|
||||
"Ignoro selection:cleared perché in modalità ritaglio",
|
||||
);
|
||||
canvas.setActiveObject(cropRect); // Ripristina selezione del rettangolo
|
||||
canvas.renderAll();
|
||||
} else if (isRemovingBackground) {
|
||||
console.log(
|
||||
"Ignoro selection:cleared perché in modalità rimozione sfondo",
|
||||
);
|
||||
canvas.setActiveObject(backgroundRemovalImage); // Ripristina selezione dell'immagine
|
||||
canvas.renderAll();
|
||||
}
|
||||
});
|
||||
// Gestisci click sul canvas per la rimozione dello sfondo
|
||||
canvas.on("mouse:down", (event) => {
|
||||
if (isRemovingBackground && backgroundRemovalImage) {
|
||||
console.log(
|
||||
"Click sul canvas in modalità rimozione sfondo",
|
||||
);
|
||||
handleBackgroundColorSelection(event);
|
||||
}
|
||||
});
|
||||
// Salva lo stato iniziale del canvas
|
||||
saveCanvasState();
|
||||
// Forza un aggiornamento iniziale dei pulsanti
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
// Salva lo stato del canvas nella pila
|
||||
function saveCanvasState() {
|
||||
if (isCropping || isRemovingBackground) {
|
||||
console.log(
|
||||
"Non salvo lo stato perché in modalità ritaglio o rimozione sfondo",
|
||||
);
|
||||
return;
|
||||
}
|
||||
console.log("Salvataggio stato del canvas");
|
||||
const state = JSON.stringify(
|
||||
canvas.toJSON([
|
||||
"cornerColor",
|
||||
"cornerStrokeColor",
|
||||
"cornerSize",
|
||||
"borderColor",
|
||||
"transparentCorners",
|
||||
]),
|
||||
);
|
||||
history.push(state);
|
||||
if (history.length > maxHistory) {
|
||||
history.shift(); // Rimuovi lo stato più vecchio se superato il limite
|
||||
}
|
||||
console.log("Stato salvato, lunghezza pila:", history.length);
|
||||
updateButtons();
|
||||
}
|
||||
|
||||
// Ripristina l'ultimo stato del canvas
|
||||
function undo() {
|
||||
if (history.length <= 1) {
|
||||
console.log("Nessuno stato da annullare");
|
||||
return;
|
||||
}
|
||||
console.log("Annullamento ultima azione");
|
||||
history.pop(); // Rimuovi lo stato corrente
|
||||
const previousState = history[history.length - 1];
|
||||
if (previousState) {
|
||||
canvas.clear();
|
||||
canvas.loadFromJSON(previousState, () => {
|
||||
canvas.renderAll();
|
||||
console.log("Stato ripristinato");
|
||||
updateButtons();
|
||||
});
|
||||
} else {
|
||||
console.warn("Nessuno stato precedente disponibile");
|
||||
canvas.clear();
|
||||
canvas.setBackgroundColor("#fff");
|
||||
canvas.renderAll();
|
||||
updateButtons();
|
||||
}
|
||||
}
|
||||
|
||||
// Aggiorna stato dei pulsanti
|
||||
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();
|
||||
console.log(
|
||||
"updateButtons: activeObject =",
|
||||
activeObject ? activeObject.type : null,
|
||||
"isCropping =",
|
||||
isCropping,
|
||||
"isRemovingBackground =",
|
||||
isRemovingBackground,
|
||||
"history.length =",
|
||||
history.length,
|
||||
);
|
||||
if (isCropping && cropRect) {
|
||||
console.log(
|
||||
"Modo ritaglio attivo, applyCropBtn e cancelCropBtn abilitati",
|
||||
);
|
||||
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) {
|
||||
console.log(
|
||||
"Modo rimozione sfondo attivo, removeBackgroundBtn disabilitato",
|
||||
);
|
||||
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
|
||||
) {
|
||||
console.log(
|
||||
"Abilitazione cropImageBtn, removeBackgroundBtn e removeImageBtn",
|
||||
);
|
||||
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 {
|
||||
console.log("Disabilitazione tutti i pulsanti");
|
||||
cropBtn.disabled = true;
|
||||
applyCropBtn.disabled = true;
|
||||
cancelCropBtn.disabled = true;
|
||||
removeBackgroundBtn.disabled = true;
|
||||
removeImageBtn.disabled = true;
|
||||
undoBtn.disabled = history.length <= 1;
|
||||
instruction.style.display = "none";
|
||||
}
|
||||
}
|
||||
|
||||
// Entra in modalità ritaglio
|
||||
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;
|
||||
}
|
||||
console.log(
|
||||
"Entrata in modalità ritaglio per immagine:",
|
||||
activeObject,
|
||||
);
|
||||
isCropping = true;
|
||||
croppedImage = activeObject; // Memorizza l'immagine da ritagliare
|
||||
canvas.discardActiveObject(); // Deseleziona l'immagine
|
||||
// Crea un rettangolo di ritaglio
|
||||
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();
|
||||
console.log("Rettangolo di ritaglio creato e applicato");
|
||||
}
|
||||
|
||||
// Esci dalla modalità ritaglio
|
||||
function exitCropMode() {
|
||||
if (cropRect) {
|
||||
console.log("Rimozione rettangolo di ritaglio");
|
||||
canvas.remove(cropRect);
|
||||
cropRect = null;
|
||||
}
|
||||
isCropping = false;
|
||||
croppedImage = null;
|
||||
isApplyingCrop = false;
|
||||
canvas.discardActiveObject();
|
||||
canvas.renderAll();
|
||||
updateButtons();
|
||||
console.log("Uscita dalla modalità ritaglio");
|
||||
}
|
||||
|
||||
// Applica il ritaglio
|
||||
function applyCrop() {
|
||||
if (isApplyingCrop) {
|
||||
console.log("applyCrop già in esecuzione, ignoro chiamata");
|
||||
return;
|
||||
}
|
||||
console.log("applyCrop chiamato, stato:", {
|
||||
isCropping,
|
||||
cropRect: !!cropRect,
|
||||
croppedImage: !!croppedImage,
|
||||
});
|
||||
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;
|
||||
console.log("Applicazione ritaglio all'immagine:", croppedImage);
|
||||
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;
|
||||
console.log("Parametri di ritaglio:", {
|
||||
cropX,
|
||||
cropY,
|
||||
cropWidth,
|
||||
cropHeight,
|
||||
});
|
||||
|
||||
// Crea un'immagine ritagliata
|
||||
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); // Rimuovi l'immagine originale
|
||||
canvas.remove(cropRect); // Rimuovi il rettangolo di ritaglio
|
||||
canvas.add(newImg); // Aggiungi l'immagine ritagliata
|
||||
canvas.setActiveObject(newImg);
|
||||
exitCropMode();
|
||||
saveCanvasState(); // Salva lo stato dopo il ritaglio
|
||||
canvas.renderAll();
|
||||
console.log("Ritaglio applicato con successo");
|
||||
},
|
||||
{ crossOrigin: "anonymous" },
|
||||
);
|
||||
}
|
||||
|
||||
// Entra in modalità rimozione sfondo
|
||||
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;
|
||||
}
|
||||
console.log(
|
||||
"Entrata in modalità rimozione sfondo per immagine:",
|
||||
activeObject,
|
||||
);
|
||||
isRemovingBackground = true;
|
||||
backgroundRemovalImage = activeObject;
|
||||
updateButtons();
|
||||
console.log(
|
||||
"Modalità rimozione sfondo attivata, clicca sull'immagine per selezionare il colore",
|
||||
);
|
||||
}
|
||||
|
||||
// Esci dalla modalità rimozione sfondo
|
||||
function exitBackgroundRemovalMode() {
|
||||
isRemovingBackground = false;
|
||||
backgroundRemovalImage = null;
|
||||
canvas.discardActiveObject();
|
||||
canvas.renderAll();
|
||||
updateButtons();
|
||||
console.log("Uscita dalla modalità rimozione sfondo");
|
||||
}
|
||||
|
||||
// Gestisci la selezione del colore dello sfondo
|
||||
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;
|
||||
|
||||
// Crea una canvas temporanea per ottenere i dati dei pixel
|
||||
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);
|
||||
|
||||
// Calcola la posizione relativa del click rispetto all'immagine
|
||||
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;
|
||||
|
||||
// Ottieni il colore del pixel cliccato
|
||||
const pixelData = ctx.getImageData(x, y, 1, 1).data;
|
||||
const targetColor = {
|
||||
r: pixelData[0],
|
||||
g: pixelData[1],
|
||||
b: pixelData[2],
|
||||
};
|
||||
console.log("Colore dello sfondo selezionato:", targetColor);
|
||||
|
||||
// Rimuovi il colore dello sfondo
|
||||
removeBackground(img, targetColor);
|
||||
}
|
||||
|
||||
// Rimuovi il colore dello sfondo
|
||||
function removeBackground(img, targetColor) {
|
||||
console.log("Inizio rimozione sfondo con colore:", 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; // Tolleranza per colori simili
|
||||
|
||||
// Scansiona i pixel e rendi trasparenti quelli che corrispondono al colore target
|
||||
for (let i = 0; i < data.length; i += 4) {
|
||||
const r = data[i];
|
||||
const g = data[i + 1];
|
||||
const b = data[i + 2];
|
||||
// Verifica se il colore è simile al targetColor
|
||||
if (
|
||||
Math.abs(r - targetColor.r) <= tolerance &&
|
||||
Math.abs(g - targetColor.g) <= tolerance &&
|
||||
Math.abs(b - targetColor.b) <= tolerance
|
||||
) {
|
||||
data[i + 3] = 0; // Imposta l'alpha a 0 (trasparente)
|
||||
}
|
||||
}
|
||||
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
const newImageUrl = tempCanvas.toDataURL("image/png");
|
||||
|
||||
// Crea una nuova immagine con lo sfondo rimosso
|
||||
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); // Rimuovi l'immagine originale
|
||||
canvas.add(newImg); // Aggiungi l'immagine con sfondo rimosso
|
||||
canvas.setActiveObject(newImg);
|
||||
exitBackgroundRemovalMode();
|
||||
saveCanvasState(); // Salva lo stato dopo la rimozione dello sfondo
|
||||
canvas.renderAll();
|
||||
console.log("Sfondo rimosso con successo");
|
||||
},
|
||||
{ crossOrigin: "anonymous" },
|
||||
);
|
||||
}
|
||||
|
||||
// Rimuovi l'immagine selezionata
|
||||
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;
|
||||
}
|
||||
console.log("Rimozione immagine selezionata:", activeObject);
|
||||
canvas.remove(activeObject);
|
||||
canvas.discardActiveObject();
|
||||
saveCanvasState(); // Salva lo stato dopo la rimozione
|
||||
canvas.renderAll();
|
||||
console.log("Immagine rimossa con successo");
|
||||
}
|
||||
|
||||
// Aggiungi foto selezionate al canvas
|
||||
@@ -430,21 +910,35 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
}
|
||||
checkboxes.forEach((cb) => {
|
||||
const imgPath = cb.getAttribute("data-path");
|
||||
fabric.Image.fromURL(imgPath, (img) => {
|
||||
img.set({
|
||||
left: Math.random() * 600, // Posizione random iniziale
|
||||
top: Math.random() * 400,
|
||||
scaleX: 0.5, // Scala iniziale
|
||||
scaleY: 0.5,
|
||||
hasControls: true, // Abilita resize/rotate
|
||||
hasBorders: true,
|
||||
});
|
||||
canvas.add(img);
|
||||
canvas.renderAll();
|
||||
});
|
||||
fabric.Image.fromURL(
|
||||
imgPath,
|
||||
(img) => {
|
||||
img.set({
|
||||
left: Math.random() * 600, // Posizione random iniziale
|
||||
top: Math.random() * 400,
|
||||
scaleX: 0.5, // Scala iniziale
|
||||
scaleY: 0.5,
|
||||
hasControls: true, // Abilita resize/rotate
|
||||
hasBorders: true,
|
||||
cornerColor: "black",
|
||||
cornerStrokeColor: "black",
|
||||
cornerSize: 12,
|
||||
borderColor: "black",
|
||||
transparentCorners: false,
|
||||
});
|
||||
canvas.add(img);
|
||||
canvas.renderAll();
|
||||
console.log(
|
||||
"Immagine aggiunta al canvas:",
|
||||
imgPath,
|
||||
);
|
||||
},
|
||||
{ crossOrigin: "anonymous" },
|
||||
);
|
||||
});
|
||||
// Deseleziona checkbox dopo aggiunta
|
||||
checkboxes.forEach((cb) => (cb.checked = false));
|
||||
saveCanvasState(); // Salva lo stato dopo l'aggiunta
|
||||
});
|
||||
}
|
||||
|
||||
@@ -470,6 +964,7 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
// Chiudi modale e ricarica popup
|
||||
document.getElementById("collageModal").style.display = "none";
|
||||
loadPopupContent(iddatadb);
|
||||
console.log("Collage salvato e modale chiuso");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -479,7 +974,10 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
clearCanvasBtn.addEventListener("click", () => {
|
||||
canvas.clear();
|
||||
canvas.setBackgroundColor("#fff");
|
||||
history = []; // Resetta la pila di stati
|
||||
saveCanvasState(); // Salva lo stato vuoto
|
||||
canvas.renderAll();
|
||||
console.log("Canvas pulito");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -491,6 +989,8 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
if (activeObject) {
|
||||
canvas.bringToFront(activeObject);
|
||||
canvas.renderAll();
|
||||
saveCanvasState(); // Salva lo stato dopo il cambio di livello
|
||||
console.log("Oggetto portato in primo piano");
|
||||
} else {
|
||||
alert("Seleziona un'immagine sul canvas!");
|
||||
}
|
||||
@@ -504,6 +1004,8 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
if (activeObject) {
|
||||
canvas.sendToBack(activeObject);
|
||||
canvas.renderAll();
|
||||
saveCanvasState(); // Salva lo stato dopo il cambio di livello
|
||||
console.log("Oggetto mandato in fondo");
|
||||
} else {
|
||||
alert("Seleziona un'immagine sul canvas!");
|
||||
}
|
||||
@@ -517,6 +1019,8 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
if (activeObject) {
|
||||
canvas.bringForward(activeObject);
|
||||
canvas.renderAll();
|
||||
saveCanvasState(); // Salva lo stato dopo il cambio di livello
|
||||
console.log("Oggetto spostato avanti di un livello");
|
||||
} else {
|
||||
alert("Seleziona un'immagine sul canvas!");
|
||||
}
|
||||
@@ -530,12 +1034,68 @@ document.addEventListener("DOMContentLoaded", function () {
|
||||
if (activeObject) {
|
||||
canvas.sendBackwards(activeObject);
|
||||
canvas.renderAll();
|
||||
saveCanvasState(); // Salva lo stato dopo il cambio di livello
|
||||
console.log("Oggetto spostato indietro di un livello");
|
||||
} else {
|
||||
alert("Seleziona un'immagine sul canvas!");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Gestione ritaglio immagini
|
||||
const cropImageBtn = document.getElementById("cropImageBtn");
|
||||
if (cropImageBtn) {
|
||||
cropImageBtn.addEventListener("click", () => {
|
||||
console.log("Pulsante Ritaglia cliccato");
|
||||
enterCropMode();
|
||||
});
|
||||
}
|
||||
|
||||
const applyCropBtn = document.getElementById("applyCropBtn");
|
||||
if (applyCropBtn) {
|
||||
applyCropBtn.addEventListener("click", () => {
|
||||
console.log("Pulsante Applica Ritaglio cliccato");
|
||||
applyCrop();
|
||||
});
|
||||
}
|
||||
|
||||
const cancelCropBtn = document.getElementById("cancelCropBtn");
|
||||
if (cancelCropBtn) {
|
||||
cancelCropBtn.addEventListener("click", () => {
|
||||
console.log("Pulsante Annulla Ritaglio cliccato");
|
||||
exitCropMode();
|
||||
});
|
||||
}
|
||||
|
||||
// Gestione rimozione sfondo
|
||||
const removeBackgroundBtn = document.getElementById(
|
||||
"removeBackgroundBtn",
|
||||
);
|
||||
if (removeBackgroundBtn) {
|
||||
removeBackgroundBtn.addEventListener("click", () => {
|
||||
console.log("Pulsante Rimuovi Sfondo cliccato");
|
||||
enterBackgroundRemovalMode();
|
||||
});
|
||||
}
|
||||
|
||||
// Gestione rimozione immagine
|
||||
const removeImageBtn = document.getElementById("removeImageBtn");
|
||||
if (removeImageBtn) {
|
||||
removeImageBtn.addEventListener("click", () => {
|
||||
console.log("Pulsante Rimuovi Immagine cliccato");
|
||||
removeImage();
|
||||
});
|
||||
}
|
||||
|
||||
// Gestione undo
|
||||
const undoBtn = document.getElementById("undoBtn");
|
||||
if (undoBtn) {
|
||||
undoBtn.addEventListener("click", () => {
|
||||
console.log("Pulsante Annulla cliccato");
|
||||
undo();
|
||||
});
|
||||
}
|
||||
|
||||
// Assicurati che il loader sia nascosto all'apertura del popup
|
||||
const loader = document.getElementById("loader");
|
||||
if (loader) {
|
||||
|
||||
@@ -4,6 +4,8 @@ include('include/headscript.php');
|
||||
// Includi Fabric.js solo per questa pagina
|
||||
?>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/5.3.1/fabric.min.js"></script>
|
||||
|
||||
<?php
|
||||
// Includi l'autoloader di Composer
|
||||
require_once __DIR__ . '/../../vendor/autoload.php';
|
||||
@@ -171,7 +173,7 @@ $result->saveToFile($qrCodeFile);
|
||||
<img id="enlargedImage" class="image-modal-content" src="" alt="Immagine ingrandita">
|
||||
</div>
|
||||
|
||||
<!-- Nuovo modale per collage -->
|
||||
<!-- Modale per collage -->
|
||||
<div id="collageModal" class="modal" style="display: none; position: fixed; z-index: 1002; left: 0; top: 0; width: 100%; height: 100%; overflow: auto; background-color: rgba(0,0,0,0.8);">
|
||||
<div class="modal-content" style="background: white; margin: 5% auto; padding: 20px; width: 80%; max-width: 1200px; position: relative;">
|
||||
<span class="close-collage" style="position: absolute; top: 10px; right: 20px; font-size: 30px; cursor: pointer;">×</span>
|
||||
@@ -194,13 +196,20 @@ $result->saveToFile($qrCodeFile);
|
||||
<canvas id="collageCanvas" width="800" height="600" style="border: 1px solid #ccc; margin-top: 20px;"></canvas>
|
||||
|
||||
<!-- Bottoni azioni -->
|
||||
<div style="margin-top: 20px;">
|
||||
<button id="saveCollageBtn">Salva Collage</button>
|
||||
<button id="clearCanvasBtn">Pulisci Canvas</button>
|
||||
<button id="bringToFrontBtn" title="Porta in primo piano">In Alto</button>
|
||||
<button id="sendToBackBtn" title="Manda in fondo">In Fondo</button>
|
||||
<button id="bringForwardBtn" title="Sposta avanti di un livello">Avanti</button>
|
||||
<button id="sendBackwardBtn" title="Sposta indietro di un livello">Indietro</button>
|
||||
<div style="margin-top: 20px; display: flex; flex-wrap: wrap; gap: 5px;">
|
||||
<button id="saveCollageBtn" title="Salva il collage"><i class="fas fa-save"></i></button>
|
||||
<!-- <button id="clearCanvasBtn" title="Pulisci il canvas"><i class="fas fa-trash"></i></button> -->
|
||||
<button id="bringToFrontBtn" title="Porta in primo piano"><i class="fas fa-arrow-up"></i></button>
|
||||
<button id="sendToBackBtn" title="Manda in fondo"><i class="fas fa-arrow-down"></i></button>
|
||||
<button id="bringForwardBtn" title="Sposta avanti di un livello"><i class="fas fa-arrow-circle-up"></i></button>
|
||||
<button id="sendBackwardBtn" title="Sposta indietro di un livello"><i class="fas fa-arrow-circle-down"></i></button>
|
||||
<button id="cropImageBtn" title="Ritaglia immagine selezionata" disabled><i class="fas fa-crop"></i></button>
|
||||
<button id="applyCropBtn" title="Applica ritaglio" disabled><i class="fas fa-crop"></i> Applica</button>
|
||||
<button id="cancelCropBtn" title="Annulla ritaglio" disabled><i class="fas fa-crop"></i> Annulla</button>
|
||||
<button id="removeBackgroundBtn" title="Rimuovi sfondo immagine selezionata" disabled><i class="fas fa-eraser"></i> Rimuovi Sfondo</button>
|
||||
<button id="removeImageBtn" title="Rimuovi immagine selezionata" disabled><i class="fas fa-trash-alt"></i> Rimuovi</button>
|
||||
<button id="undoBtn" title="Annulla ultima azione" disabled><i class="fas fa-undo"></i></button>
|
||||
<p id="backgroundRemovalInstruction" style="display: none; color: #007bff;">Clicca sull'immagine per selezionare il colore dello sfondo da rimuovere</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -283,4 +292,56 @@ $result->saveToFile($qrCodeFile);
|
||||
font-size: 16px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
/* Stile per i pulsanti del modale collage */
|
||||
#collageModal button {
|
||||
padding: 8px 12px;
|
||||
margin: 5px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
#saveCollageBtn {
|
||||
background: #28a745;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#clearCanvasBtn {
|
||||
background: #dc3545;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#bringToFrontBtn,
|
||||
#sendToBackBtn,
|
||||
#bringForwardBtn,
|
||||
#sendBackwardBtn {
|
||||
background: #007bff;
|
||||
color: white;
|
||||
padding: 8px;
|
||||
/* Pulsanti solo icona più piccoli */
|
||||
}
|
||||
|
||||
#cropImageBtn,
|
||||
#applyCropBtn,
|
||||
#cancelCropBtn,
|
||||
#removeBackgroundBtn,
|
||||
#removeImageBtn,
|
||||
#undoBtn {
|
||||
background: #ffc107;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#collageModal button:disabled {
|
||||
background: #ccc;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
#collageModal button i {
|
||||
font-size: 16px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user