top of page
Buscar

Galeria paisajes 3D Carrito de compras


<!DOCTYPE html>

<html lang="es">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Galería de Paisajes 3D</title>

<style>

* {

margin: 0;

padding: 0;

box-sizing: border-box;

}

body {

font-family: 'Arial', sans-serif;

background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);

color: white;

min-height: 100vh;

}

.container {

max-width: 1200px;

margin: 0 auto;

padding: 20px;

}

.header {

text-align: center;

margin-bottom: 40px;

}

.header h1 {

font-size: 3rem;

margin-bottom: 10px;

background: linear-gradient(45deg, #FFD700, #FF69B4);

-webkit-background-clip: text;

-webkit-text-fill-color: transparent;

background-clip: text;

}

.gallery {

display: grid;

grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));

gap: 30px;

margin-bottom: 40px;

}

.artwork-card {

background: rgba(0, 0, 0, 0.3);

border-radius: 20px;

padding: 20px;

backdrop-filter: blur(10px);

border: 1px solid rgba(255, 255, 255, 0.1);

transition: transform 0.3s ease;

}

.artwork-card:hover {

transform: translateY(-5px);

}

.canvas-container {

width: 100%;

height: 250px;

border-radius: 15px;

overflow: hidden;

margin-bottom: 15px;

background: #000;

}

.artwork-info h3 {

font-size: 1.5rem;

margin-bottom: 10px;

color: #FFD700;

}

.artwork-info p {

color: #B0C4DE;

margin-bottom: 15px;

}

.price {

font-size: 1.5rem;

font-weight: bold;

color: #00FF7F;

margin-bottom: 15px;

}

.btn {

padding: 12px 24px;

border: none;

border-radius: 10px;

font-weight: bold;

cursor: pointer;

transition: all 0.3s ease;

margin: 5px;

}

