diff --git a/css/animations.css b/css/animations.css new file mode 100644 index 0000000..feb73b5 --- /dev/null +++ b/css/animations.css @@ -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; +} \ No newline at end of file diff --git a/css/style.css b/css/style.css index 8fed94a..d745669 100644 --- a/css/style.css +++ b/css/style.css @@ -65,7 +65,7 @@ img { slide-deck div { height: 80vh; padding: 1em; - background: lightgray; + border: solid 2px lightgray; } @media only screen and (max-width: 960px) { @@ -93,6 +93,6 @@ slide-controls { float: left; } -nextslide { +nextslide, transition { display: none; } \ No newline at end of file diff --git a/index.html b/index.html index 735cc01..f7e1729 100644 --- a/index.html +++ b/index.html @@ -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';"> +
diff --git a/js/animator.js b/js/animator.js new file mode 100644 index 0000000..ca3d2c2 --- /dev/null +++ b/js/animator.js @@ -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); + } +} \ No newline at end of file diff --git a/js/navigator.js b/js/navigator.js index ff74cd6..c6bbe68 100644 --- a/js/navigator.js +++ b/js/navigator.js @@ -1,10 +1,12 @@ import { loadSlides } from "./slideLoader.js" import { Router } from "./router.js" +import { Animator } from "./animator.js" class Navigator extends HTMLElement { constructor() { super(); + this._animator = new Animator(); this._router = new Router(); this._route = this._router.getRoute(); this.slidesChangedEvent = new CustomEvent("slideschanged", { @@ -61,6 +63,9 @@ class Navigator extends HTMLElement { } jumpTo(slideIdx) { + if (this._animator.transitioning) { + return; + } if (slideIdx >= 0 && slideIdx < this.totalSlides) { this._currentIndex = slideIdx; this.innerHTML = ''; @@ -68,12 +73,23 @@ class Navigator extends HTMLElement { this._router.setRoute(slideIdx+1); this._route = this._router.getRoute(); this.dispatchEvent(this.slidesChangedEvent); + if (this._animator.animationReady) { + this._animator.endAnimation(this.querySelector("div")); + } } } next() { 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); + } } } diff --git a/js/slide.js b/js/slide.js index 3445e6a..74260e3 100644 --- a/js/slide.js +++ b/js/slide.js @@ -5,6 +5,13 @@ export class Slide { this._html = document.createElement('div'); this._html.innerHTML = text; 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"); if (hasNext.length > 0) { this._nextSlideName = hasNext[0].innerText; @@ -14,6 +21,10 @@ export class Slide { } } + get transition() { + return this._transition; + } + get title() { return this._title; } diff --git a/slides/001-title.html b/slides/001-title.html index cc660e3..f77793c 100644 --- a/slides/001-title.html +++ b/slides/001-title.html @@ -2,4 +2,5 @@