Skip to content

Instantly share code, notes, and snippets.

@oceangravity
Created July 16, 2024 16:24
Show Gist options
  • Save oceangravity/5a298182377a99151ed0549400dc01f4 to your computer and use it in GitHub Desktop.
Save oceangravity/5a298182377a99151ed0549400dc01f4 to your computer and use it in GitHub Desktop.
zYVvPEe
<div class="container">
<ul id="bandList"></ul>
</div>
const bands = [
"The Beatles", "Led Zeppelin", "Pink Floyd", "Queen", "The Rolling Stones",
"AC/DC", "Nirvana", "Guns N' Roses", "Metallica", "Aerosmith",
"The Who", "U2", "Pearl Jam", "The Doors", "Radiohead",
"Foo Fighters", "Red Hot Chili Peppers", "The Eagles", "Fleetwood Mac", "Deep Purple",
"The Clash", "Black Sabbath", "Bon Jovi", "Kiss", "Lynyrd Skynyrd",
"Def Leppard", "Green Day", "Oasis", "Journey", "Linkin Park"
];
let startIndex = 0;
const itemHeight = 40;
const bandList = document.getElementById('bandList');
let translateY = 0;
function createListElement(index) {
const li = document.createElement('li');
li.textContent = bands[index % bands.length];
li.dataset.index = index;
return li;
}
function renderList() {
bandList.innerHTML = '';
for (let i = 0; i < 7; i++) {
const li = createListElement((startIndex + i) % bands.length);
li.style.transform = `translateY(${i * itemHeight}px)`;
bandList.appendChild(li);
}
}
function updateList(direction) {
if (direction === 'up') {
startIndex = (startIndex - 1 + bands.length) % bands.length;
const first = bandList.firstChild;
const newItem = createListElement(startIndex);
newItem.style.transform = `translateY(${parseInt(first.style.transform.replace('translateY(', '').replace('px)', '')) - itemHeight}px)`;
bandList.insertBefore(newItem, first);
bandList.removeChild(bandList.lastChild);
} else if (direction === 'down') {
const last = bandList.lastChild;
const newItem = createListElement((startIndex + 6) % bands.length);
newItem.style.transform = `translateY(${parseInt(last.style.transform.replace('translateY(', '').replace('px)', '')) + itemHeight}px)`;
bandList.appendChild(newItem);
bandList.removeChild(bandList.firstChild);
startIndex = (startIndex + 1) % bands.length;
}
// Re-observe the list items
Array.from(bandList.children).forEach(item => observer.observe(item));
}
const observer = new IntersectionObserver(entries => {
entries.forEach(entry => {
if (entry.isIntersecting) {
if (entry.target.dataset.index == startIndex) {
updateList('up');
} else if (entry.target.dataset.index == (startIndex + 6) % bands.length) {
updateList('down');
}
}
});
}, { root: document.querySelector('.container'), threshold: 0.1 });
renderList();
Array.from(bandList.children).forEach(item => observer.observe(item));
let startY = 0;
let isDragging = false;
bandList.addEventListener('mousedown', (event) => {
isDragging = true;
startY = event.clientY;
bandList.classList.add('draggable');
});
document.addEventListener('mouseup', () => {
isDragging = false;
bandList.classList.remove('draggable');
});
document.addEventListener('mousemove', (event) => {
if (isDragging) {
const diff = event.clientY - startY;
startY = event.clientY;
translateY += diff;
bandList.style.transform = `translateY(${translateY}px)`;
// if (translateY <= -itemHeight) {
// translateY += itemHeight;
// updateList('up');
// } else if (translateY >= itemHeight) {
// translateY -= itemHeight;
// updateList('down');
// }
}
});
body {
font-family: Arial, sans-serif;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
background-color: #f4f4f4;
user-select: none;
}
.container {
width: 300px;
height: 200px; /* Height to show 5 items */
overflow: hidden;
border: 1px solid #ccc;
border-radius: 5px;
background: #fff;
position: relative;
}
#bandList {
list-style-type: none;
padding: 0;
margin: 0;
position: relative;
transform: translateY(0);
}
#bandList li {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
outline: 1px solid #ddd;
width: 100%;
height: 40px; /* Fixed height for each item */
}
.draggable {
cursor: grab;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment