tinder clone for rating bricks 16 brick images, swipe left/right functionality match modal with profile pics auto-dismisses after 2s background image fades in on swipe end screen with youtube video link styling and animations complete joke website but functional
358 lines
11 KiB
JavaScript
358 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');
|
|
}
|
|
}
|
|
|
|
function hideMatchPopup() {
|
|
if (matchPopup) {
|
|
matchPopup.classList.remove('show');
|
|
}
|
|
}
|
|
|
|
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);
|