Created
September 5, 2023 00:51
-
-
Save Spurlos/f6339c3009c89bbbf8091a721973c28d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
<style> | |
.marquee-container { | |
width: 100%; | |
overflow: hidden; | |
position: relative; | |
white-space: nowrap; | |
} | |
.marquee-content { | |
display: inline-block; | |
white-space: nowrap; | |
animation: marquee linear infinite; /* Use linear timing function */ | |
} | |
@keyframes marquee { | |
0% { | |
transform: translateX(0%); | |
} | |
100% { | |
transform: translateX(-100%); | |
} | |
} | |
</style> | |
</head> | |
<body> | |
<div class="marquee-container" id="marquee-container"> | |
</div> | |
<script> | |
const container = document.getElementById("marquee-container"); | |
const text = "Lorem ipsum dolor; "; | |
const textWidth = getTextWidth(text); // Get the width of the text | |
// Calculate the animation duration coefficient based on the desired duration (e.g., 4 seconds) and a reference text width (e.g., 100px) | |
const desiredDuration = 4; // Desired animation duration in seconds | |
const referenceTextWidth = 100; // Reference text width in pixels | |
const animationDurationCoefficient = desiredDuration / referenceTextWidth; | |
// Calculate the animation duration based on the actual text width | |
const animationDuration = animationDurationCoefficient * textWidth; | |
function createMarquee() { | |
const marquee = document.createElement("div"); | |
marquee.className = "marquee-content"; | |
marquee.textContent = text; | |
marquee.style.animationDuration = animationDuration + "s"; | |
container.appendChild(marquee); | |
} | |
// Helper function to get the width of the text | |
function getTextWidth(text) { | |
const span = document.createElement("span"); | |
span.style.visibility = "hidden"; | |
span.style.whiteSpace = "nowrap"; | |
span.textContent = text; | |
container.appendChild(span); | |
const width = span.offsetWidth; | |
container.removeChild(span); | |
return width; | |
} | |
// Function to continuously add new marquee blocks | |
function addMarquees() { | |
const marqueeElements = container.querySelectorAll(".marquee-content"); | |
let totalWidth = 0; | |
// Calculate the total width of existing marquee blocks | |
marqueeElements.forEach((marquee) => { | |
totalWidth += marquee.offsetWidth; | |
}); | |
// Calculate the number of blocks that can fit in the viewport | |
const blocksPerViewport = Math.floor(window.innerWidth / textWidth); | |
// Calculate the number of blocks needed to fill the viewport | |
const blocksToAdd = blocksPerViewport - Math.ceil(totalWidth / textWidth) + 2; // Add two more blocks | |
// Add new marquee blocks to fill the viewport | |
for (let i = 0; i < blocksToAdd; i++) { | |
createMarquee(); | |
} | |
removeMarqueeIfNeeded(); | |
} | |
function removeMarqueeIfNeeded() { | |
const marqueeElements = container.querySelectorAll(".marquee-content"); | |
for (const marquee of marqueeElements) { | |
const rect = marquee.getBoundingClientRect(); | |
if (rect.right <= 0) { | |
container.removeChild(marquee); | |
} | |
} | |
} | |
// Start by adding marquee blocks based on the available space | |
addMarquees(); | |
// Use Intersection Observer to detect when new marquee blocks should appear | |
const observer = new IntersectionObserver((entries) => { | |
entries.forEach((entry) => { | |
if (entry.isIntersecting) { | |
addMarquees(); | |
} | |
}); | |
}); | |
// Observe the container | |
observer.observe(container); | |
// Listen for viewport changes and recalculate | |
window.addEventListener("resize", () => { | |
// Clear existing marquee blocks | |
const marqueeElements = container.querySelectorAll(".marquee-content"); | |
marqueeElements.forEach((marquee) => { | |
container.removeChild(marquee); | |
}); | |
// Re-add marquee blocks based on the new viewport size | |
addMarquees(); | |
}); | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment