digital-theory/js/anime-master/documentation/examples/time-control.html

410 lines
11 KiB
HTML
Raw Normal View History

2023-04-21 23:27:42 +02:00
<!DOCTYPE html>
<html>
<head>
<title>time control • anime.js</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta property="og:title" content="anime.js">
<meta property="og:url" content="https://animejs.com">
<meta property="og:description" content="Javascript Animation Engine">
<meta property="og:image" content="https://animejs.com/documentation/assets/img/icons/og.png">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="anime.js">
<meta name="twitter:site" content="@juliangarnier">
<meta name="twitter:description" content="Javascript Animation Engine">
<meta name="twitter:image" content="https://animejs.com/documentation/assets/img/icons/twitter.png">
<link rel="apple-touch-icon-precomposed" href="../assets/img/social-media-image.png">
<link rel="icon" type="image/png" href="../assets/img/favicon.png" >
<link href="../assets/css/animejs.css" rel="stylesheet">
<style>
:root {
font-size: 24px;
}
body {
display: flex;
flex-wrap: wrap;
justify-content: center;
align-items: center;
}
.feature-section {
position: relative;
display: flex;
}
.feature-section-center {
flex-direction: column;
align-items: center;
text-align: center;
}
.section-title {
font-size: 64px;
line-height: 56px;
letter-spacing: 0;
margin-bottom: 1rem;
}
.section-title span {
display: inline-block;
}
.section-description {
font-size: 24px;
line-height: 32px;
letter-spacing: 0;
margin-bottom: 3rem;
}
.feature-anim {
position: relative;
display: flex;
flex-wrap: wrap;
align-items: center;
}
.time-control {
height: 12rem;
}
.time-control .ruller {
position: absolute;
top: 0;
display: flex;
width: calc(34rem + 4px);
padding: 0 1px;
}
.time-control .line {
width: 2px;
height: .5rem;
background-color: currentColor;
}
.time-control .line:nth-child(9n+2) {
height: 1rem;
}
.time-control .line:not(:last-child) {
margin-right: 4px;
}
.time-cursor {
position: absolute;
z-index: 1;
top: -1.125rem;
left: calc(-1rem + 2px);
width: 2rem;
height: 2rem;
background-color: currentColor;
border-radius: 50%;
}
.time-cursor input {
position: relative;
z-index: 1;
width: 2rem;
height: 2rem;
color: #FFF;
background-color: transparent;
border-radius: 50%;
text-align: center;
font-size: .5rem;
}
.time-cursor:before {
content: "";
position: absolute;
top: 0;
left: calc(1rem - 1px);
display: block;
width: 2px;
height: 12.125rem;
background-color: #F64E4D;
}
.timeline {
position: relative;
z-index: 1;
overflow: visible;
display: flex;
width: 100%;
height: 8px;
font-size: .75rem;
}
.animation {
position: relative;
overflow: visible;
display: flex;
}
.animation-band {
position: relative;
height: 8px;
margin: 0 1px;
border-radius: 4px;
}
.animation-delay {
background-color: currentColor;
width: 48px;
}
.animation-change {
background-color: #F64E4D;
width: 156px;
}
.animation-end-delay {
border: 2px solid currentColor;
width: 48px;
}
.info {
position: relative;
display: flex;
flex-direction: column;
width: 2px;
height: 2rem;
margin: 0 1px;
}
.info + .info { margin-left: -3px; }
.info-large { height: 4rem; }
.info-top {
bottom: 0;
justify-content: flex-start;
align-items: flex-end;
align-self: flex-end;
}
.info-bottom {
top: 0;
justify-content: flex-end;
}
.info-bar {
position: absolute;
width: 2px;
height: 100%;
background-color: currentColor;
transform-origin: 50% 100%;
}
.info-top .info-bar { bottom: 0; }
.info-bottom .info-bar { top: 0; transform-origin: 50% 0%; }
.info-left .info-bar { left: 0; }
.info-right .info-bar { right: 0; }
.info-label {
white-space: nowrap;
height: 1rem;
padding-left: .5rem;
padding-right: .5rem;
line-height: 1rem;
}
.info-top .info-label {
margin: -4px 0 0;
}
.info-bottom .info-label {
margin: 0 0 -4px 0;
}
</style>
</head>
<body>
<section class="feature-section feature-section-center feature-control" style="margin-top: 1000px; margin-bottom: 1000px;">
<h1 class="section-title">
<span>Time</span> <span>control</span> <span>& callbacks</span>
</h1>
<p class="section-description">
Play, pause, control, reverse and trigger events in sync
</p>
<div class="time-control feature-anim">
<div class="ruller">
<div class="time-cursor color-red">
<input value="999" />
</div>
</div>
<div class="timeline">
<div class="info-loop-begin info info-large info-left info-bottom" data-delay="0">
<div class="info-bar"></div>
<div class="info-label">loop begin</div>
<div class="info-label">animation begin</div>
</div>
<div class="animation">
<div class="animation-band animation-delay"></div>
<div class="info-change-begin info info-left info-bottom" data-delay="100">
<div class="info-bar"></div>
<div class="info-label">change begin</div>
</div>
<div class="animation-band animation-change"></div>
<div class="info-change-complete info info-right info-top" data-delay="400">
<div class="info-bar"></div>
<div class="info-label">change complete</div>
</div>
<div class="animation-band animation-end-delay"></div>
</div>
<div class="info-loop-complete info info-large info-right info-top" data-delay="500">
<div class="info-bar"></div>
<div class="info-label">loop complete</div>
</div>
<div class="info info-large info-left info-bottom" data-delay="500">
<div class="info-bar"></div>
<div class="info-label">loop begin</div>
<div class="info-label">reverse</div>
</div>
<div class="animation">
<div class="animation-band animation-delay"></div>
<div class="info-change-begin info info-left info-bottom" data-delay="600">
<div class="info-bar"></div>
<div class="info-label">change begin</div>
</div>
<div class="animation-band animation-change"></div>
<div class="info-change-complete info info-right info-top" data-delay="900">
<div class="info-bar"></div>
<div class="info-label">change complete</div>
</div>
<div class="animation-band animation-end-delay"></div>
</div>
<div class="info-loop-complete info info-large info-right info-top" data-delay="1000">
<div class="info-bar"></div>
<div class="info-label">loop complete</div>
</div>
<div class="info info-large info-left info-bottom" data-delay="1000">
<div class="info-bar"></div>
<div class="info-label">loop begin</div>
<div class="info-label">reverse</div>
</div>
<div class="animation">
<div class="animation-band animation-delay"></div>
<div class="info-change-begin info info-left info-bottom" data-delay="1100">
<div class="info-bar"></div>
<div class="info-label">change begin</div>
</div>
<div class="animation-band animation-change"></div>
<div class="info-change-complete info info-right info-top" data-delay="1400">
<div class="info-bar"></div>
<div class="info-label">change complete</div>
</div>
<div class="animation-band animation-end-delay"></div>
</div>
<div class="info-loop-complete info info-large info-right info-top" data-delay="1500">
<div class="info-bar"></div>
<div class="info-label">animation complete</div>
<div class="info-label">loop complete</div>
</div>
</div>
</div>
</section>
</body>
<script type="module">
import anime from '../../src/index.js';
const timeControlEl = document.querySelector('.time-control');
const rullerEl = document.querySelector('.ruller');
const timeEl = document.querySelector('.time-cursor input');
const infoEls = document.querySelectorAll('.info');
const fragment = document.createDocumentFragment();
const numberOfElements = 136;
function isElementInViewport(el, inCB, outCB) {
function handleIntersect(entries, observer) {
var entry = entries[0];
if (entry.isIntersecting) {
if (inCB) inCB(el, entry);
} else {
if (outCB) outCB(el, entry);
}
}
var observer = new IntersectionObserver(handleIntersect);
observer.observe(el);
}
for (let i = 0; i < numberOfElements; i++) {
const dotEl = document.createElement('div');
dotEl.classList.add('line');
fragment.appendChild(dotEl);
}
rullerEl.appendChild(fragment);
const timeControlAnimation = anime.timeline({
easing: 'linear',
autoplay: false
})
.add({
targets: '.time-cursor',
keyframes: [
{ translateY: ['-1rem', 0], duration: 100, easing: 'easeInQuad' },
{ translateX: 'calc(34rem - 6px)', duration: 1500 },
{ translateY: '-1rem', duration: 100, easing: 'easeOutQuad' }
],
duration: 1500,
update: function(anim) {
timeEl.value = anim.currentTime;
}
}, -100)
.add({
targets: '.ruller .line',
translateY: [ {value: '1rem'}, {value: '0rem'} ],
duration: 200,
delay: anime.stagger([0, 1500]),
easing: 'easeInOutSine'
}, -100)
for (var i = 0; i < infoEls.length; i++) {
var infoEl = infoEls[i];
var delay = parseFloat(anime.get(infoEl, 'data-delay'));
var direction = infoEl.classList.contains('info-bottom') ? -1 : 1;
timeControlAnimation
.add({
targets: infoEl.querySelector('.info-bar'),
scaleY: [0, 1],
duration: 250,
easing: 'easeOutCirc'
}, delay)
.add({
targets: infoEl.querySelectorAll('.info-label'),
opacity: [0, 1],
translateY: [direction * 10, 0],
duration: 150,
delay: anime.stagger(50, {start: 10, direction: direction > 0 ? 'reverse' : 'normal'}),
easing: 'easeOutSine'
}, delay)
}
var controlAnimationCanMove = false;
function moveControlAnimation() {
var rect = timeControlEl.getBoundingClientRect();
var top = rect.top;
var height = rect.height;
var windowHeight = window.innerHeight;
var scrolled = (top - windowHeight) * -1;
timeControlAnimation.seek((scrolled * 3) - 500);
if (controlAnimationCanMove) requestAnimationFrame(moveControlAnimation);
}
isElementInViewport(timeControlEl, function(el, entry) {
controlAnimationCanMove = true;
requestAnimationFrame(moveControlAnimation);
}, function(el, entry) {
controlAnimationCanMove = false;
});
</script>
</html>