prevented body scroll when modal shows viewport units and mobile responsive fixes overflow hidden on body/html when match popup active mobile media queries for smaller screens terry davis would be proud of this viewport handling
364 lines
11 KiB
JavaScript
364 lines
11 KiB
JavaScript
// Brick data - loaded from Pexels API downloads
|
|
const bricks = [
|
|
{
|
|
id: 1,
|
|
name: "Old Brick Wall",
|
|
image: "images/brick_01.jpg",
|
|
description: "A moody close-up of an old brick wall with character.",
|
|
color: "Brown",
|
|
texture: "Weathered"
|
|
},
|
|
{
|
|
id: 2,
|
|
name: "Dark Brick Wall",
|
|
image: "images/brick_02.jpg",
|
|
description: "Close-up texture of a dark, rough brick wall.",
|
|
color: "Dark Brown",
|
|
texture: "Rough"
|
|
},
|
|
{
|
|
id: 3,
|
|
name: "White Brick Wall",
|
|
image: "images/brick_03.jpg",
|
|
description: "A minimalist white brick wall casting shadows.",
|
|
color: "White",
|
|
texture: "Smooth"
|
|
},
|
|
{
|
|
id: 4,
|
|
name: "Red Brick Building",
|
|
image: "images/brick_04.jpg",
|
|
description: "Red-brick modern building against a vibrant blue sky.",
|
|
color: "Red",
|
|
texture: "Modern"
|
|
},
|
|
{
|
|
id: 5,
|
|
name: "Weathered Red Brick",
|
|
image: "images/brick_05.jpg",
|
|
description: "A detailed view of a weathered red brick wall.",
|
|
color: "Red",
|
|
texture: "Weathered"
|
|
},
|
|
{
|
|
id: 6,
|
|
name: "Ancient Brick Archway",
|
|
image: "images/brick_06.jpg",
|
|
description: "The timeless beauty of an ancient brick archway.",
|
|
color: "Brown",
|
|
texture: "Aged"
|
|
},
|
|
{
|
|
id: 7,
|
|
name: "Vintage Brick Door",
|
|
image: "images/brick_07.jpg",
|
|
description: "A vintage wooden door set in historic brickwork.",
|
|
color: "Brown",
|
|
texture: "Vintage"
|
|
},
|
|
{
|
|
id: 8,
|
|
name: "Brick Archway",
|
|
image: "images/brick_08.jpg",
|
|
description: "Captivating brick archway showcasing architectural beauty.",
|
|
color: "Brown",
|
|
texture: "Textured"
|
|
},
|
|
{
|
|
id: 9,
|
|
name: "Ancient Stone Masonry",
|
|
image: "images/brick_09.jpg",
|
|
description: "Explore the timeless beauty of ancient stone masonry with a view through a historic window in ruins.",
|
|
color: "Brown",
|
|
texture: "Ancient"
|
|
},
|
|
{
|
|
id: 10,
|
|
name: "Pink Brick Wall",
|
|
image: "images/brick_10.jpg",
|
|
description: "Light pink textured brick wall corner perfect for backgrounds and design.",
|
|
color: "Pink",
|
|
texture: "Textured"
|
|
},
|
|
{
|
|
id: 11,
|
|
name: "Urban Brick Alley",
|
|
image: "images/brick_11.jpg",
|
|
description: "Explore the character of a narrow urban alley lined with rustic brick walls and faded graffiti.",
|
|
color: "Brown",
|
|
texture: "Rustic"
|
|
},
|
|
{
|
|
id: 12,
|
|
name: "Red Brick Wall",
|
|
image: "images/brick_12.jpg",
|
|
description: "High-resolution image of a red brick wall with white mortar lines, perfect for backgrounds.",
|
|
color: "Red",
|
|
texture: "Classic"
|
|
},
|
|
{
|
|
id: 13,
|
|
name: "Aged Brick Window",
|
|
image: "images/brick_13.jpg",
|
|
description: "A cat peeks through a wooden window of an aged building, adding charm.",
|
|
color: "Brown",
|
|
texture: "Aged"
|
|
},
|
|
{
|
|
id: 14,
|
|
name: "Roman Stone Arch",
|
|
image: "images/brick_14.jpg",
|
|
description: "Detailed view of an ancient Roman stone arch with ornate decorative carvings.",
|
|
color: "Brown",
|
|
texture: "Ornate"
|
|
},
|
|
{
|
|
id: 15,
|
|
name: "Cozy Brick Fireplace",
|
|
image: "images/brick_15.jpg",
|
|
description: "Cozy winter fireplace with brickwork showcasing warm textures.",
|
|
color: "Brown",
|
|
texture: "Cozy"
|
|
},
|
|
{
|
|
id: 16,
|
|
name: "Classic Brick Doorway",
|
|
image: "images/brick_16.jpg",
|
|
description: "A classic wooden door set in an ancient stone wall with a decorative flower wreath.",
|
|
color: "Brown",
|
|
texture: "Classic"
|
|
}
|
|
];
|
|
|
|
let currentIndex = 0;
|
|
let likedCount = 0;
|
|
let startX = 0;
|
|
let startY = 0;
|
|
let currentX = 0;
|
|
let currentY = 0;
|
|
let isDragging = false;
|
|
|
|
const card = document.getElementById('currentCard');
|
|
const brickImage = document.getElementById('brickImage');
|
|
const brickName = document.getElementById('brickName');
|
|
const brickDescription = document.getElementById('brickDescription');
|
|
const brickColor = document.getElementById('brickColor');
|
|
const brickTexture = document.getElementById('brickTexture');
|
|
const likeBtn = document.getElementById('likeBtn');
|
|
const nopeBtn = document.getElementById('nopeBtn');
|
|
const likedCountEl = document.getElementById('likedCount');
|
|
const remainingCountEl = document.getElementById('remainingCount');
|
|
const endScreen = document.getElementById('endScreen');
|
|
const finalLikedCount = document.getElementById('finalLikedCount');
|
|
const restartBtn = document.getElementById('restartBtn');
|
|
const backgroundImage = document.querySelector('.background-image');
|
|
const matchPopup = document.getElementById('matchPopup');
|
|
|
|
function loadBrick(index) {
|
|
if (index >= bricks.length) {
|
|
showEndScreen();
|
|
return;
|
|
}
|
|
|
|
const brick = bricks[index];
|
|
|
|
// Reset card position and opacity for smooth entry
|
|
card.style.transition = 'none';
|
|
card.style.transform = 'translate(0, 0) rotate(0deg)';
|
|
card.style.opacity = '0';
|
|
|
|
// Hide background image when new card loads
|
|
if (backgroundImage) {
|
|
backgroundImage.style.transition = 'opacity 0.3s ease-in';
|
|
backgroundImage.style.opacity = '0';
|
|
}
|
|
|
|
// Update content
|
|
brickImage.src = brick.image;
|
|
brickImage.alt = brick.name;
|
|
brickName.textContent = brick.name;
|
|
brickDescription.textContent = brick.description;
|
|
brickColor.textContent = brick.color;
|
|
brickTexture.textContent = brick.texture;
|
|
card.querySelector('.card-overlay').classList.remove('active');
|
|
|
|
updateStats();
|
|
|
|
// Fade in the new card smoothly
|
|
setTimeout(() => {
|
|
card.style.transition = 'opacity 0.3s ease-in';
|
|
card.style.opacity = '1';
|
|
}, 50);
|
|
}
|
|
|
|
function updateStats() {
|
|
likedCountEl.textContent = likedCount;
|
|
remainingCountEl.textContent = bricks.length - currentIndex;
|
|
}
|
|
|
|
function swipeCard(direction) {
|
|
const overlay = card.querySelector('.card-overlay');
|
|
const likeBadge = overlay.querySelector('.like-badge');
|
|
const nopeBadge = overlay.querySelector('.nope-badge');
|
|
|
|
overlay.classList.add('active');
|
|
|
|
// Set transition for smooth animation
|
|
card.style.transition = 'transform 0.4s ease-out, opacity 0.4s ease-out';
|
|
|
|
// Show background image as card swipes away
|
|
if (backgroundImage) {
|
|
backgroundImage.style.transition = 'opacity 0.4s ease-out';
|
|
backgroundImage.style.opacity = '0.10';
|
|
}
|
|
|
|
if (direction === 'right') {
|
|
likeBadge.style.display = 'block';
|
|
nopeBadge.style.display = 'none';
|
|
likedCount++;
|
|
updateStats();
|
|
|
|
// Smoothly animate card off screen
|
|
card.style.transform = `translate(400px, 0) rotate(25deg)`;
|
|
card.style.opacity = '0';
|
|
|
|
// Show match popup after card animation, then auto-continue
|
|
setTimeout(() => {
|
|
showMatchPopup();
|
|
// Auto-hide and continue after 2 seconds
|
|
setTimeout(() => {
|
|
hideMatchPopup();
|
|
nextBrick();
|
|
}, 2000);
|
|
}, 400);
|
|
} else {
|
|
nopeBadge.style.display = 'block';
|
|
likeBadge.style.display = 'none';
|
|
|
|
// Smoothly animate card off screen
|
|
card.style.transform = `translate(-400px, 0) rotate(-25deg)`;
|
|
card.style.opacity = '0';
|
|
|
|
// Load next brick after animation completes
|
|
setTimeout(() => {
|
|
nextBrick();
|
|
}, 400);
|
|
}
|
|
}
|
|
|
|
function showMatchPopup() {
|
|
if (matchPopup) {
|
|
// Set the right profile image to the current brick
|
|
const rightProfileImg = document.getElementById('rightProfileImg');
|
|
if (rightProfileImg && currentIndex < bricks.length) {
|
|
rightProfileImg.src = bricks[currentIndex].image;
|
|
}
|
|
matchPopup.classList.add('show');
|
|
// Prevent body scrolling
|
|
document.body.style.overflow = 'hidden';
|
|
document.documentElement.style.overflow = 'hidden';
|
|
}
|
|
}
|
|
|
|
function hideMatchPopup() {
|
|
if (matchPopup) {
|
|
matchPopup.classList.remove('show');
|
|
// Restore body scrolling
|
|
document.body.style.overflow = '';
|
|
document.documentElement.style.overflow = '';
|
|
}
|
|
}
|
|
|
|
function nextBrick() {
|
|
currentIndex++;
|
|
loadBrick(currentIndex);
|
|
}
|
|
|
|
function showEndScreen() {
|
|
endScreen.classList.add('show');
|
|
finalLikedCount.textContent = likedCount;
|
|
}
|
|
|
|
function restart() {
|
|
currentIndex = 0;
|
|
likedCount = 0;
|
|
endScreen.classList.remove('show');
|
|
loadBrick(0);
|
|
}
|
|
|
|
// Touch/Mouse events for swiping
|
|
card.addEventListener('mousedown', startDrag);
|
|
card.addEventListener('touchstart', startDrag);
|
|
|
|
card.addEventListener('mousemove', drag);
|
|
card.addEventListener('touchmove', drag);
|
|
|
|
card.addEventListener('mouseup', endDrag);
|
|
card.addEventListener('touchend', endDrag);
|
|
card.addEventListener('mouseleave', endDrag);
|
|
|
|
function startDrag(e) {
|
|
isDragging = true;
|
|
const clientX = e.touches ? e.touches[0].clientX : e.clientX;
|
|
const clientY = e.touches ? e.touches[0].clientY : e.clientY;
|
|
startX = clientX - card.offsetLeft;
|
|
startY = clientY - card.offsetTop;
|
|
card.style.transition = 'none';
|
|
}
|
|
|
|
function drag(e) {
|
|
if (!isDragging) return;
|
|
e.preventDefault();
|
|
|
|
const clientX = e.touches ? e.touches[0].clientX : e.clientX;
|
|
const clientY = e.touches ? e.touches[0].clientY : e.clientY;
|
|
currentX = clientX - startX;
|
|
currentY = clientY - startY;
|
|
|
|
const rotate = currentX / 20;
|
|
card.style.transform = `translate(${currentX}px, ${currentY}px) rotate(${rotate}deg)`;
|
|
|
|
const overlay = card.querySelector('.card-overlay');
|
|
if (Math.abs(currentX) > 50) {
|
|
overlay.classList.add('active');
|
|
if (currentX > 0) {
|
|
overlay.querySelector('.like-badge').style.display = 'block';
|
|
overlay.querySelector('.nope-badge').style.display = 'none';
|
|
} else {
|
|
overlay.querySelector('.nope-badge').style.display = 'block';
|
|
overlay.querySelector('.like-badge').style.display = 'none';
|
|
}
|
|
} else {
|
|
overlay.classList.remove('active');
|
|
}
|
|
}
|
|
|
|
function endDrag() {
|
|
if (!isDragging) return;
|
|
isDragging = false;
|
|
card.style.transition = 'transform 0.4s ease-out, opacity 0.4s ease-out';
|
|
|
|
if (Math.abs(currentX) > 100) {
|
|
if (currentX > 0) {
|
|
swipeCard('right');
|
|
} else {
|
|
swipeCard('left');
|
|
}
|
|
} else {
|
|
card.style.transform = 'translate(0, 0) rotate(0deg)';
|
|
card.style.opacity = '1';
|
|
card.querySelector('.card-overlay').classList.remove('active');
|
|
}
|
|
|
|
currentX = 0;
|
|
currentY = 0;
|
|
}
|
|
|
|
// Button events
|
|
likeBtn.addEventListener('click', () => swipeCard('right'));
|
|
nopeBtn.addEventListener('click', () => swipeCard('left'));
|
|
restartBtn.addEventListener('click', restart);
|
|
|
|
// Initialize
|
|
loadBrick(0);
|