mirror of
https://github.com/JeremyLikness/vanillajs-deck
synced 2024-12-04 19:27:37 +00:00
Add animation framework
This commit is contained in:
parent
f37b3371bb
commit
88f7b5cbc2
21
css/animations.css
Normal file
21
css/animations.css
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
@keyframes slide-left {
|
||||||
|
from { margin-left: 0vw; }
|
||||||
|
to { margin-left: -100vw; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes enter-right {
|
||||||
|
from { margin-left: 100vw; }
|
||||||
|
to { margin-left: 0vw; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.anim-slide-left-begin {
|
||||||
|
animation-name: slide-left;
|
||||||
|
animation-timing-function: ease-in;
|
||||||
|
animation-duration: 0.5s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.anim-slide-left-end {
|
||||||
|
animation-name: enter-right;
|
||||||
|
animation-timing-function: ease-out;
|
||||||
|
animation-duration: 0.3s;
|
||||||
|
}
|
@ -65,7 +65,7 @@ img {
|
|||||||
slide-deck div {
|
slide-deck div {
|
||||||
height: 80vh;
|
height: 80vh;
|
||||||
padding: 1em;
|
padding: 1em;
|
||||||
background: lightgray;
|
border: solid 2px lightgray;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media only screen and (max-width: 960px) {
|
@media only screen and (max-width: 960px) {
|
||||||
@ -93,6 +93,6 @@ slide-controls {
|
|||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
nextslide {
|
nextslide, transition {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
@ -11,6 +11,7 @@
|
|||||||
content="default-src 'self'; child-src 'none'; connect-src 'self'; font-src 'self'; frame-src 'self'; img-src 'self'; media-src 'self'; object-src 'none'; style-src 'self';">
|
content="default-src 'self'; child-src 'none'; connect-src 'self'; font-src 'self'; frame-src 'self'; img-src 'self'; media-src 'self'; object-src 'none'; style-src 'self';">
|
||||||
<link rel="shortcut icon" href="/images/logo.png" type="image/png" />
|
<link rel="shortcut icon" href="/images/logo.png" type="image/png" />
|
||||||
<link rel="stylesheet" href="css/style.css">
|
<link rel="stylesheet" href="css/style.css">
|
||||||
|
<link rel="stylesheet" href="css/animations.css">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
42
js/animator.js
Normal file
42
js/animator.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
export class Animator {
|
||||||
|
constructor() {
|
||||||
|
this._transitioning = false;
|
||||||
|
this._begin = null;
|
||||||
|
this._end = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
get transitioning() {
|
||||||
|
return this._transitioning;
|
||||||
|
}
|
||||||
|
|
||||||
|
get animationReady() {
|
||||||
|
return !!this._end;
|
||||||
|
}
|
||||||
|
|
||||||
|
beginAnimation(animationName, host, callback) {
|
||||||
|
this._transitioning = true;
|
||||||
|
this._begin = `anim-${animationName}-begin`;
|
||||||
|
this._end = `anim-${animationName}-end`;
|
||||||
|
const animationEnd = () => {
|
||||||
|
host.removeEventListener("animationend", animationEnd);
|
||||||
|
host.classList.remove(this._begin);
|
||||||
|
this._transitioning = false;
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
host.addEventListener("animationend", animationEnd, false);
|
||||||
|
host.classList.add(this._begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
endAnimation(host) {
|
||||||
|
this._transitioning = true;
|
||||||
|
const animationEnd = () => {
|
||||||
|
host.removeEventListener("animationend", animationEnd);
|
||||||
|
host.classList.remove(this._end);
|
||||||
|
this._transitioning = false;
|
||||||
|
this._begin = null;
|
||||||
|
this._end = null;
|
||||||
|
}
|
||||||
|
host.addEventListener("animationend", animationEnd, false);
|
||||||
|
host.classList.add(this._end);
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,12 @@
|
|||||||
import { loadSlides } from "./slideLoader.js"
|
import { loadSlides } from "./slideLoader.js"
|
||||||
import { Router } from "./router.js"
|
import { Router } from "./router.js"
|
||||||
|
import { Animator } from "./animator.js"
|
||||||
|
|
||||||
class Navigator extends HTMLElement {
|
class Navigator extends HTMLElement {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
this._animator = new Animator();
|
||||||
this._router = new Router();
|
this._router = new Router();
|
||||||
this._route = this._router.getRoute();
|
this._route = this._router.getRoute();
|
||||||
this.slidesChangedEvent = new CustomEvent("slideschanged", {
|
this.slidesChangedEvent = new CustomEvent("slideschanged", {
|
||||||
@ -61,6 +63,9 @@ class Navigator extends HTMLElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
jumpTo(slideIdx) {
|
jumpTo(slideIdx) {
|
||||||
|
if (this._animator.transitioning) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (slideIdx >= 0 && slideIdx < this.totalSlides) {
|
if (slideIdx >= 0 && slideIdx < this.totalSlides) {
|
||||||
this._currentIndex = slideIdx;
|
this._currentIndex = slideIdx;
|
||||||
this.innerHTML = '';
|
this.innerHTML = '';
|
||||||
@ -68,12 +73,23 @@ class Navigator extends HTMLElement {
|
|||||||
this._router.setRoute(slideIdx+1);
|
this._router.setRoute(slideIdx+1);
|
||||||
this._route = this._router.getRoute();
|
this._route = this._router.getRoute();
|
||||||
this.dispatchEvent(this.slidesChangedEvent);
|
this.dispatchEvent(this.slidesChangedEvent);
|
||||||
|
if (this._animator.animationReady) {
|
||||||
|
this._animator.endAnimation(this.querySelector("div"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
next() {
|
next() {
|
||||||
if (this.hasNext) {
|
if (this.hasNext) {
|
||||||
this.jumpTo(this.currentIndex + 1);
|
if (this.currentSlide.transition !== null) {
|
||||||
|
this._animator.beginAnimation(
|
||||||
|
this.currentSlide.transition,
|
||||||
|
this.querySelector("div"),
|
||||||
|
() => this.jumpTo(this.currentIndex+1));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.jumpTo(this.currentIndex + 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
11
js/slide.js
11
js/slide.js
@ -5,6 +5,13 @@ export class Slide {
|
|||||||
this._html = document.createElement('div');
|
this._html = document.createElement('div');
|
||||||
this._html.innerHTML = text;
|
this._html.innerHTML = text;
|
||||||
this._title = this._html.querySelectorAll("title")[0].innerText;
|
this._title = this._html.querySelectorAll("title")[0].innerText;
|
||||||
|
const transition = this._html.querySelectorAll("transition");
|
||||||
|
if (transition.length) {
|
||||||
|
this._transition = transition[0].innerText;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this._transition = null;
|
||||||
|
}
|
||||||
const hasNext = this._html.querySelectorAll("nextslide");
|
const hasNext = this._html.querySelectorAll("nextslide");
|
||||||
if (hasNext.length > 0) {
|
if (hasNext.length > 0) {
|
||||||
this._nextSlideName = hasNext[0].innerText;
|
this._nextSlideName = hasNext[0].innerText;
|
||||||
@ -14,6 +21,10 @@ export class Slide {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get transition() {
|
||||||
|
return this._transition;
|
||||||
|
}
|
||||||
|
|
||||||
get title() {
|
get title() {
|
||||||
return this._title;
|
return this._title;
|
||||||
}
|
}
|
||||||
|
@ -2,4 +2,5 @@
|
|||||||
<h1>Vanilla.js: Modern 1st Party JavaScript</h1>
|
<h1>Vanilla.js: Modern 1st Party JavaScript</h1>
|
||||||
<h2>Jeremy Likness</h2>
|
<h2>Jeremy Likness</h2>
|
||||||
<h3>Cloud Advocate, Microsoft</h3>
|
<h3>Cloud Advocate, Microsoft</h3>
|
||||||
<nextslide>002-stuff</nextslide>
|
<nextslide>002-stuff</nextslide>
|
||||||
|
<transition>slide-left</transition>
|
Loading…
Reference in New Issue
Block a user