Implementa o editor interativo de Canvas para montagem livre de cartazes

This commit is contained in:
2026-06-07 16:40:35 +00:00
parent 264c38a7ce
commit a31764811b
3 changed files with 613 additions and 7 deletions
+521 -6
View File
@@ -7185,10 +7185,35 @@ document.addEventListener('DOMContentLoaded', () => {
const tamanho = document.getElementById('cartazTamanhoSelect') ? document.getElementById('cartazTamanhoSelect').value : 'A4'; const tamanho = document.getElementById('cartazTamanhoSelect') ? document.getElementById('cartazTamanhoSelect').value : 'A4';
const orientacao = document.getElementById('cartazOrientacaoSelect') ? document.getElementById('cartazOrientacaoSelect').value : 'retrato'; const orientacao = document.getElementById('cartazOrientacaoSelect') ? document.getElementById('cartazOrientacaoSelect').value : 'retrato';
const imgContainerHtml = cartazPreviewImageContainer.style.display === 'block' const imgContainerHtml = cartazPreviewImageContainer.style.display === 'block' && !canvasModeActive
? `<div style="width: 100%; margin-bottom: 20px; border-radius: 8px; overflow: hidden; border: 2px solid rgba(0,0,0,0.1); text-align: center; background: rgba(0,0,0,0.02);"><img src="${cartazPreviewImage.src}" style="max-width: 100%; max-height: 350px; object-fit: contain; display: inline-block;"></div>` ? `<div style="width: 100%; margin-bottom: 20px; border-radius: 8px; overflow: hidden; border: 2px solid rgba(0,0,0,0.1); text-align: center; background: rgba(0,0,0,0.02);"><img src="${cartazPreviewImage.src}" style="max-width: 100%; max-height: 350px; object-fit: contain; display: inline-block;"></div>`
: ''; : '';
let printContent = '';
if (canvasModeActive) {
// Clone printable area and cleanup handles / active state borders for print output
const tempContainer = document.createElement('div');
tempContainer.innerHTML = cartazPrintableArea.innerHTML;
tempContainer.querySelectorAll('.canvas-resize-handle').forEach(h => h.remove());
tempContainer.querySelectorAll('.canvas-item').forEach(item => {
item.classList.remove('active-item');
item.removeAttribute('contenteditable');
// We can remove border style only if it was a dashed editing border
if (item.style.border.includes('dashed')) {
item.style.border = 'none';
}
});
printContent = tempContainer.innerHTML;
} else {
printContent = `
<h1>${title}</h1>
${imgContainerHtml}
<div class="content-area">
${cartazPreviewContent.innerHTML}
</div>
`;
}
const printWindow = window.open('', '_blank'); const printWindow = window.open('', '_blank');
printWindow.document.write(` printWindow.document.write(`
<html> <html>
@@ -7225,6 +7250,9 @@ document.addEventListener('DOMContentLoaded', () => {
border: ${border === 'none' ? 'none' : `${border} ${text}`}; border: ${border === 'none' ? 'none' : `${border} ${text}`};
display: flex; display: flex;
flex-direction: column; flex-direction: column;
position: relative;
overflow: hidden;
container-type: inline-size;
} }
h1 { h1 {
text-align: center; text-align: center;
@@ -7260,6 +7288,18 @@ document.addEventListener('DOMContentLoaded', () => {
li { li {
margin-bottom: 12px; margin-bottom: 12px;
} }
/* Estilos específicos do Canvas no PDF/Print */
.canvas-item {
position: absolute !important;
box-sizing: border-box;
background: rgba(255, 255, 255, 0.3);
border-radius: 8px;
padding: 10px;
border: none !important;
box-shadow: none !important;
}
@media print { @media print {
body { background: transparent; padding: 0; display: block; } body { background: transparent; padding: 0; display: block; }
.cartaz-frame { .cartaz-frame {
@@ -7277,11 +7317,7 @@ document.addEventListener('DOMContentLoaded', () => {
</head> </head>
<body> <body>
<div class="cartaz-frame"> <div class="cartaz-frame">
<h1>${title}</h1> ${printContent}
${imgContainerHtml}
<div class="content-area">
${cartazPreviewContent.innerHTML}
</div>
</div> </div>
<script> <script>
window.onload = function() { window.onload = function() {
@@ -7409,4 +7445,483 @@ document.addEventListener('DOMContentLoaded', () => {
cartazesHistoryContainer.innerHTML = '<div style="color: #ef4444; padding: 20px;">Erro ao carregar histórico de cartazes.</div>'; cartazesHistoryContainer.innerHTML = '<div style="color: #ef4444; padding: 20px;">Erro ao carregar histórico de cartazes.</div>';
} }
} }
// --- MODO DESIGN CANVAS (EDITOR INTERATIVO DE CARTAZES) ---
const btnCanvasModeToggle = document.getElementById('btnCanvasModeToggle');
const canvasControlPanel = document.getElementById('canvasControlPanel');
const btnCanvasAddText = document.getElementById('btnCanvasAddText');
const btnCanvasAddCard = document.getElementById('btnCanvasAddCard');
const canvasFontFamily = document.getElementById('canvasFontFamily');
const canvasFontSize = document.getElementById('canvasFontSize');
const canvasTextColor = document.getElementById('canvasTextColor');
const canvasBgColorInput = document.getElementById('canvasBgColor');
const btnCanvasZIndexUp = document.getElementById('btnCanvasZIndexUp');
const btnCanvasZIndexDown = document.getElementById('btnCanvasZIndexDown');
const btnCanvasDelete = document.getElementById('btnCanvasDelete');
let canvasModeActive = false;
let selectedCanvasItem = null;
let isDraggingCanvas = false;
let isResizingCanvas = false;
let dragStartX, dragStartY;
let dragStartLeft, dragStartTop;
let dragStartWidth, dragStartHeight;
function enterCanvasMode() {
canvasModeActive = true;
if (btnCanvasModeToggle) {
btnCanvasModeToggle.textContent = '💾 Salvar Canvas';
btnCanvasModeToggle.style.background = '#10a37f';
btnCanvasModeToggle.style.color = 'white';
}
if (canvasControlPanel) canvasControlPanel.style.display = 'flex';
cartazPrintableArea.style.position = 'relative';
const rectParent = cartazPrintableArea.getBoundingClientRect();
const items = [];
if (cartazPreviewTitle) items.push(cartazPreviewTitle);
if (cartazPreviewImageContainer && cartazPreviewImageContainer.style.display !== 'none') {
items.push(cartazPreviewImageContainer);
}
const cards = Array.from(cartazPreviewContent.children);
cards.forEach(card => {
items.push(card);
});
const clientRects = items.map(item => item.getBoundingClientRect());
items.forEach((item, index) => {
const rect = clientRects[index];
const leftPercent = ((rect.left - rectParent.left) / rectParent.width) * 100;
const topPercent = ((rect.top - rectParent.top) / rectParent.height) * 100;
const widthPercent = (rect.width / rectParent.width) * 100;
const heightPercent = (rect.height / rectParent.height) * 100;
item.classList.add('canvas-item');
item.style.position = 'absolute';
item.style.left = `${leftPercent}%`;
item.style.top = `${topPercent}%`;
item.style.width = `${widthPercent}%`;
item.style.height = `${heightPercent}%`;
item.style.margin = '0';
item.setAttribute('contenteditable', 'true');
if (!item.querySelector('.canvas-resize-handle')) {
const handle = document.createElement('div');
handle.className = 'canvas-resize-handle';
item.appendChild(handle);
}
if (item.parentNode === cartazPreviewContent) {
cartazPrintableArea.appendChild(item);
}
setupCanvasItemEvents(item);
});
cartazPreviewContent.style.display = 'none';
showToast('Modo Design Canvas ativado! Arraste, redimensione e clique duas vezes para editar o texto.', 'info');
}
function exitCanvasMode() {
canvasModeActive = false;
if (btnCanvasModeToggle) {
btnCanvasModeToggle.textContent = '🎨 Design Canvas';
btnCanvasModeToggle.style.background = 'transparent';
btnCanvasModeToggle.style.color = 'var(--text-secondary)';
}
if (canvasControlPanel) canvasControlPanel.style.display = 'none';
if (selectedCanvasItem) {
selectedCanvasItem.classList.remove('active-item');
selectedCanvasItem = null;
}
const items = cartazPrintableArea.querySelectorAll('.canvas-item');
items.forEach(item => {
item.removeAttribute('contenteditable');
});
showToast('Layout do Canvas salvo com sucesso!', 'success');
}
function setupCanvasItemEvents(item) {
item.addEventListener('click', (e) => {
if (!canvasModeActive) return;
e.stopPropagation();
if (selectedCanvasItem) {
selectedCanvasItem.classList.remove('active-item');
}
selectedCanvasItem = item;
item.classList.add('active-item');
updateToolbarForSelected();
});
item.addEventListener('mousedown', (e) => {
if (!canvasModeActive) return;
if (e.target.classList.contains('canvas-resize-handle')) return;
if (document.activeElement === item && e.target !== item && !e.target.classList.contains('canvas-item')) {
return;
}
e.preventDefault();
selectedCanvasItem = item;
document.querySelectorAll('.canvas-item').forEach(el => el.classList.remove('active-item'));
item.classList.add('active-item');
updateToolbarForSelected();
isDraggingCanvas = true;
dragStartX = e.clientX;
dragStartY = e.clientY;
const parentRect = cartazPrintableArea.getBoundingClientRect();
const itemRect = item.getBoundingClientRect();
dragStartLeft = ((itemRect.left - parentRect.left) / parentRect.width) * 100;
dragStartTop = ((itemRect.top - parentRect.top) / parentRect.height) * 100;
document.addEventListener('mousemove', handleCanvasDrag);
document.addEventListener('mouseup', stopCanvasDrag);
});
item.addEventListener('touchstart', (e) => {
if (!canvasModeActive) return;
if (e.target.classList.contains('canvas-resize-handle')) return;
if (document.activeElement === item && e.target !== item) return;
selectedCanvasItem = item;
document.querySelectorAll('.canvas-item').forEach(el => el.classList.remove('active-item'));
item.classList.add('active-item');
updateToolbarForSelected();
isDraggingCanvas = true;
const touch = e.touches[0];
dragStartX = touch.clientX;
dragStartY = touch.clientY;
const parentRect = cartazPrintableArea.getBoundingClientRect();
const itemRect = item.getBoundingClientRect();
dragStartLeft = ((itemRect.left - parentRect.left) / parentRect.width) * 100;
dragStartTop = ((itemRect.top - parentRect.top) / parentRect.height) * 100;
document.addEventListener('touchmove', handleCanvasTouchDrag, { passive: false });
document.addEventListener('touchend', stopCanvasDrag);
});
const handle = item.querySelector('.canvas-resize-handle');
if (handle) {
handle.addEventListener('mousedown', (e) => {
if (!canvasModeActive) return;
e.stopPropagation();
e.preventDefault();
isResizingCanvas = true;
dragStartX = e.clientX;
dragStartY = e.clientY;
const parentRect = cartazPrintableArea.getBoundingClientRect();
const itemRect = item.getBoundingClientRect();
dragStartWidth = (itemRect.width / parentRect.width) * 100;
dragStartHeight = (itemRect.height / parentRect.height) * 100;
document.addEventListener('mousemove', handleCanvasResize);
document.addEventListener('mouseup', stopCanvasResize);
});
handle.addEventListener('touchstart', (e) => {
if (!canvasModeActive) return;
e.stopPropagation();
e.preventDefault();
isResizingCanvas = true;
const touch = e.touches[0];
dragStartX = touch.clientX;
dragStartY = touch.clientY;
const parentRect = cartazPrintableArea.getBoundingClientRect();
const itemRect = item.getBoundingClientRect();
dragStartWidth = (itemRect.width / parentRect.width) * 100;
dragStartHeight = (itemRect.height / parentRect.height) * 100;
document.addEventListener('touchmove', handleCanvasTouchResize, { passive: false });
document.addEventListener('touchend', stopCanvasResize);
});
}
}
function handleCanvasDrag(e) {
if (!isDraggingCanvas || !selectedCanvasItem) return;
const dx = e.clientX - dragStartX;
const dy = e.clientY - dragStartY;
const parentRect = cartazPrintableArea.getBoundingClientRect();
const dxPercent = (dx / parentRect.width) * 100;
const dyPercent = (dy / parentRect.height) * 100;
let newLeft = dragStartLeft + dxPercent;
let newTop = dragStartTop + dyPercent;
const itemRect = selectedCanvasItem.getBoundingClientRect();
const itemWPercent = (itemRect.width / parentRect.width) * 100;
const itemHPercent = (itemRect.height / parentRect.height) * 100;
if (newLeft < 0) newLeft = 0;
if (newTop < 0) newTop = 0;
if (newLeft + itemWPercent > 100) newLeft = 100 - itemWPercent;
if (newTop + itemHPercent > 100) newTop = 100 - itemHPercent;
selectedCanvasItem.style.left = `${newLeft}%`;
selectedCanvasItem.style.top = `${newTop}%`;
}
function handleCanvasTouchDrag(e) {
if (!isDraggingCanvas || !selectedCanvasItem) return;
e.preventDefault();
const touch = e.touches[0];
const dx = touch.clientX - dragStartX;
const dy = touch.clientY - dragStartY;
const parentRect = cartazPrintableArea.getBoundingClientRect();
const dxPercent = (dx / parentRect.width) * 100;
const dyPercent = (dy / parentRect.height) * 100;
let newLeft = dragStartLeft + dxPercent;
let newTop = dragStartTop + dyPercent;
const itemRect = selectedCanvasItem.getBoundingClientRect();
const itemWPercent = (itemRect.width / parentRect.width) * 100;
const itemHPercent = (itemRect.height / parentRect.height) * 100;
if (newLeft < 0) newLeft = 0;
if (newTop < 0) newTop = 0;
if (newLeft + itemWPercent > 100) newLeft = 100 - itemWPercent;
if (newTop + itemHPercent > 100) newTop = 100 - itemHPercent;
selectedCanvasItem.style.left = `${newLeft}%`;
selectedCanvasItem.style.top = `${newTop}%`;
}
function stopCanvasDrag() {
isDraggingCanvas = false;
document.removeEventListener('mousemove', handleCanvasDrag);
document.removeEventListener('mouseup', stopCanvasDrag);
document.removeEventListener('touchmove', handleCanvasTouchDrag);
document.removeEventListener('touchend', stopCanvasDrag);
}
function handleCanvasResize(e) {
if (!isResizingCanvas || !selectedCanvasItem) return;
const dx = e.clientX - dragStartX;
const dy = e.clientY - dragStartY;
const parentRect = cartazPrintableArea.getBoundingClientRect();
const dxPercent = (dx / parentRect.width) * 100;
const dyPercent = (dy / parentRect.height) * 100;
let newWidth = dragStartWidth + dxPercent;
let newHeight = dragStartHeight + dyPercent;
if (newWidth < 10) newWidth = 10;
if (newHeight < 5) newHeight = 5;
const itemLeft = parseFloat(selectedCanvasItem.style.left) || 0;
const itemTop = parseFloat(selectedCanvasItem.style.top) || 0;
if (itemLeft + newWidth > 100) newWidth = 100 - itemLeft;
if (itemTop + newHeight > 100) newHeight = 100 - itemTop;
selectedCanvasItem.style.width = `${newWidth}%`;
selectedCanvasItem.style.height = `${newHeight}%`;
}
function handleCanvasTouchResize(e) {
if (!isResizingCanvas || !selectedCanvasItem) return;
e.preventDefault();
const touch = e.touches[0];
const dx = touch.clientX - dragStartX;
const dy = touch.clientY - dragStartY;
const parentRect = cartazPrintableArea.getBoundingClientRect();
const dxPercent = (dx / parentRect.width) * 100;
const dyPercent = (dy / parentRect.height) * 100;
let newWidth = dragStartWidth + dxPercent;
let newHeight = dragStartHeight + dyPercent;
if (newWidth < 10) newWidth = 10;
if (newHeight < 5) newHeight = 5;
const itemLeft = parseFloat(selectedCanvasItem.style.left) || 0;
const itemTop = parseFloat(selectedCanvasItem.style.top) || 0;
if (itemLeft + newWidth > 100) newWidth = 100 - itemLeft;
if (itemTop + newHeight > 100) newHeight = 100 - itemTop;
selectedCanvasItem.style.width = `${newWidth}%`;
selectedCanvasItem.style.height = `${newHeight}%`;
}
function stopCanvasResize() {
isResizingCanvas = false;
document.removeEventListener('mousemove', handleCanvasResize);
document.removeEventListener('mouseup', stopCanvasResize);
document.removeEventListener('touchmove', handleCanvasTouchResize);
document.removeEventListener('touchend', stopCanvasResize);
}
function rgbToHex(rgb) {
if (!rgb || rgb === 'transparent') return '#ffffff';
if (rgb.startsWith('#')) return rgb;
const match = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+(?:\.\d+)?))?\)$/);
if (!match) return '#ffffff';
const r = parseInt(match[1]);
const g = parseInt(match[2]);
const b = parseInt(match[3]);
return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
}
function updateToolbarForSelected() {
if (!selectedCanvasItem) return;
const ff = window.getComputedStyle(selectedCanvasItem).fontFamily.replace(/['"]/g, '').split(',')[0].trim();
if (canvasFontFamily) canvasFontFamily.value = ff;
const fs = parseFloat(window.getComputedStyle(selectedCanvasItem).fontSize);
if (canvasFontSize) canvasFontSize.value = Math.round(fs);
const col = rgbToHex(window.getComputedStyle(selectedCanvasItem).color);
if (canvasTextColor) canvasTextColor.value = col;
const bg = rgbToHex(window.getComputedStyle(selectedCanvasItem).backgroundColor);
if (canvasBgColorInput) canvasBgColorInput.value = bg;
}
if (canvasFontFamily) {
canvasFontFamily.addEventListener('change', () => {
if (selectedCanvasItem) selectedCanvasItem.style.fontFamily = canvasFontFamily.value;
});
}
if (canvasFontSize) {
canvasFontSize.addEventListener('input', () => {
if (selectedCanvasItem) selectedCanvasItem.style.fontSize = `${canvasFontSize.value}px`;
});
}
if (canvasTextColor) {
canvasTextColor.addEventListener('input', () => {
if (selectedCanvasItem) selectedCanvasItem.style.color = canvasTextColor.value;
});
}
if (canvasBgColorInput) {
canvasBgColorInput.addEventListener('input', () => {
if (selectedCanvasItem) selectedCanvasItem.style.backgroundColor = canvasBgColorInput.value;
});
}
if (btnCanvasZIndexUp) {
btnCanvasZIndexUp.addEventListener('click', () => {
if (selectedCanvasItem) {
const currentZ = parseInt(selectedCanvasItem.style.zIndex) || 1;
selectedCanvasItem.style.zIndex = currentZ + 1;
}
});
}
if (btnCanvasZIndexDown) {
btnCanvasZIndexDown.addEventListener('click', () => {
if (selectedCanvasItem) {
const currentZ = parseInt(selectedCanvasItem.style.zIndex) || 1;
selectedCanvasItem.style.zIndex = Math.max(1, currentZ - 1);
}
});
}
if (btnCanvasDelete) {
btnCanvasDelete.addEventListener('click', () => {
if (selectedCanvasItem) {
selectedCanvasItem.remove();
selectedCanvasItem = null;
}
});
}
if (btnCanvasAddText) {
btnCanvasAddText.addEventListener('click', () => {
if (!canvasModeActive) return;
const textItem = document.createElement('div');
textItem.className = 'canvas-item';
textItem.innerHTML = 'Novo Texto (Clique duplo para editar)';
textItem.style.left = '10%';
textItem.style.top = '15%';
textItem.style.width = '50%';
textItem.style.height = '8%';
textItem.style.fontSize = '20px';
textItem.style.color = cartazTextColor.value || '#2d3748';
textItem.style.fontFamily = cartazFontSelect.value || 'Fredoka';
textItem.setAttribute('contenteditable', 'true');
const handle = document.createElement('div');
handle.className = 'canvas-resize-handle';
textItem.appendChild(handle);
cartazPrintableArea.appendChild(textItem);
setupCanvasItemEvents(textItem);
textItem.click();
});
}
if (btnCanvasAddCard) {
btnCanvasAddCard.addEventListener('click', () => {
if (!canvasModeActive) return;
const cardItem = document.createElement('div');
cardItem.className = 'canvas-item';
cardItem.style.background = 'rgba(255, 255, 255, 0.4)';
cardItem.style.border = '2px dashed ' + (cartazTextColor.value || '#2d3748');
cardItem.style.borderRadius = '12px';
cardItem.style.left = '20%';
cardItem.style.top = '25%';
cardItem.style.width = '45%';
cardItem.style.height = '20%';
cardItem.style.padding = '15px';
cardItem.innerHTML = '<h3>Novo Card</h3><p>Edite este texto...</p>';
cardItem.style.fontFamily = cartazFontSelect.value || 'Fredoka';
cardItem.setAttribute('contenteditable', 'true');
const handle = document.createElement('div');
handle.className = 'canvas-resize-handle';
cardItem.appendChild(handle);
cartazPrintableArea.appendChild(cardItem);
setupCanvasItemEvents(cardItem);
cardItem.click();
});
}
if (btnCanvasModeToggle) {
btnCanvasModeToggle.addEventListener('click', () => {
if (canvasModeActive) {
exitCanvasMode();
} else {
if (cartazEditArea && cartazEditArea.style.display !== 'none') {
btnEditCartazToggle.click();
}
enterCanvasMode();
}
});
}
if (cartazPrintableArea) {
cartazPrintableArea.addEventListener('click', (e) => {
if (!canvasModeActive) return;
if (e.target === cartazPrintableArea) {
if (selectedCanvasItem) {
selectedCanvasItem.classList.remove('active-item');
selectedCanvasItem = null;
}
}
});
}
}); });
+38 -1
View File
@@ -1850,11 +1850,48 @@
<div style="display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--border-light); padding-bottom: 8px;"> <div style="display: flex; justify-content: space-between; align-items: center; border-bottom: 1px solid var(--border-light); padding-bottom: 8px;">
<h4 style="margin: 0; color: var(--text-primary);">👁️ Visualização do Cartaz</h4> <h4 style="margin: 0; color: var(--text-primary);">👁️ Visualização do Cartaz</h4>
<div style="display: flex; gap: 8px;"> <div style="display: flex; gap: 8px;">
<button id="btnEditCartazToggle" class="btn-save-settings" style="background: transparent; border: 1px solid var(--border-light); color: var(--text-secondary); padding: 5px 10px; font-size: 0.75rem;">✏️ Editar Conteúdo</button> <button id="btnCanvasModeToggle" class="btn-save-settings" style="background: transparent; border: 1px solid var(--border-light); color: var(--text-secondary); padding: 5px 10px; font-size: 0.75rem;">🎨 Design Canvas</button>
<button id="btnEditCartazToggle" class="btn-save-settings" style="background: transparent; border: 1px solid var(--border-light); color: var(--text-secondary); padding: 5px 10px; font-size: 0.75rem;">✏️ Editar HTML</button>
<button id="btnPrintCartaz" class="btn-save-settings" style="background: #3b82f6; border: none; color: white; padding: 5px 12px; font-size: 0.75rem; font-weight: bold; border-radius: 6px;">🖨️ Imprimir Cartaz</button> <button id="btnPrintCartaz" class="btn-save-settings" style="background: #3b82f6; border: none; color: white; padding: 5px 12px; font-size: 0.75rem; font-weight: bold; border-radius: 6px;">🖨️ Imprimir Cartaz</button>
</div> </div>
</div> </div>
<!-- Painel de Controle do Canvas (Apenas visível no Modo Canvas) -->
<div id="canvasControlPanel" style="display: none; background: var(--bg-secondary); border: 1px solid var(--border-light); padding: 10px; border-radius: 8px; gap: 10px; align-items: center; flex-wrap: wrap; margin-bottom: 8px;">
<button id="btnCanvasAddText" class="btn-save-settings" style="background: #10a37f; color: white; border: none; padding: 4px 10px; font-size: 0.75rem; font-weight: 600; border-radius: 6px; cursor: pointer;"> Texto</button>
<button id="btnCanvasAddCard" class="btn-save-settings" style="background: #a855f7; color: white; border: none; padding: 4px 10px; font-size: 0.75rem; font-weight: 600; border-radius: 6px; cursor: pointer;"> Card</button>
<div style="height: 20px; width: 1px; background: var(--border-light);"></div>
<!-- Controles do Item Selecionado -->
<span style="font-size: 0.75rem; color: var(--text-secondary);">Item:</span>
<select id="canvasFontFamily" class="obs-select" style="padding: 2px 5px; font-size: 0.75rem; min-width: 90px; margin: 0;">
<option value="Fredoka">Fredoka</option>
<option value="Outfit">Outfit</option>
<option value="Caveat">Caveat</option>
<option value="Playfair Display">Playfair</option>
<option value="Arial">Arial</option>
</select>
<input type="number" id="canvasFontSize" class="obs-input" style="width: 55px; padding: 2px 5px; font-size: 0.75rem; margin: 0;" min="8" max="72" value="16" title="Tamanho da fonte (px)">
<div style="display: flex; align-items: center; gap: 4px;">
<label style="font-size: 0.72rem; color: var(--text-secondary);">Cor:</label>
<input type="color" id="canvasTextColor" style="width: 24px; height: 24px; border: 1px solid var(--border-light); border-radius: 4px; padding: 0; cursor: pointer; background: transparent; margin: 0;">
</div>
<div style="display: flex; align-items: center; gap: 4px;">
<label style="font-size: 0.72rem; color: var(--text-secondary);">Fundo:</label>
<input type="color" id="canvasBgColor" style="width: 24px; height: 24px; border: 1px solid var(--border-light); border-radius: 4px; padding: 0; cursor: pointer; background: transparent; margin: 0;">
</div>
<div style="display: flex; gap: 4px; align-items: center;">
<button id="btnCanvasZIndexUp" class="btn-save-settings" style="background: transparent; border: 1px solid var(--border-light); color: var(--text-secondary); padding: 2px 6px; font-size: 0.7rem; cursor: pointer;" title="Trazer para Frente">🔺</button>
<button id="btnCanvasZIndexDown" class="btn-save-settings" style="background: transparent; border: 1px solid var(--border-light); color: var(--text-secondary); padding: 2px 6px; font-size: 0.7rem; cursor: pointer;" title="Enviar para Trás">🔻</button>
<button id="btnCanvasDelete" class="btn-save-settings" style="background: #ef4444; color: white; border: none; padding: 2px 8px; font-size: 0.7rem; font-weight: bold; border-radius: 4px; cursor: pointer;" title="Excluir Elemento">🗑️ Excluir</button>
</div>
</div>
<!-- Área de Edição do Conteúdo (Inicialmente Oculta) --> <!-- Área de Edição do Conteúdo (Inicialmente Oculta) -->
<div id="cartazEditArea" style="display: none; flex-direction: column; gap: 8px;"> <div id="cartazEditArea" style="display: none; flex-direction: column; gap: 8px;">
<label style="color: var(--text-secondary); font-size: 0.78rem; font-weight: 600; text-transform: uppercase;">Editor HTML do Cartaz</label> <label style="color: var(--text-secondary); font-size: 0.78rem; font-weight: 600; text-transform: uppercase;">Editor HTML do Cartaz</label>
+54
View File
@@ -3685,6 +3685,60 @@ code {
max-height: 100% !important; max-height: 100% !important;
} }
/* Estilos de Itens do Canvas (Arrastáveis e Redimensionáveis) */
.canvas-item {
position: absolute !important;
box-sizing: border-box;
cursor: move;
border: 1px dashed rgba(59, 130, 246, 0.4);
padding: 10px;
background: rgba(255, 255, 255, 0.3);
border-radius: 8px;
user-select: text; /* Permite selecionar texto interno para edição */
}
.canvas-item:hover {
border-color: rgba(59, 130, 246, 0.8);
box-shadow: 0 0 8px rgba(59, 130, 246, 0.2);
}
.canvas-item.active-item {
border: 2.5px solid #3b82f6 !important;
box-shadow: 0 0 12px rgba(59, 130, 246, 0.4);
z-index: 1000;
}
/* Alça de redimensionamento do card */
.canvas-resize-handle {
position: absolute;
width: 14px;
height: 14px;
background: #3b82f6;
border: 2px solid white;
border-radius: 50%;
bottom: -7px;
right: -7px;
cursor: se-resize;
z-index: 10;
display: none;
}
.canvas-item.active-item .canvas-resize-handle {
display: block;
}
/* Oculte alças e tracejados na impressão e exportação */
@media print {
.canvas-resize-handle {
display: none !important;
}
.canvas-item {
border: none !important;
box-shadow: none !important;
cursor: default !important;
}
}