.btn-buy {

background: linear-gradient(45deg, #FF6B6B, #4ECDC4);

color: white;

}

.btn-buy:hover {

transform: scale(1.05);

box-shadow: 0 5px 15px rgba(255, 107, 107, 0.4);

}

.btn-download {

background: linear-gradient(45deg, #32CD32, #228B22);

color: white;

}

.btn-download:hover {

transform: scale(1.05);

box-shadow: 0 5px 15px rgba(50, 205, 50, 0.4);

}

.cart-sidebar {

position: fixed;

right: 20px;

top: 20px;

width: 300px;

background: rgba(0, 0, 0, 0.5);

backdrop-filter: blur(15px);

border-radius: 20px;

padding: 20px;

border: 1px solid rgba(255, 255, 255, 0.2);

z-index: 1000;

}

.cart-header {

display: flex;

align-items: center;

gap: 10px;

margin-bottom: 15px;

}

.cart-item {

background: rgba(255, 255, 255, 0.1);

padding: 10px;

border-radius: 10px;

margin-bottom: 10px;

display: flex;

justify-content: space-between;

align-items: center;

}

.cart-total {

border-top: 2px solid #FFD700;

padding-top: 15px;

margin-top: 15px;

font-size: 1.2rem;

font-weight: bold;

}

.hit-counter {

text-align: center;

background: rgba(0, 255, 127, 0.2);

padding: 15px;

border-radius: 15px;

margin-top: 20px;

}

.hit-counter .count {

font-size: 2rem;

font-weight: bold;

color: #00FF7F;

}

.thanks-message {

position: fixed;

top: 50%;

left: 50%;

transform: translate(-50%, -50%);

background: linear-gradient(45deg, #00FF7F, #32CD32);

color: white;

padding: 30px;

border-radius: 20px;

text-align: center;

font-size: 1.5rem;

font-weight: bold;

z-index: 2000;

animation: fadeInOut 3s ease-in-out;

}

@keyframes fadeInOut {

0%, 100% { opacity: 0; transform: translate(-50%, -50%) scale(0.8); }

50% { opacity: 1; transform: translate(-50%, -50%) scale(1); }

}

.hidden {

display: none;

}

</style>

</head>

<body>

<div class="container">

<header class="header">

<h1>🎨 Galería de Paisajes 3D</h1>

<p>Arte digital generativo único - Colección exclusiva</p>

</header>

<div class="gallery" id="gallery"></div>

</div>

<!-- Carrito lateral -->

<div class="cart-sidebar">

<div class="cart-header">

<span style="font-size: 1.5rem;">🛒</span>

<h3>Carrito (<span id="cart-count">0</span>)</h3>

</div>

<div id="cart-items"></div>

<div class="cart-total">

Total: $<span id="cart-total">0</span> COP

</div>

<div class="hit-counter">

<div>💎 Hit Counter</div>

<div class="count" id="hit-count">0</div>

<div style="font-size: 0.8rem;">Compras realizadas</div>

</div>

</div>

<!-- Mensaje de agradecimiento -->

<div id="thanks-message" class="thanks-message hidden">

<div>¡Gracias por tu donación! 🎉</div>

<div style="font-size: 1rem; margin-top: 10px;">Tu compra apoya el arte digital</div>

</div>


<script>

// Estado global

let cart = [];

let hitCount = 0;

let renderers = [];

const artworks = [

{

id: 1,

name: "Amanecer Dorado",

price: 45000,

description: "Hermoso paisaje con sol naciente entre montañas",

scene: 'sunrise'

},

{

id: 2,

name: "Noche Serena",

price: 52000,

description: "Paisaje nocturno con luna llena y montañas silenciosas",

scene: 'moonlight'

},

{

id: 3,

name: "Atardecer Místico",

price: 48000,

description: "Montañas al atardecer con colores cálidos",

scene: 'sunset'

},

{

id: 4,

name: "Valle Esmeralda",

price: 55000,

description: "Valle verde con río y montañas azules",

scene: 'valley'

}

];


// Funciones para crear escenas

function createSunriseScene(scene) {

// Cielo degradado

const skyGeometry = new THREE.SphereGeometry(50, 32, 32);

const skyMaterial = new THREE.MeshBasicMaterial({

color: 0x87CEEB,

side: THREE.BackSide

});

const sky = new THREE.Mesh(skyGeometry, skyMaterial);

scene.add(sky);


// Sol

const sunGeometry = new THREE.SphereGeometry(2, 16, 16);

const sunMaterial = new THREE.MeshBasicMaterial({

color: 0xFFD700,

emissive: 0xFFA500,

emissiveIntensity: 0.5

});

const sun = new THREE.Mesh(sunGeometry, sunMaterial);

sun.position.set(15, 10, -20);

scene.add(sun);


// Montañas

for (let i = 0; i < 4; i++) {

const mountainGeometry = new THREE.ConeGeometry(4 + Math.random() * 2, 8 + Math.random() * 4, 8);

const mountainMaterial = new THREE.MeshLambertMaterial({

color: new THREE.Color().setHSL(0.25, 0.3, 0.3 + Math.random() * 0.2)

});

const mountain = new THREE.Mesh(mountainGeometry, mountainMaterial);

mountain.position.set((i - 2) * 8, 0, -15 - Math.random() * 5);

scene.add(mountain);

}


// Luces

const ambientLight = new THREE.AmbientLight(0x404040, 0.6);

scene.add(ambientLight);

const directionalLight = new THREE.DirectionalLight(0xFFE4B5, 0.8);

directionalLight.position.copy(sun.position);

scene.add(directionalLight);

}


function createMoonlightScene(scene) {

// Cielo nocturno

const skyGeometry = new THREE.SphereGeometry(50, 32, 32);

const skyMaterial = new THREE.MeshBasicMaterial({

color: 0x0B1426,

side: THREE.BackSide

});

const sky = new THREE.Mesh(skyGeometry, skyMaterial);

scene.add(sky);


// Luna

const moonGeometry = new THREE.SphereGeometry(1.5, 16, 16);

const moonMaterial = new THREE.MeshBasicMaterial({

color: 0xF5F5DC,

emissive: 0xF5F5DC,

emissiveIntensity: 0.3

});

const moon = new THREE.Mesh(moonGeometry, moonMaterial);

moon.position.set(-10, 15, -20);

scene.add(moon);


// Estrellas

for (let i = 0; i < 50; i++) {

const starGeometry = new THREE.SphereGeometry(0.05, 4, 4);

const starMaterial = new THREE.MeshBasicMaterial({ color: 0xFFFFFF });

const star = new THREE.Mesh(starGeometry, starMaterial);

star.position.set(

(Math.random() - 0.5) * 100,

Math.random() * 30 + 5,

(Math.random() - 0.5) * 100

);

scene.add(star);

}


// Montañas nocturnas

for (let i = 0; i < 3; i++) {

const mountainGeometry = new THREE.ConeGeometry(5 + Math.random() * 3, 10 + Math.random() * 5, 8);

const mountainMaterial = new THREE.MeshLambertMaterial({ color: 0x1a1a2e });

const mountain = new THREE.Mesh(mountainGeometry, mountainMaterial);

mountain.position.set((i - 1) * 12, 0, -18 - Math.random() * 8);

scene.add(mountain);

}


const ambientLight = new THREE.AmbientLight(0x404080, 0.4);

scene.add(ambientLight);

const moonLight = new THREE.DirectionalLight(0xF5F5DC, 0.5);

moonLight.position.copy(moon.position);

scene.add(moonLight);

}


function createSunsetScene(scene) {

// Cielo atardecer

const skyGeometry = new THREE.SphereGeometry(50, 32, 32);

const skyMaterial = new THREE.MeshBasicMaterial({

color: 0xFF6347,

side: THREE.BackSide

});

const sky = new THREE.Mesh(skyGeometry, skyMaterial);

scene.add(sky);


// Sol atardecer

const sunGeometry = new THREE.SphereGeometry(2.5, 16, 16);

const sunMaterial = new THREE.MeshBasicMaterial({

color: 0xFF4500,

emissive: 0xFF6347,

emissiveIntensity: 0.6

});

const sun = new THREE.Mesh(sunGeometry, sunMaterial);

sun.position.set(-18, 6, -25);

scene.add(sun);


// Montañas silueta

for (let i = 0; i < 5; i++) {

const mountainGeometry = new THREE.ConeGeometry(3 + Math.random() * 3, 6 + Math.random() * 6, 6);

const mountainMaterial = new THREE.MeshBasicMaterial({ color: 0x2F1B69 });

const mountain = new THREE.Mesh(mountainGeometry, mountainMaterial);

mountain.position.set((i - 2) * 8, 0, -15 - Math.random() * 10);

scene.add(mountain);

}


const ambientLight = new THREE.AmbientLight(0x8B4513, 0.5);

scene.add(ambientLight);

}


function createValleyScene(scene) {

// Cielo día

const skyGeometry = new THREE.SphereGeometry(50, 32, 32);

const skyMaterial = new THREE.MeshBasicMaterial({

color: 0x87CEEB,

side: THREE.BackSide

});

const sky = new THREE.Mesh(skyGeometry, skyMaterial);

scene.add(sky);


// Sol

const sunGeometry = new THREE.SphereGeometry(1.8, 16, 16);

const sunMaterial = new THREE.MeshBasicMaterial({

color: 0xFFFF00,

emissive: 0xFFFF00,

emissiveIntensity: 0.4

});

const sun = new THREE.Mesh(sunGeometry, sunMaterial);

sun.position.set(0, 18, -30);

scene.add(sun);


// Montañas verdes

for (let i = 0; i < 6; i++) {

const mountainGeometry = new THREE.ConeGeometry(4 + Math.random() * 3, 9 + Math.random() * 4, 8);

const mountainMaterial = new THREE.MeshLambertMaterial({

color: new THREE.Color().setHSL(0.25, 0.7, 0.4 + Math.random() * 0.2)

});

const mountain = new THREE.Mesh(mountainGeometry, mountainMaterial);

mountain.position.set((i - 2.5) * 8, 0, -18 - Math.random() * 8);

scene.add(mountain);

}


// Río

const riverGeometry = new THREE.PlaneGeometry(60, 3);

const riverMaterial = new THREE.MeshLambertMaterial({

color: 0x4169E1,

transparent: true,

opacity: 0.7

});

const river = new THREE.Mesh(riverGeometry, riverMaterial);

river.rotation.x = -Math.PI / 2;

river.position.y = -3;

scene.add(river);


const ambientLight = new THREE.AmbientLight(0x404040, 0.7);

scene.add(ambientLight);

const sunLight = new THREE.DirectionalLight(0xFFFFFF, 0.8);

sunLight.position.copy(sun.position);

scene.add(sunLight);

}


function createArtworkCanvas(artwork, container) {

const scene = new THREE.Scene();

const camera = new THREE.PerspectiveCamera(75, container.offsetWidth / container.offsetHeight, 0.1, 1000);

const renderer = new THREE.WebGLRenderer({ antialias: true, preserveDrawingBuffer: true });

renderer.setSize(container.offsetWidth, container.offsetHeight);

renderer.setClearColor(0x000000);

container.appendChild(renderer.domElement);


camera.position.set(0, 8, 20);

camera.lookAt(0, 0, 0);


// Crear escena según el tipo

switch (artwork.scene) {

case 'sunrise':

createSunriseScene(scene);

break;

case 'moonlight':

createMoonlightScene(scene);

break;

case 'sunset':

createSunsetScene(scene);

break;

case 'valley':

createValleyScene(scene);

break;

}


// Animación

function animate() {

requestAnimationFrame(animate);

camera.position.x = Math.sin(Date.now() * 0.0003) * 1.5;

renderer.render(scene, camera);

}

animate();


return { renderer, scene, camera };

}


function addToCart(artwork) {

cart.push(artwork);

hitCount++;

updateCartDisplay();

updateHitCounter();

showThanksMessage();

}


function updateCartDisplay() {

const cartItems = document.getElementById('cart-items');

const cartCount = document.getElementById('cart-count');

const cartTotal = document.getElementById('cart-total');

cartItems.innerHTML = '';

if (cart.length === 0) {

cartItems.innerHTML = '<div style="color: #888; text-align: center;">Carrito vacío</div>';

} else {

cart.forEach((item, index) => {

const cartItem = document.createElement('div');

cartItem.className = 'cart-item';

cartItem.innerHTML = `

<div>

<div style="font-weight: bold; font-size: 0.9rem;">${item.name}</div>

<div style="color: #FFD700;">$${item.price.toLocaleString('es-CO')}</div>

</div>

<button onclick="removeFromCart(${index})" style="background: #FF4444; color: white; border: none; border-radius: 5px; padding: 5px; cursor: pointer;">✕</button>

`;

cartItems.appendChild(cartItem);

});

}

cartCount.textContent = cart.length;

cartTotal.textContent = cart.reduce((total, item) => total + item.price, 0).toLocaleString('es-CO');

}


function removeFromCart(index) {

cart.splice(index, 1);

updateCartDisplay();

}


function updateHitCounter() {

document.getElementById('hit-count').textContent = hitCount;

}


function showThanksMessage() {

const thanksMsg = document.getElementById('thanks-message');

thanksMsg.classList.remove('hidden');

setTimeout(() => {

thanksMsg.classList.add('hidden');

}, 3000);

}


function exportImage(artworkId) {

const renderer = renderers[artworkId - 1];

if (renderer) {

const canvas = renderer.domElement;

const link = document.createElement('a');

const artwork = artworks.find(art => art.id === artworkId);

link.download = `${artwork.name.replace(/\s+/g, '_')}.png`;

link.href = canvas.toDataURL('image/png');

link.click();

}

}


function createGallery() {

const gallery = document.getElementById('gallery');

artworks.forEach((artwork) => {

const card = document.createElement('div');

card.className = 'artwork-card';

card.innerHTML = `

<div class="canvas-container" id="canvas-${artwork.id}"></div>

<div class="artwork-info">

<h3>${artwork.name}</h3>

<p>${artwork.description}</p>

<div class="price">$${artwork.price.toLocaleString('es-CO')} COP</div>

<div>

<button class="btn btn-buy" onclick="addToCart(${JSON.stringify(artwork).replace(/"/g, '&quot;')})">

🛒 Comprar Ahora

</button>

<button class="btn btn-download" onclick="exportImage(${artwork.id})">

📥 Descargar PNG

</button>

</div>

</div>

`;

gallery.appendChild(card);

// Crear canvas 3D para esta obra

const container = document.getElementById(`canvas-${artwork.id}`);

const { renderer } = createArtworkCanvas(artwork, container);

renderers.push(renderer);

});

}


// Inicializar la galería cuando se carga la página

window.addEventListener('load', () => {

createGallery();

updateCartDisplay();

updateHitCounter();

});


// Manejar redimensionamiento

window.addEventListener('resize', () => {

// Actualizar tamaños de canvas si es necesario

renderers.forEach((renderer, index) => {

const container = document.getElementById(`canvas-${index + 1}`);

if (container && renderer) {

renderer.setSize(container.offsetWidth, container.offsetHeight);

}

});

});

</script>

</body>

</html>



















ree

 
 
 

Comentarios


bottom of page