Wavescroll是一款基于GSAP的响应式全屏背景图片jQuery幻灯片插件。该幻灯片插件支持鼠标拖动、鼠标滚动和移动触摸事件,可以制作出炫酷的波浪滚动切换效果。
该幻灯片插件主要使用的技术有:jQuery, CSS3, requestAnimationFrame 和 GSAP的TweenMax.js。
使用方法
HTML结构
该jQuery幻灯片的HTML结构如下:
< div class = "ws-pages" > < div class = "ws-bgs" > < div class = "ws-bg" ></ div > < div class = "ws-bg" ></ div > < div class = "ws-bg" ></ div > < div class = "ws-bg" ></ div > < div class = "ws-bg" ></ div > </ div > < div class = "ws-text" > < h2 class = "ws-text__heading" > < span >This is Slide 1</ span > </ h2 > < h2 class = "ws-text__heading" > < span >This is Slide 2</ span > </ h2 > < h2 class = "ws-text__heading" > < span >This is Slide 3</ span > </ h2 > < h2 class = "ws-text__heading" > < span >This is Slide 4</ span > </ h2 > < h2 class = "ws-text__heading" > < span >This is Slide 5</ span > < span >The end</ span > </ h2 > </ div > </ div > |
CSS样式
该幻灯片的主要CSS样式如下:所有幻灯片都通过background-size: cover;
来设置为全屏模式。.ws-bg__part
是制作百叶窗效果的每一个窗叶。每个幻灯片slide分为24个窗叶,分别使用使用ws-bg__part-n:after
伪元素来制作。
.ws-pages { overflow : hidden ; position : relative ; height : 100% ; } .ws-bgs { position : relative ; height : 100% ; } .ws-bg { height : 100% ; background-size : cover ; background-position : center center ; } .ws-pages.s--ready .ws-bg { background : none !important ; } .ws-bg:after { content : "" ; display : table; clear : both ; } .ws-bg__part { overflow : hidden ; position : relative ; float : left ; width : 4.16667% ; height : 100% ; background-size : cover ; background-position : center center ; cursor : -webkit- grab ; cursor : grab ; -webkit- user-select : none ; -moz- user-select : none ; -ms- user-select : none ; user-select : none ; } .ws-bg__part:after { content : "" ; position : absolute ; top : 0 ; width : 100 vw; height : 100% ; background : inherit; } .ws-bg__part -1: after { left : 0 vw; } .ws-bg__part -2: after { left : -4.16667 vw; } .ws-bg__part -3: after { left : -8.33333 vw; } .ws-bg__part -4: after { left : -12.5 vw; } .ws-bg__part -5: after { left : -16.66667 vw; } .ws-bg__part -6: after { left : -20.83333 vw; } .ws-bg__part -7: after { left : -25 vw; } .ws-bg__part -8: after { left : -29.16667 vw; } .ws-bg__part -9: after { left : -33.33333 vw; } .ws-bg__part -10: after { left : -37.5 vw; } .ws-bg__part -11: after { left : -41.66667 vw; } .ws-bg__part -12: after { left : -45.83333 vw; } .ws-bg__part -13: after { left : -50 vw; } .ws-bg__part -14: after { left : -54.16667 vw; } .ws-bg__part -15: after { left : -58.33333 vw; } .ws-bg__part -16: after { left : -62.5 vw; } .ws-bg__part -17: after { left : -66.66667 vw; } .ws-bg__part -18: after { left : -70.83333 vw; } .ws-bg__part -19: after { left : -75 vw; } .ws-bg__part -20: after { left : -79.16667 vw; } .ws-bg__part -21: after { left : -83.33333 vw; } .ws-bg__part -22: after { left : -87.5 vw; } .ws-bg__part -23: after { left : -91.66667 vw; } .ws-bg__part -24: after { left : -95.83333 vw; } |
幻灯片的图片使用背景图片来制作。
.ws-bg:nth-child( 1 ) { background-image : url ( 1 .jpg); } .ws-bg:nth-child( 1 ) .ws-bg__part { 1 .jpg); } .ws-bg:nth-child( 2 ) { background-image : url ( 2 .jpg); } .ws-bg:nth-child( 2 ) .ws-bg__part { background-image : url ( 2 .jpg); } .ws-bg:nth-child( 3 ) { background-image : url ( 3 .jpg); } .ws-bg:nth-child( 3 ) .ws-bg__part { background-image : url ( 3 .jpg); } .ws-bg:nth-child( 4 ) { background-image : url ( 4 .jpg); } .ws-bg:nth-child( 4 ) .ws-bg__part { background-image : url ( 4 .jpg); } .ws-bg:nth-child( 5 ) { background-image : url ( 5 .jpg); } .ws-bg:nth-child( 5 ) .ws-bg__part { background-image : url ( 5 .jpg); } |
初始化插件
Wavescroll是基于GSAP来制作的,所以在使用时要在页面中引入jQuery和TweenMax.js文件。
< script src = "/path/to/jquery.min.js" ></ script > < script src = "/path/to/TweenMax.min.js" ></ script > |
Wavescroll幻灯片的核心js代码如下:
window.requestAnimFrame = ( function () { return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || function (callback){ window.setTimeout(callback, 1000 / 60); }; })(); function rafThrottle(fn) { var busy = false ; return function () { if (busy) return ; busy = true ; fn.apply( this , arguments); requestAnimFrame( function () { busy = false ; }); }; }; $(document).ready( function () { var $wsPages = $( ".ws-pages" ); var $headings = $( ".ws-text__heading" ); var bgParts = 24; var staggerVal = 65; var staggerStep = 4; var textH = $( ".ws-text" ).height(); var winW = $(window).width(); var winH = $(window).height(); var curPage = 1; var numOfPages = $( ".ws-bg" ).length; var changeAT = 0.5; var waveStartDelay = 0.2; var waveStagger = 0.013; var waveBlocked = false ; var index = 1; var startY = 0; var deltaY = 0; var headingsY = 0; var $parts; function initBgs() { var arr = []; for ( var i = 1; i <= bgParts; i++) { var $part = $( '<div class="ws-bg__part">' ); $part.addClass( "ws-bg__part-" + i); arr.push($part); } $( ".ws-bg" ).append(arr); $wsPages.addClass( "s--ready" ); $parts = $( ".ws-bg__part" ); changePages(); }; initBgs(); function changePages() { var y = (curPage - 1) * winH * -1; var textY = textH * (curPage - 1) * -1; var leftMax = index - 1; var rightMin = index + 1; TweenMax.to($( ".ws-bg__part-" + index), changeAT, {y: y}); for ( var i = leftMax; i > 0; i--) { var d = (index - i) * waveStagger; TweenMax.to($( ".ws-bg__part-" + i), changeAT - d, {y: y, delay: d}); } for ( var j = rightMin; j <= bgParts; j++) { var d = (j - index) * waveStagger; TweenMax.to($( ".ws-bg__part-" + j), changeAT - d, {y: y, delay: d}); } TweenMax.to($headings, changeAT, {y: textY}); }; function waveChange() { waveBlocked = true ; var y = (curPage - 1) * winH * -1; var textY = textH * (curPage - 1) * -1; for ( var i = 1; i <= bgParts; i++) { var $part = $( ".ws-bg__part-" + i); var d = (i - 1) * waveStagger + waveStartDelay; TweenMax.to($part, changeAT, {y: y, delay: d}); } TweenMax.to($headings, changeAT, {y: textY, delay: d}); var delay = (changeAT + waveStagger * (bgParts - 1)) * 1000; setTimeout( function () { waveBlocked = false ; }, delay); }; function navigateUp() { if (curPage > 1) curPage--; }; function navigateDown() { if (curPage < numOfPages) curPage++; }; function navigateWaveUp() { if (curPage === 1) return ; curPage--; waveChange(); }; function navigateWaveDown() { if (curPage === numOfPages) return ; curPage++; waveChange(); }; function movePart($part, y) { var y = y - (curPage - 1) * winH; var headY = headingsY - (curPage - 1) * textH; TweenMax.to($part, changeAT, {y: y, ease: Back.easeOut.config(4)}); TweenMax.to($headings, changeAT, {y: headY}); }; function moveParts(y, index) { var leftMax = index - 1; var rightMin = index + 1; var stagLeft = 0; var stagRight = 0; var stagStepL = -staggerStep; var stagStepR = -staggerStep; var sign = (y > 0) ? -1 : 1; movePart($( ".ws-bg__part-" + index), y); for ( var i = leftMax; i > 0; i--) { var step = index - i; stagStepL += (step <= 15) ? staggerStep : 1; var sVal = staggerVal - stagStepL; if (sVal < 0) sVal = 0; stagLeft += sVal; var nextY = y + stagLeft * sign; if (Math.abs(y) < Math.abs(stagLeft)) nextY = 0; movePart($( ".ws-bg__part-" + i), nextY); } for ( var j = rightMin; j <= bgParts; j++) { var step = j - index; stagStepR += (step <= 15) ? staggerStep : 1; var sVal = staggerVal - stagStepR; if (sVal < 0) sVal = 0; stagRight += sVal; var nextY = y + stagRight * sign; if (Math.abs(y) < Math.abs(stagRight)) nextY = 0; movePart($( ".ws-bg__part-" + j), nextY); } }; var mousemoveHandler = rafThrottle( function (e) { var y = e.pageY; var x = e.pageX; index = Math.ceil(x / winW * bgParts); deltaY = y - startY; headingsY = textH * deltaY / winH; moveParts(deltaY, index); }); var touchmoveHandler = rafThrottle( function (e) { e.preventDefault(); var y = e.originalEvent.touches[0].pageY; var x = e.originalEvent.touches[0].pageX; index = Math.ceil(x / winW * bgParts); deltaY = y - startY; headingsY = textH * deltaY / winH; moveParts(deltaY, index); }); var swipeEndHandler = function () { $(document).off( "mousemove" , mousemoveHandler); $(document).off( "touchmove" , touchmoveHandler); $(document).off( "mouseup touchend" , swipeEndHandler); if (!deltaY) return ; if (deltaY / winH >= 0.5) navigateUp(); if (deltaY / winH <= -0.5) navigateDown(); changePages(); }; $(document).on( "mousedown touchstart" , ".ws-bg__part" , function (e) { startY = e.pageY || e.originalEvent.touches[0].pageY; deltaY = 0; $(document).on( "mousemove" , mousemoveHandler); $(document).on( "touchmove" , touchmoveHandler); $(document).on( "mouseup touchend" , swipeEndHandler); }); $(document).on( "mousewheel DOMMouseScroll" , function (e) { if (waveBlocked) return ; if (e.originalEvent.wheelDelta > 0 || e.originalEvent.detail < 0) { navigateWaveUp(); } else { navigateWaveDown(); } }); $(document).on( "keydown" , function (e) { if (waveBlocked) return ; if (e.which === 38) { navigateWaveUp(); } else if (e.which === 40) { navigateWaveDown(); } }); $(window).on( "resize" , function () { winW = $(window).width(); winH = $(window).height(); changePages(); }); }); |