Last active
September 12, 2017 07:46
-
-
Save Dinir/a5c912650366d49f75c0592f4fdb7434 to your computer and use it in GitHub Desktop.
adds a fullscreen slideshow on a webpage
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * @typedef {object} stoppableTimer | |
| * @desc 일시정지가 가능한 인터벌 타이머입니다. | |
| * @method stop 타이머를 멈춥니다. | |
| * @method start 타이머를 시작합니다. 새로운 타이머 값을 줄 수 있습니다. | |
| * @method reset 타이머를 리셋합니다. 새로운 타이머 값을 줄 수 있습니다. | |
| */ | |
| /** | |
| * 일시정지가 가능한 인터벌 타이머를 만듭니다. | |
| * 지정해준 시간이 지날 때마다 생성 시에 지정해준 함수를 실행합니다. | |
| * | |
| * @class | |
| * @param {function} fn 실행할 함수 | |
| * @param {number} t 실행할 시간 | |
| * @returns {stoppableTimer} | |
| */ | |
| var stoppableTimer = function(fn, t) { | |
| var timer = setInterval(fn, t); | |
| return { | |
| stop: function() { | |
| if(timer) { | |
| clearInterval(timer); | |
| timer = null; | |
| } | |
| return this; | |
| }, | |
| start: function(newT) { | |
| if(!timer) { | |
| t = newT?newT:t; | |
| timer = setInterval(fn, t); | |
| } | |
| return this; | |
| }, | |
| reset: function(newT) { | |
| return this.stop().start(newT); | |
| } | |
| } | |
| } | |
| /** | |
| * resize가 발생할 때마다 >66ms 이후에 `handler`를 실행합니다. | |
| * 큐에 실행 스케쥴이 잡혀있을 경우 실행하지 않습니다. | |
| * @param {function} handler | |
| */ | |
| var resizeHandler = function(handler) { | |
| window.addEventListener("resize", resizeThrottler, false); | |
| var resizeTimeout; | |
| function resizeThrottler() { | |
| if ( !resizeTimeout ) { | |
| resizeTimeout = setTimeout(function() { | |
| resizeTimeout = null; | |
| handler(); | |
| }, 66); | |
| } | |
| } | |
| handler(); | |
| } | |
| /** | |
| * @typedef {Object} fullscreenSlideshow | |
| * @desc 슬라이드쇼 조작에 필요한 메소드를 담습니다. | |
| * @method changePlayState | |
| * 슬라이드쇼 재생 여부를 바꿉니다. | |
| * @method arrange | |
| * 현재 창 크기에 맞춰 슬라이드 이미지의 위치를 조절해, 창의 한 가운데에 오도록 합니다. | |
| * @method on | |
| * 슬라이드쇼 화면을 현재 창에 띄웁니다. | |
| * @method off | |
| * 슬라이드쇼 화면을 현재 창에서 감춥니다. | |
| * @method play | |
| * 슬라이드쇼 재생을 시작합니다. | |
| * @method stop | |
| * 슬라이드쇼 재생을 멈춥니다. | |
| * @method move | |
| * 지정한 슬라이드가 화면에 나타나도록 합니다. | |
| */ | |
| /** | |
| * 창 전체에 나타나는 슬라이드쇼를 만듭니다. | |
| * @class | |
| * @param {string[][]} images | |
| * 슬라이드쇼에서 표시할 이미지의 주소와 설명 문구를 담는 배열입니다. | |
| * [[src, alt], [src, alt], ...] 의 형태를 받습니다. | |
| * @param {number} interval 각 슬라이드를 보여줄 시간을 설정합니다. | |
| * @param {number} transitionDuration 슬라이드 전환에 걸리는 시간을 설정합니다. | |
| * @returns {fullscreenSlideshow} | |
| */ | |
| var fullscreenSlideshow = function(images, interval, transitionDuration) { | |
| // 화면 전체에 표시할 슬라이드 쇼의 컨테이너를 만듭니다. | |
| var container = document.createElement("div"); | |
| container.id = "fullscreenSlideshowContainer"; | |
| /** | |
| * X 자 모양을 만듭니다. | |
| * CSS: `/kor/css/index.css`, `#fullscreenSlideshowContainer .close` | |
| */ | |
| var close = (function() { | |
| var dom = document.createElement("div"); | |
| dom.className = "close"; | |
| var x1 = document.createElement("span"); | |
| var x2 = document.createElement("span"); | |
| dom.appendChild(x1); | |
| dom.appendChild(x2); | |
| return dom; | |
| })(); | |
| container.appendChild(close); | |
| /** | |
| * @typedef {object} slides | |
| * @desc 슬라이드쇼에 쓰일 이미지와 이에 접근할 수 있는 프로퍼티를 담습니다. | |
| * @property {HTMLElement} dom 이미지를 담은 요소입니다. | |
| * @property {array} array 이미지를 담은 img 요소를 모아둔 어레이입니다. | |
| * @property {function} order | |
| * 화면에 표시되는 이미지의 순서를 구하거나 지정할 수 있는 함수입니다. | |
| * 순서는 0부터 시작되며 순서 값에 따라 슬라이드 내의 이미지 표시 위치를 | |
| * `.style.right`를 설정해 바꿉니다. | |
| */ | |
| /** | |
| * 이미지를 담을 요소를 만듭니다. | |
| * | |
| * @type {slides} | |
| */ | |
| var slides = (function() { | |
| var doms = document.createElement("div"); | |
| var array = []; | |
| // 이미지를 담을 요소를 만듭니다. | |
| doms.className = "slides"; | |
| doms.style.width = images.length * 100 + "%"; | |
| doms.style.right = "-100%"; | |
| // 만든 요소 안에 이미지를 넣습니다. | |
| images.map(function(v) { | |
| var dom = document.createElement("img"); | |
| dom.className = "slide"; | |
| dom.src = v[0]; | |
| dom.alt = v[1]; | |
| dom.style.width = 100/images.length + "%"; | |
| doms.appendChild(dom); | |
| array.push(dom); | |
| }); | |
| /** | |
| * 순서 값을 받아 이를 실제 존재하는 순서 값으로 바꿔서 반환합니다. | |
| * | |
| * @param {number} order | |
| * @param {number} length | |
| * @returns {number} | |
| */ | |
| var wrapOrder = function(order, length) { | |
| if(order >= length || order < 0) { | |
| var n = order % length; | |
| if (n < 0) n += length; | |
| return n; | |
| } else | |
| return order; | |
| } | |
| return { | |
| dom: doms, | |
| array: array, | |
| /** | |
| * 화면에 표시되는 이미지의 순서를 구하거나 지정합니다. | |
| * 인자를 넣지 않을 경우 현재 순서를 반환하고, | |
| * 인자를 넣을 경우 이를 실제 존재하는 순서 값으로 바꿔서 적용합니다. | |
| * @param {number} order | |
| * @param {boolean} force 참 값을 넣어주면 실제 존재하지 않는 순서를 적용합니다. | |
| * @returns {number|undefined} | |
| */ | |
| order: function(order, force) { | |
| if(typeof order !== "undefined") { | |
| doms.style.right = | |
| (force? order: wrapOrder(order, images.length)) * 100 + "%"; | |
| } else { | |
| return parseInt(doms.style.right)/100; | |
| } | |
| } | |
| }; | |
| })(); | |
| container.appendChild(slides.dom); | |
| /** | |
| * @typedef {object} buttons | |
| * @desc 슬라이드쇼에서 사용할 버튼 요소들입니다. | |
| * @property {HTMLElement} dom 버튼 요소들을 담은 요소입니다. | |
| * @property {HTMLElement} play 재생 버튼입니다. | |
| * @property {HTMLElement} stop 정지 버튼입니다. | |
| * @property {HTMLElement} slide00, slide01, ... 각 슬라이드에 대한 버튼입니다. | |
| */ | |
| /** | |
| * 슬라이드쇼에 표시될 버튼을 만들고 이를 컨테이너에 담은 뒤, | |
| * 버튼들을 모아 오브젝트 형태로 반환합니다. | |
| * | |
| * @type {buttons} | |
| */ | |
| var navigator = (function() { | |
| var dom = document.createElement("div"); | |
| dom.className = "nav"; | |
| var play = document.createElement("div"); | |
| play.className = "flowButton play"; | |
| dom.appendChild(play); | |
| var stop = document.createElement("div"); | |
| stop.className = "flowButton stop"; | |
| dom.appendChild(stop); | |
| var buttons = { | |
| dom: dom, | |
| play: play, | |
| stop: stop | |
| }; | |
| images.map(function(v,i) { | |
| var slide = document.createElement("a"); | |
| slide.className = "slideButton slide"+("0"+i).substr(-2); | |
| slide.innerHTML = "●"; | |
| dom.appendChild(slide); | |
| buttons["slide"+("0"+i).substr(-2)] = slide; | |
| }); | |
| return buttons; | |
| })(); | |
| container.appendChild(navigator.dom); | |
| document.body.appendChild(container); | |
| var playState = false; | |
| var controller = { | |
| changePlayState: function(setValue) { | |
| if(typeof setValue === "boolean") | |
| playState = setValue; | |
| else if(typeof setValue === "undefined") | |
| playState = !playState; | |
| }, | |
| arrange: function() { | |
| var screenSize = { | |
| x: window.innerWidth, | |
| y: window.innerHeight | |
| }; | |
| slides.array.map(function(v) { | |
| if(v.getBoundingClientRect().height) { | |
| var top = ( screenSize.y - v.getBoundingClientRect().height ) / 2; | |
| v.style.top = top + "px"; | |
| } else | |
| v.style.top = 0; | |
| }); | |
| return this; | |
| }, | |
| on: function() { | |
| controller.move(0, true); | |
| container.style.display = "block"; | |
| var show = setInterval(function(){ | |
| container.style.left = "0"; | |
| clearInterval(show); | |
| }, 16); | |
| controller.play(); | |
| controller.arrange(); | |
| return this; | |
| }, | |
| off: function() { | |
| container.style.left = "100%"; | |
| var hide = setInterval(function(){ | |
| container.style.display = "none"; | |
| clearInterval(hide); | |
| }, 500); | |
| controller.stop(); | |
| return this; | |
| }, | |
| play: function() { | |
| timer.reset(); | |
| controller.changePlayState(true); | |
| if(navigator.play.className.substr(-3) !== " on") { | |
| navigator.play.className += " on"; | |
| navigator.stop.className = navigator.stop.className.replace(" on", ""); | |
| } | |
| return this; | |
| }, | |
| stop: function() { | |
| timer.stop(); | |
| controller.changePlayState(false); | |
| if(navigator.stop.className.substr(-3) !== " on") { | |
| navigator.stop.className += " on"; | |
| navigator.play.className = navigator.play.className.replace(" on", ""); | |
| } | |
| return this; | |
| }, | |
| move: function(order, force) { | |
| if(parseInt(order) !== slides.order()) { | |
| var o = typeof order !== "undefined"? order: slides.order()+1; | |
| if (force) | |
| slides.dom.style.transitionDuration = "0s"; | |
| slides.order(o, force); | |
| slides.dom.style.transitionDuration = transitionDuration + "s"; | |
| if(playState) | |
| controller.play(); | |
| var oString = ("0" + slides.order()).substr(-2); | |
| for (var button in navigator) { | |
| if (button.indexOf("slide") !== -1) { | |
| if (navigator[button].className.substr(-2) === oString) | |
| navigator[button].className += " on"; | |
| else | |
| navigator[button].className = | |
| navigator[button].className.replace(" on", ""); | |
| } | |
| } | |
| } | |
| return this; | |
| }, | |
| /*inspect: function() { | |
| return { | |
| cont: container, | |
| close: close, | |
| slides: { | |
| dom: slides.dom, | |
| array: slides.array, | |
| move: controller.move, | |
| timer: timer | |
| } | |
| } | |
| }*/ | |
| } | |
| var timer = new stoppableTimer(controller.move, interval); | |
| timer.stop(); | |
| close.addEventListener("click", function() { | |
| controller. | |
| off(). | |
| move(-1, true); | |
| }); | |
| navigator.dom.addEventListener("click", function(e) { | |
| switch(e.target.className.split(" ")[1]) { | |
| case "play": | |
| controller.play(); | |
| break; | |
| case "stop": | |
| controller.stop(); | |
| break; | |
| default: | |
| if(e.target.className.split(" ")[0] === "slideButton") { | |
| controller.move(e.target.className.split(" ")[1].substr(-2)); | |
| } | |
| break; | |
| } | |
| }); | |
| return controller; | |
| }; | |
| var slideshow = new fullscreenSlideshow( | |
| [ | |
| ['/kor/images/01.jpg','alt1'], | |
| ['/kor/images/02.jpg','alt2'], | |
| ['/kor/images/03.jpg','alt3'], | |
| ['/kor/images/04.jpg','alt4'], | |
| ], | |
| 5000, | |
| .3 | |
| ); | |
| var fullscreenSlideshowAnchor = document.querySelector("#slideshowLink"); | |
| fullscreenSlideshowAnchor.addEventListener("click", slideshow.on); | |
| resizeHandler(slideshow.arrange); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #fullscreenSlideshowContainer { | |
| width: 100%; | |
| height: 100%; | |
| position: fixed; | |
| top: 0; | |
| left: 100%; | |
| overflow: hidden; | |
| transition: left .3s ease-in-out; | |
| background: url(/kor/images/bgp.gif) left top repeat; | |
| z-index: 50; | |
| display: none; | |
| .close { | |
| display: block; | |
| width: 8em; | |
| height: 8em; | |
| position: absolute; | |
| top: 0; | |
| right: 0; | |
| background-color: rgba(255, 255, 255, .5); | |
| cursor: pointer; | |
| z-index: 2; | |
| span { | |
| display: inline-block; | |
| width: 8em; | |
| border: 1px solid rgba(0, 0, 0, .5); | |
| position: absolute; | |
| top: 3.8em; | |
| &:nth-child(1) { | |
| transform: rotate(45deg); | |
| } | |
| &:nth-child(2) { | |
| transform: rotate(-45deg); | |
| } | |
| } | |
| } | |
| .slides { | |
| position: relative; | |
| /*right: -100%;*/ | |
| transition: right .0s ease-in-out; | |
| .slide { | |
| position: relative; | |
| } | |
| } | |
| .nav { | |
| position: fixed; | |
| top: 22px; | |
| width: 100%; | |
| text-align: center; | |
| z-index: 1; | |
| .flowButton, | |
| .slideButton { | |
| cursor: pointer; | |
| margin-right: 6.5px; | |
| } | |
| .flowButton { | |
| display: inline-block; | |
| width: 13px; | |
| height: 15px; | |
| &.play { | |
| background: url(/kor/images/play.png); | |
| &.on { | |
| background: url(/kor/images/play_on.png); | |
| } | |
| } | |
| &.stop { | |
| background: url(/kor/images/stop.png); | |
| &.on { | |
| background: url(/kor/images/stop_on.png); | |
| } | |
| } | |
| } | |
| .slideButton { | |
| position: relative; | |
| top: -2.5px; | |
| color: #c6c6c6; | |
| &.on { | |
| color: #bbe2a8; | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment