lightbox/
reset.css
slides.css
slides.html
slides.js
<div class="main"> <div class="welcome"> <h1>Welcome to an amazing carousel!</h1> <p>This is an example of a nice touch interface</p> </div> <div class="carousel"> <ul> <li> <a href="http://www.flickr.com/photos/protohiro/6664939239/in/photostream/"> <img data-full-height="427" data-full-width="640" src="http://farm8.staticflickr.com/7142/6664939239_7a6c846ec9_s.jpg"> </a> </li> <li> <a href="http://www.flickr.com/photos/protohiro/6664957519/in/photostream"> <img data-full-height="424" data-full-width="640" src="http://farm8.staticflickr.com/7001/6664957519_582f716e38_s.jpg"> </a> </li> <li> <a href="http://www.flickr.com/photos/protohiro/6664955215/in/photostream"> <img data-full-height="640" data-full-width="427" src="http://farm8.staticflickr.com/7019/6664955215_d49f2a0b18_s.jpg"> </a> </li> <li> <a href="http://www.flickr.com/photos/protohiro/6664952047/in/photostream"> <img data-full-height="426" data-full-width="640" src="http://farm8.staticflickr.com/7017/6664952047_6955870ecb_s.jpg"> </a> </li> <li> <a href="http://www.flickr.com/photos/protohiro/6664948305/in/photostream"> <img data-full-height="428" data-full-width="640" src="http://farm8.staticflickr.com/7149/6664948305_fb5a6276e5_s.jpg"> </a> </li> </ul> </div> </div> </body> <script src="zepto.min.js" type="text/javascript" charset="utf-8"></script> <script src="slides.js" type="text/javascript" charset="utf-8"></script> <script type="text/javascript" charset="utf-8"> //this code initializes the lightbox and shows it when the user //clicks on a slide $(document).ready(function(){ var lightbox = new saw.Lightbox('.carousel'); $(document).on('click', 'a', function(e){ e.preventDefault(); lightbox.show(this.href); }); }); </script> </html>
html { background: #f1eee4; font-family: georgia; color: #7d7f94; } h1 { color: #ba4a00; } .welcome { text-align: center; text-shadow: 1px 1px 1px #fff; } .welcome h1 { font-size: 20px; font-weight: bold; } .welcome { -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */ -moz-box-sizing: border-box; /* Firefox, other Gecko */ box-sizing: border-box; /* Opera/IE 8+ */ margin:5px; padding:10px; box-shadow: 2px 2px 5px rgba(0,0,0,0.5); border-radius: 5px; } .carousel { margin:5px; } .carousel ul li { height: 70px; width: 70px; margin: 5px; overflow: hidden; display: block; float: left; border-radius: 5px; box-shadow: 1px 1px 2px rgba(0,0,0,0.5), -1px -1px 2px rgba(255,255,255,1); }
function prefixify(str) { var ua = window.navigator.userAgent; if(ua.indexOf('WebKit') !== -1) { return '-webkit-' + str; } if(ua.indexOf('Opera') !== -1) { return '-o-' + str; } if(ua.indexOf('Gecko') !== -1) { return '-moz-' + str; } return str; } function setPosition(node, left) { // node.css('left', left +'px'); node.css(prefixify('transform'), "translate3d("+left+"px, 0, 0)"); } function addTransitions(node){ node.css(prefixify('transition'), prefixify('transform') + ' .25s ease-in-out'); node[0].addEventListener('webkitTransitionEnd', function(e){ window.setTimeout(function(){ $(e.target).css('-webkit-transition', 'none'); }, 0) }) } function cleanTransitions(node){ node.css(prefixify('transition'), 'none'); }
//clean namespacing window.saw = (function($){ //the lightbox constructor function Lightbox (selector) { var container_node = $(selector), wrapper, chromeBuilt, currentSlide = 0, slideData =[], boundingBox = [0,0], slideMap = {}; function init(){ //init function } return { show: show, hide: hide }; } return { Lightbox:Lightbox }; }($));
function init(){ var slides = container_node.find('li'); slides.each(function(i, el){ var thisSlide = {}, thisImg = $(el).find('img'); thisSlide.url = thisImg.attr('src'); thisSlide.height = thisImg.attr('data-full-height'); thisSlide.width = thisImg.attr('data-full-width'); thisSlide.link = $(el).find('a').attr('href'); //push the slide info into the slideData array while recording the array index in the slideMap object. slideMap[thisSlide.link] = slideData.push(thisSlide) - 1; }); }
//this is the function called from the inline script function show(startSlide){ if(!chromeBuilt){ buildChrome(); attachEvents(); } wrapper.show(); //keep track of the viewport size boundingBox = [ window.innerWidth, window.innerHeight ]; goTo(slideMap[startSlide]); }
var wrapperTemplate = function(){ return '<div class="slidewrap">'+ '<div class="controls"><a class="prev" href="#">prev</a> | <a class="next" href="#">next</a></div>'+ '</div>'; } function buildChrome(){ wrapper = $(wrapperTemplate()).addClass('slidewrap'); $('body').append(wrapper); chromeBuilt = true; }
function handleClicks(e){ e.preventDefault(); var targ = $(e.target); if(targ.hasClass('next')) { goTo(currentSlide + 1); } else if(targ.hasClass('prev')){ goTo(currentSlide - 1); } else { hide(); } } function attachEvents(){ wrapper.on('click', handleClicks, false); }
//for the slides, takes a "slide" object function slideTemplate(slide){ return '<div class="slide"><span>'+slide.id+'</span><div style="background-image:url('+slide.url.replace(/_s|_q/, '_z')+')"></div></div>'; }
function buildSlide (slideNum) { var thisSlide, s, img, scaleFactor = 1, w, h; if(!slideData[slideNum] || slideData[slideNum].node){ return false; } var thisSlide = slideData[slideNum]; var s = $(slideTemplate(thisSlide)); var img = s.children('div'); //image is too big! scale it! if(thisSlide.width > boundingBox[0] || thisSlide.height > boundingBox[1]){ if(thisSlide.width > thisSlide.height) { scaleFactor = boundingBox[0]/thisSlide.width; } else { scaleFactor = boundingBox[1]/thisSlide.height; } w = Math.round(thisSlide.width * scaleFactor); h = Math.round(thisSlide.height * scaleFactor); img.css('height', h + 'px'); img.css('width', w + 'px'); }else{ img.css('height', thisSlide.height + 'px'); img.css('width', thisSlide.width + 'px'); } thisSlide.node = s; wrapper.append(s); //put the new slide into the start poisition setPosition(s, boundingBox[0]); return s; }
function goTo(slideNum){ var thisSlide; //if the slide we are looking for doesn't exist, lets just go //back to the current slide. This has the handy effect of providing //"snap back" feedback when gesturing, the slide will just animate //back into position if(!slideData[slideNum]){ return; } thisSlide = slideData[slideNum]; //build adjacent slides buildSlide(slideNum); buildSlide(slideNum + 1); buildSlide(slideNum - 1); //make it fancy addTransitions(thisSlide.node); //put the current slide into position setPosition(thisSlide.node, 0); //slide the adjacent slides away if(slideData[slideNum - 1] && slideData[slideNum-1].node){ addTransitions(slideData[slideNum - 1 ].node); setPosition( slideData[slideNum - 1 ].node , (0 - boundingBox[0]) ); } if(slideData[slideNum + 1] && slideData[slideNum + 1].node){ addTransitions(slideData[slideNum + 1 ].node); setPosition(slideData[slideNum + 1 ].node, boundingBox[0] ); } //update the state currentSlide = slideNum; }
function attachTouchEvents() { var bd = document.querySelector('html'); bd.addEventListener('touchmove', handleTouchEvents); bd.addEventListener('touchstart', handleTouchEvents); bd.addEventListener('touchend', handleTouchEvents); }
var startPos, endPos, lastPos;
function handleTouchEvents(e){ var direction = 0; //you could also use a switch statement if(e.type == 'touchstart') { } else if(e.type == 'touchmove' ) { } else if(e.type == 'touchend) { }
if(e.type == 'touchstart') { //record the start clientX startPos = e.touches[0].clientX; //lastPos is startPos at the beginning lastPos = startPos; //we'll keep track of direction as a signed integer. // -1 is left, 1 is right and 0 is staying still direction = 0; //now we clean off the transtions if(slideData[currentSlide] && slideData[currentSlide].node){ cleanTransitions(slideData[currentSlide].node); } if(slideData[currentSlide + 1] && slideData[currentSlide + 1].node){ cleanTransitions(slideData[currentSlide + 1].node); } if(slideData[currentSlide - 1] && slideData[currentSlide -1].node){ cleanTransitions(slideData[currentSlide -1].node); } } else if(e.type == 'touchmove' ) {
}else if(e.type == 'touchmove'){ e.preventDefault(); //figure out the direction if(lastPos > startPos){ direction = -1; }else{ direction = 1; } //make sure the slide exists if(slideData[currentSlide]){ //move the current slide into position setPosition(slideData[currentSlide].node, e.touches[0].clientX - startPos); //make sure the next or previous slide exits if(direction !== 0 && slideData[currentSlide + direction]){ //move the next or previous slide. if(direction < 0){ //I want to move the next slide into the right position, which is the same as the //current slide, minus the width of the viewport (each slide is as wide as the viewport) setPosition(slideData[currentSlide + direction].node, (e.touches[0].clientX - startPos) - boundingBox[0]); }else if(direction > 0){ setPosition(slideData[currentSlide + direction].node, (e.touches[0].clientX - startPos) + boundingBox[0]); } } } //save the last position, we need it for touch end lastPos = e.touches[0].clientX; }else if(e.type == 'touchend'){
}else if(e.type == 'touchend'){ //figure out if we have moved left or right beyond a threshold //(50 pixels in this case) if(lastPos - startPos > 50){ goTo(currentSlide-1); } else if(lastPos - startPos < -50){ goTo(currentSlide+1); }else{ //we are not advancing, so we need to "snap back" to the previous position addTransitions(slideData[currentSlide].node); setPosition(slideData[currentSlide].node, 0); if(slideData[currentSlide + 1] && slideData[currentSlide + 1].node){ addTransitions(slideData[currentSlide + 1]); setPosition(slideData[currentSlide + 1].node, boundingBox[0]); } if(slideData[currentSlide - 1] && slideData[currentSlide - 1].node){ addTransitions(slideData[currentSlide - 1]); setPosition(slideData[currentSlide - 1].node, 0 - boundingBox[0]); } } }
Source: https://habr.com/ru/post/143211/
All Articles