3raya / index.html
josejuan314's picture
en m贸vil no se ven las im谩genes que se mueven - Follow Up Deployment
3dc5290 verified
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Im谩genes Interactivas</title>
<script src="https://cdn.tailwindcss.com"></script>
<style>
.draggable {
position: absolute;
cursor: grab;
touch-action: none;
user-select: none;
transition: transform 0.1s ease;
}
.draggable:active {
cursor: grabbing;
transform: scale(1.05);
z-index: 10;
}
@media (hover: none) {
.draggable {
touch-action: manipulation;
}
.draggable:active {
transform: scale(1.1);
}
}
#background-container {
position: relative;
width: 100%;
overflow: hidden;
}
#background-img {
width: 100%;
height: auto;
display: block;
}
#draggables-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
@media (max-width: 640px) {
.draggable {
width: 30% !important;
min-width: 100px;
}
#background-container {
min-height: 300px;
}
}
</style>
</head>
<body class="bg-gray-100">
<div class="container mx-auto px-4 py-8">
<h1 class="text-4xl font-bold text-center mb-8 text-indigo-700">Crea tu composici贸n</h1>
<p class="text-center mb-8 text-gray-600 max-w-2xl mx-auto">
Arrastra las im谩genes sobre el fondo para crear tu dise帽o personalizado.
Puedes moverlas con el rat贸n en desktop o con el dedo en m贸viles.
</p>
<div class="bg-white rounded-xl shadow-xl overflow-hidden mb-8">
<div id="background-container" class="relative">
<img id="background-img" src="https://www.solonoticias.news/i/fondo.png" alt="Fondo" class="w-full">
<div id="draggables-container"></div>
</div>
</div>
<div class="flex flex-col items-center space-y-4 mb-8">
<div class="flex space-x-4">
<button id="reset-btn" class="px-6 py-3 bg-red-500 text-white rounded-lg hover:bg-red-600 transition">
Reiniciar Posiciones
</button>
<button id="random-btn" class="px-6 py-3 bg-purple-500 text-white rounded-lg hover:bg-purple-600 transition">
Posici贸n Aleatoria
</button>
</div>
<div class="w-64">
<label for="size-slider" class="block text-sm font-medium text-gray-700 mb-1">Tama帽o de im谩genes</label>
<input type="range" id="size-slider" min="10" max="100" value="100" class="w-full h-2 bg-gray-200 rounded-lg appearance-none cursor-pointer">
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const backgroundImg = document.getElementById('background-img');
const draggablesContainer = document.getElementById('draggables-container');
const resetBtn = document.getElementById('reset-btn');
const randomBtn = document.getElementById('random-btn');
// Image paths with custom base sizes (width, height)
const imagePaths = [
{ path: 'bailadora.png', originalWidth: 600, originalHeight: 1000 },
{ path: 'botella.png', originalWidth: 400, originalHeight: 900 },
{ path: 'copas.png', originalWidth: 750, originalHeight: 750 },
{ path: 'hombre.png', originalWidth: 750, originalHeight: 1000 },
{ path: 'litro.png', originalWidth: 600, originalHeight: 600 },
{ path: 'toro.png', originalWidth: 900, originalHeight: 600 }
];
// Base URL for images
const baseUrl = 'https://www.solonoticias.news/i/';
// Store original positions
const originalPositions = [];
let scaleFactor = 1;
// Global scale for draggable images
let globalScale = 1;
// Update all draggable sizes proportionally
function updateDraggableSizes() {
const draggables = document.querySelectorAll('.draggable');
draggables.forEach((draggable, index) => {
const originalPos = originalPositions[index];
const newWidth = originalPos.width * scaleFactor * globalScale;
const newHeight = originalPos.height * scaleFactor * globalScale;
draggable.style.width = `${newWidth}px`;
draggable.style.height = `${newHeight}px`;
// Adjust position to prevent going out of bounds
const maxX = backgroundImg.width - newWidth;
const maxY = backgroundImg.height - newHeight;
const currentLeft = parseFloat(draggable.style.left);
const currentTop = parseFloat(draggable.style.top);
draggable.style.left = `${Math.max(0, Math.min(maxX, currentLeft))}px`;
draggable.style.top = `${Math.max(0, Math.min(maxY, currentTop))}px`;
});
}
// Initialize the app
function init() {
// Calculate scale factor based on background image dimensions
backgroundImg.onload = function() {
const originalWidth = this.naturalWidth;
const displayedWidth = this.width;
scaleFactor = displayedWidth / originalWidth;
// Create draggable images
createDraggableImages();
};
// Handle window resize
window.addEventListener('resize', function() {
// Recalculate scale factor
const originalWidth = backgroundImg.naturalWidth;
const displayedWidth = backgroundImg.width;
scaleFactor = displayedWidth / originalWidth;
// Update all draggable positions
const draggables = document.querySelectorAll('.draggable');
draggables.forEach((draggable, index) => {
const originalPos = originalPositions[index];
draggable.style.left = `${originalPos.x * scaleFactor}px`;
draggable.style.top = `${originalPos.y * scaleFactor}px`;
draggable.style.width = `${originalPos.width * scaleFactor}px`;
});
});
}
// Create draggable images
function createDraggableImages() {
// Clear container
draggablesContainer.innerHTML = '';
originalPositions.length = 0;
// Create each draggable image
imagePaths.forEach((imgPath, index) => {
const img = document.createElement('img');
img.src = baseUrl + imgPath.path;
img.alt = imgPath.path.split('.')[0];
img.className = 'draggable';
// Set initial size (scaled down from original dimensions)
const width = imgPath.originalWidth * scaleFactor * globalScale;
const height = imgPath.originalHeight * scaleFactor * globalScale;
// Set random initial position within bounds
const maxX = backgroundImg.width - width;
const maxY = backgroundImg.height - height;
const x = Math.random() * maxX;
const y = Math.random() * maxY;
img.style.width = `${width}px`;
img.style.height = `${height}px`;
img.style.left = `${x}px`;
img.style.top = `${y}px`;
// Store original position (in original image coordinates)
originalPositions.push({
x: x / scaleFactor,
y: y / scaleFactor,
width: imgPath.originalWidth,
height: imgPath.originalHeight
});
// Make draggable and add double-click handler
makeDraggable(img);
img.addEventListener('dblclick', function() {
duplicateImage(img);
});
// Add to container
draggablesContainer.appendChild(img);
});
}
// Duplicate an image
function duplicateImage(originalImg) {
const img = document.createElement('img');
img.src = originalImg.src;
img.alt = originalImg.alt;
img.className = 'draggable';
// Copy dimensions
img.style.width = originalImg.style.width;
img.style.height = originalImg.style.height;
// Position slightly offset from original
const originalLeft = parseFloat(originalImg.style.left);
const originalTop = parseFloat(originalImg.style.top);
img.style.left = `${originalLeft + 20}px`;
img.style.top = `${originalTop + 20}px`;
// Make draggable and add double-click/tap handlers
makeDraggable(img);
img.addEventListener('dblclick', function() {
duplicateImage(img);
});
// Add to container
draggablesContainer.appendChild(img);
// Store original position (in original image coordinates)
const originalIndex = Array.from(document.querySelectorAll('.draggable')).indexOf(originalImg);
const originalPos = originalPositions[originalIndex];
originalPositions.push({
x: (originalLeft + 20) / scaleFactor,
y: (originalTop + 20) / scaleFactor,
width: originalPos.width,
height: originalPos.height
});
}
// Make an element draggable
function makeDraggable(element) {
let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
// Mouse events
element.onmousedown = dragMouseDown;
// Touch events
let lastTouchTime = 0;
element.addEventListener('touchstart', function(e) {
const currentTime = new Date().getTime();
if (currentTime - lastTouchTime < 300) {
// Double tap detected
duplicateImage(element);
e.preventDefault();
}
lastTouchTime = currentTime;
dragTouchStart(e);
}, { passive: false });
function dragMouseDown(e) {
e = e || window.event;
e.preventDefault();
// Get the mouse cursor position at startup
pos3 = e.clientX;
pos4 = e.clientY;
document.onmouseup = closeDragElement;
document.onmousemove = elementDrag;
}
function dragTouchStart(e) {
e.preventDefault();
const touch = e.touches[0];
// Get the touch position at startup
pos3 = touch.clientX;
pos4 = touch.clientY;
document.ontouchend = closeDragElement;
document.ontouchmove = elementDragTouch;
}
function elementDrag(e) {
e = e || window.event;
e.preventDefault();
// Calculate the new cursor position
pos1 = pos3 - e.clientX;
pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
// Set the element's new position
const newTop = element.offsetTop - pos2;
const newLeft = element.offsetLeft - pos1;
// Constrain to container bounds
const maxTop = draggablesContainer.offsetHeight - element.offsetHeight;
const maxLeft = draggablesContainer.offsetWidth - element.offsetWidth;
element.style.top = `${Math.max(0, Math.min(maxTop, newTop))}px`;
element.style.left = `${Math.max(0, Math.min(maxLeft, newLeft))}px`;
}
function elementDragTouch(e) {
e.preventDefault();
const touch = e.touches[0];
// Calculate the new touch position
pos1 = pos3 - touch.clientX;
pos2 = pos4 - touch.clientY;
pos3 = touch.clientX;
pos4 = touch.clientY;
// Set the element's new position
const newTop = element.offsetTop - pos2;
const newLeft = element.offsetLeft - pos1;
// Constrain to container bounds
const maxTop = draggablesContainer.offsetHeight - element.offsetHeight;
const maxLeft = draggablesContainer.offsetWidth - element.offsetWidth;
element.style.top = `${Math.max(0, Math.min(maxTop, newTop))}px`;
element.style.left = `${Math.max(0, Math.min(maxLeft, newLeft))}px`;
}
function closeDragElement() {
// Stop moving when mouse/touch is released
document.onmouseup = null;
document.onmousemove = null;
document.ontouchend = null;
document.ontouchmove = null;
}
}
// Reset positions
resetBtn.addEventListener('click', function() {
const draggables = document.querySelectorAll('.draggable');
draggables.forEach((draggable, index) => {
const originalPos = originalPositions[index];
draggable.style.left = `${originalPos.x * scaleFactor}px`;
draggable.style.top = `${originalPos.y * scaleFactor}px`;
});
});
// Random positions
randomBtn.addEventListener('click', function() {
const draggables = document.querySelectorAll('.draggable');
draggables.forEach(draggable => {
const maxX = backgroundImg.width - draggable.offsetWidth;
const maxY = backgroundImg.height - draggable.offsetHeight;
const x = Math.random() * maxX;
const y = Math.random() * maxY;
draggable.style.left = `${x}px`;
draggable.style.top = `${y}px`;
});
});
// Size slider control
document.getElementById('size-slider').addEventListener('input', function(e) {
globalScale = e.target.value / 100;
updateDraggableSizes();
});
// Start the app
init();
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 馃К <a href="https://enzostvs-deepsite.hf.space?remix=josejuan314/3raya" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>