시연 동영상 보기
<div class="prizesection">
<div id="app">
<div id="prize">
<h2 id="prize-label">
<span class="asterisk">*</span>
<span>금액</span>
<span class="asterisk">*</span>
</h2>
<h1 id="prize-text"></h1>
</div>
</div>
</div>
<style>
.prizesection {
background-color: black;
height: 100vh;
overflow: hidden;
font-family: "Orbitron", sans-serif;
}
#app {
height: 100%;
width: 100%;
position: relative;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(
60deg,
rgb(var(--background-rgb)) 30%,
rgb(var(--theme-rgb) / 8%) 50%,
rgb(var(--background-rgb)) 70%
);
}
@keyframes float {
from, to {
translate: 0% 0%;
}
50% {
translate: 0% 10%;
}
}
#prize {
width: 105rem;
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
position: relative;
z-index: 2;
background-color: rgb(var(--darker-rgb));
border: 1.5rem solid rgb(255 255 255 / 2.5%);
padding: 10rem 4rem;
box-shadow: 0rem 0rem 10rem 4rem rgb(0 0 0 / 75%);
backdrop-filter: blur(1rem);
}
#prize-label,
#prize-text {
color: rgb(var(--theme-rgb));
text-align: center;
}
#prize-label {
display: flex;
align-items: center;
justify-content: center;
gap: 2rem;
font-size: 3rem;
opacity: 0.75;
}
#prize-label > span {
display: inline-flex;
}
#prize-label > .asterisk {
padding-top: 0.25em;
line-height: 0.5em;
}
#prize-text {
display: flex;
gap: 1rem;
height: 10rem;
line-height: 10rem;
font-size: 11rem;
}
#prize-text > .digit {
width: 8rem;
position: relative;
overflow: hidden;
border-bottom: 0.25rem solid rgb(var(--theme-rgb));
}
#prize-text > .digit > .digit-track {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
position: absolute;
left: 0%;
top: 0%;
translate: 0% 0%;
transition: translate 3000ms cubic-bezier(.1,.67,0,1);
}
@media(max-width: 1700px) {
#prize {
scale: 0.75;
}
}
@media(max-width: 1300px) {
#prize {
scale: 0.5;
}
}
@media(max-width: 900px) {
#prize {
scale: 0.3;
}
}
@media(max-width: 600px) {
#prize {
scale: 0.2;
}
}
</style>
<script>
const MINIMUM_ADDITIONAL_ITERATION_COUNT = 2;
const config = {
additionalIterationCount: Math.max(MINIMUM_ADDITIONAL_ITERATION_COUNT, 3),
transitionDuration: 3000,
prize: 120000000,
digits: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
}
const USD = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "KRW",
maximumFractionDigits: 0
});
const getPrizeText = () => document.getElementById("prize-text"),
getTracks = () => document.querySelectorAll(".digit > .digit-track");
const getFormattedPrize = () => USD.format(config.prize),
getPrizeDigitByIndex = index => parseInt(config.prize.toString()[index]),
determineIterations = index => index + config.additionalIterationCount;
const createElement = (type, className, text) => {
const element = document.createElement(type);
element.className = className;
if(text !== undefined) element.innerText = text;
return element;
}
const createCharacter = character => createElement("span", "character", character);
const createDigit = (digit, trackIndex) => {
const digitElement = createElement("span", "digit"),
trackElement = createElement("span", "digit-track");
let digits = [],
iterations = determineIterations(trackIndex);
for(let i = 0; i < iterations; i++) {
digits = [...digits, ...config.digits];
}
trackElement.innerText = digits.join(" ");
trackElement.style.transitionDuration = `${config.transitionDuration}ms`;
digitElement.appendChild(trackElement);
return digitElement;
}
const setup = () => {
let index = 0;
const prizeText = getPrizeText();
for(const character of getFormattedPrize()) {
const element = isNaN(character)
? createCharacter(character) : createDigit(character, index++);
prizeText.appendChild(element);
}
}
const animate = () => {
getTracks().forEach((track, index) => {
const digit = getPrizeDigitByIndex(index),
iterations = determineIterations(index),
activeDigit = ((iterations - 1) * 10) + digit;
track.style.translate = `0rem ${activeDigit * -10}rem`;
});
}
window.onload = () => {
setup();
setTimeout(animate);
};
const handleRedo = () => {
resetAnimation();
animate();
}
const resetTrackPosition = track => {
track.style.transitionDuration = "0ms";
track.style.translate = "0rem 0rem";
track.offsetHeight;
track.style.transitionDuration = `${config.transitionDuration}ms`;
}
const resetAnimation = () => {
for(const track of getTracks()) resetTrackPosition(track);
}
</script>
시연 동영상 보기
<div class="prizesection">
<div id="app">
<div id="prize">
<h2 id="prize-label">
<span class="asterisk">*</span>
<span>금액</span>
<span class="asterisk">*</span>
</h2>
<h1 id="prize-text"></h1>
</div>
</div>
</div>
<style>
.prizesection {
background-color: black;
height: 100vh;
overflow: hidden;
font-family: "Orbitron", sans-serif;
}
#app {
height: 100%;
width: 100%;
position: relative;
display: flex;
align-items: center;
justify-content: center;
background: linear-gradient(
60deg,
rgb(var(--background-rgb)) 30%,
rgb(var(--theme-rgb) / 8%) 50%,
rgb(var(--background-rgb)) 70%
);
}
@keyframes float {
from, to {
translate: 0% 0%;
}
50% {
translate: 0% 10%;
}
}
#prize {
width: 105rem;
display: flex;
flex-direction: column;
align-items: center;
gap: 0.5rem;
position: relative;
z-index: 2;
background-color: rgb(var(--darker-rgb));
border: 1.5rem solid rgb(255 255 255 / 2.5%);
padding: 10rem 4rem;
box-shadow: 0rem 0rem 10rem 4rem rgb(0 0 0 / 75%);
backdrop-filter: blur(1rem);
}
#prize-label,
#prize-text {
color: rgb(var(--theme-rgb));
text-align: center;
}
#prize-label {
display: flex;
align-items: center;
justify-content: center;
gap: 2rem;
font-size: 3rem;
opacity: 0.75;
}
#prize-label > span {
display: inline-flex;
}
#prize-label > .asterisk {
padding-top: 0.25em;
line-height: 0.5em;
}
#prize-text {
display: flex;
gap: 1rem;
height: 10rem;
line-height: 10rem;
font-size: 11rem;
}
#prize-text > .digit {
width: 8rem;
position: relative;
overflow: hidden;
border-bottom: 0.25rem solid rgb(var(--theme-rgb));
}
#prize-text > .digit > .digit-track {
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
position: absolute;
left: 0%;
top: 0%;
translate: 0% 0%;
transition: translate 3000ms cubic-bezier(.1,.67,0,1);
}
@media(max-width: 1700px) {
#prize {
scale: 0.75;
}
}
@media(max-width: 1300px) {
#prize {
scale: 0.5;
}
}
@media(max-width: 900px) {
#prize {
scale: 0.3;
}
}
@media(max-width: 600px) {
#prize {
scale: 0.2;
}
}
</style>
<script>
const MINIMUM_ADDITIONAL_ITERATION_COUNT = 2;
const config = {
additionalIterationCount: Math.max(MINIMUM_ADDITIONAL_ITERATION_COUNT, 3),
transitionDuration: 3000,
prize: 120000000,
digits: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
}
const USD = new Intl.NumberFormat("en-US", {
style: "currency",
currency: "KRW",
maximumFractionDigits: 0
});
const getPrizeText = () => document.getElementById("prize-text"),
getTracks = () => document.querySelectorAll(".digit > .digit-track");
const getFormattedPrize = () => USD.format(config.prize),
getPrizeDigitByIndex = index => parseInt(config.prize.toString()[index]),
determineIterations = index => index + config.additionalIterationCount;
const createElement = (type, className, text) => {
const element = document.createElement(type);
element.className = className;
if(text !== undefined) element.innerText = text;
return element;
}
const createCharacter = character => createElement("span", "character", character);
const createDigit = (digit, trackIndex) => {
const digitElement = createElement("span", "digit"),
trackElement = createElement("span", "digit-track");
let digits = [],
iterations = determineIterations(trackIndex);
for(let i = 0; i < iterations; i++) {
digits = [...digits, ...config.digits];
}
trackElement.innerText = digits.join(" ");
trackElement.style.transitionDuration = `${config.transitionDuration}ms`;
digitElement.appendChild(trackElement);
return digitElement;
}
const setup = () => {
let index = 0;
const prizeText = getPrizeText();
for(const character of getFormattedPrize()) {
const element = isNaN(character)
? createCharacter(character) : createDigit(character, index++);
prizeText.appendChild(element);
}
}
const animate = () => {
getTracks().forEach((track, index) => {
const digit = getPrizeDigitByIndex(index),
iterations = determineIterations(index),
activeDigit = ((iterations - 1) * 10) + digit;
track.style.translate = `0rem ${activeDigit * -10}rem`;
});
}
window.onload = () => {
setup();
setTimeout(animate);
};
const handleRedo = () => {
resetAnimation();
animate();
}
const resetTrackPosition = track => {
track.style.transitionDuration = "0ms";
track.style.translate = "0rem 0rem";
track.offsetHeight;
track.style.transitionDuration = `${config.transitionDuration}ms`;
}
const resetAnimation = () => {
for(const track of getTracks()) resetTrackPosition(track);
}
</script>