From: Andrew Lorimer Date: Wed, 15 Jun 2022 11:01:32 +0000 (+1000) Subject: initial commit X-Git-Url: https://git.lorimer.id.au/simple-slideshow.git/diff_plain/a6c556585237625b64a6e234ad5b2c1402b39df2?ds=sidebyside initial commit --- a6c556585237625b64a6e234ad5b2c1402b39df2 diff --git a/slideshow.css b/slideshow.css new file mode 100644 index 0000000..552d5fb --- /dev/null +++ b/slideshow.css @@ -0,0 +1,135 @@ +:root { + --sl-cap: 20px; + --sl-dots: 10px; + --sl-transition: 0.5s; +} + +div.slideshow { + max-width: 1000px; + position: relative; + margin: auto; +} + + +/* + * Slides + */ + +figure.slide:first-child { + /* Position the first slide relatively to set the height (others are + * positioned absolutely to allow overlapping) */ + position: relative; +} + +figure.slide { + /* Position slides absolutely to allow overlapping */ + position: absolute; + top: 0; + left: 0; + margin: 0; + /* Slides start at 0 opacity */ + opacity: 0; + /* Fade out duration is double the fade in duration (approximates a cross + * dissolve) */ + transition: opacity calc(2 * var(--sl-transition)) ease; + -webkit-transition: opacity calc(2 * var(--sl-transition)) ease; + -moz-transition: opacity calc(2 * var(--sl-transition)) ease; + z-index: -1; +} + +figure.slide.active { + opacity: 1; + z-index: 0; + /*display: block;*/ + transition: opacity 1s ease; + -webkit-transition: opacity 1s ease; + -moz-transition: opacity 1s ease; +} + +figure.slide *, +div.slideshow div#controls { + width: 100%; +} + +figure.slide figcaption { + height: var(--sl-cap); + text-align: center; +} + + +/* + * Buttons + */ + +#prev, #next, #state { + cursor: pointer; + font-weight: bold; + font-size: 1.5em; + user-select: none; + opacity: 0; + transition: 0.2s ease; + position: absolute; + color: white; +} + +#prev, #next { + top: calc(50% - calc(var(--sl-cap) + var(--sl-dots) + 50px) / 2); + width: auto; + padding: 16px; + border-radius: 0 3px 3px 0; +} + +#state { + width: 1.5em; + height: 1.5em; + text-align: center; + font-family: monospace; + top: 15px; + right: 15px; + padding: 4px; + border-radius: 3px; +} + +#next { + /* Position next button on right */ + right: 0; + border-radius: 3px 0 0 3px; +} + +div.slideshow:hover #prev, +div.slideshow:hover #next, +div.slideshow:hover #state { + /* Show buttons on slideshow hover */ + opacity: 100; + background-color: rgba(0,0,0,0.3); +} + +#prev:hover, #next:hover, #state:hover { + /* Button hover */ + background-color: rgba(0,0,0,0.8) !important; +} + + +/* + * Dot controls/indicators + */ + +div.slideshow div#controls { + text-align: center; +} + +div.slideshow div#controls span { + cursor: pointer; + height: var(--sl-dots); + width: var(--sl-dots); + margin: 0 2px; + background-color: #bbb; + border-radius: 50%; + display: inline-block; + transition: background-color 0.6s ease; +} + +div#controls span.active, +div#controls span:hover { + background-color: #717171 !important; +} diff --git a/slideshow.html b/slideshow.html new file mode 100644 index 0000000..a581b1f --- /dev/null +++ b/slideshow.html @@ -0,0 +1,41 @@ + + + + + + + + +
+ +
+ +
This is a long caption yeah yeah yeah
+
+ +
+ +
Shorter caption
+
+ +
+ +
Caption 3
+
+ + + + ⏸︎ + +
+ + + +
+ +
+ + + + + diff --git a/slideshow.js b/slideshow.js new file mode 100644 index 0000000..f73a888 --- /dev/null +++ b/slideshow.js @@ -0,0 +1,96 @@ +const INTERVAL = 2000; +const STATE_PAUSE = "⏸︎"; +const STATE_PLAY = "⏵︎"; + +// Start at -1 - the recursive function playSlideshow() increases this to 0 +// on page load +let currentSlide = -1; + +// Elements +let slides = document.getElementsByClassName("slide"); +let dots = document.getElementsByClassName("dot"); +let stateBtn = document.getElementById("state"); + +// Global state +let maxIndex = slides.length - 1; +var timeout; +var paused = false; + +// Start the slideshow +playSlideshow(); + +// Recursive function that advances the slide and then calls itself with a +// delay +function playSlideshow() { + nextSlide(); + timeout = setTimeout(playSlideshow, INTERVAL); +} + +// Change the slide to a given index +function setSlide(slide) { + + if (slide < 0 || slide > maxIndex) { + console.log("Attempted to change to slide outside range"); + return; + } + + // Remove active class from figure and dot + for (i = 0; i <= maxIndex; i++) { + slides[i].className = slides[i].className.replace(" active", ""); + dots[i].className = dots[i].className.replace(" active", ""); + } + + // Add active class to figure and dot + slides[slide].className += " active"; + dots[slide].className += " active"; + + currentSlide = slide; +} + +function nextSlide() { + // Go to the next slide + if (currentSlide == maxIndex) { + setSlide(0); + } + else { + setSlide(currentSlide + 1); + } +} + +function prevSlide() { + // Go to the previous slide + if (currentSlide == 0) { + setSlide(maxIndex); + } + else { + setSlide(currentSlide - 1); + } +} + +function mouseEnter() { + // Pause the slideshow + clearTimeout(timeout); + timeout = null; +} + +function mouseLeave() { + // Start the slideshow if not manually paused + if (!paused && timeout == null) { + timeout = setTimeout(playSlideshow, INTERVAL); + } +} + +function changeState() { + if (paused) { + // Play immediately despite mouseover + stateBtn.innerHTML = STATE_PAUSE; + timeout = setTimeout(playSlideshow, INTERVAL); + } + else { + // Pause until user presses play again + clearTimeout(timeout); // make sure timer is stopped + timeout = null; + stateBtn.innerHTML = STATE_PLAY; + } + paused = !paused; +} diff --git a/test-img/1.jpg b/test-img/1.jpg new file mode 100644 index 0000000..bab2280 Binary files /dev/null and b/test-img/1.jpg differ diff --git a/test-img/2.jpg b/test-img/2.jpg new file mode 100644 index 0000000..b3f3d4c Binary files /dev/null and b/test-img/2.jpg differ diff --git a/test-img/3.jpg b/test-img/3.jpg new file mode 100644 index 0000000..f93f45c Binary files /dev/null and b/test-img/3.jpg differ