尽管现在的计算机屏幕已经变得越来越大,但要向用户展示的内容仍旧可能比较多,难以在一个屏幕之内全部展现出来。更关键的是,如果只利用一个屏幕,那么很有可能网页所凸显的重点也变得不那么明确。
现在,设计师们已经开始倾向于使用网页的向下滚动,来将更多原本分属于不同页面的内容,集合在一个页面当中。本文将向你介绍这样的技术,我们将不同的链接以时间顺序串接起来,依靠网页的滚动来逐个展现。
本文的所有代码均来自http://tympanus.net/codrops/2011/12/05/lateral-on-scroll-sliding-with-jquery/,如果您对其中的任何技术细节存在疑问,请以原文为准。
HTML
首先来看一看基本的HTML该怎么写。我们的页面分割成N个小段,每个小段都包含一个左半部分和一个右半部分,两个部分分别存放标题和一个图片链接。
为了让页面看起来大致对称,我们还需要让左右两个部分的职能进行均匀的交替。对于小段整体尺寸的控制,我们通过“ss-small”、 “ss-medium”、“ss-large”来进行区别。
November
2011
November 28, 2011 Some Title
CSS
主体部分用于整个页面的定位。同时有一点小技巧:因为我们的页面元素都是横向集中的,而我们不希望页面有横向的滚动条来破坏效果,所以我们加上横向溢出隐藏。
.ss-container{ width: 100%; position: relative; text-align: left; float: left; overflow: hidden; /*溢出隐藏*/ padding-bottom: 500px; }
我们在主体部分上额外增加一个before
伪元素的使用,这个伪元素我们使用绝对定位的方法,使它出现在整个主体部分的正中,成为我们的分割线。
.ss-container:before{ position: absolute; width: 4px; background: rgba(17,17,22,0.8); top: 0px; left: 50%; margin-left: -2px; content: ''; height: 100%; }
之后是我们的小段容器,以及左右两半部分:
.ss-row{ width: 100%; clear: both; float: left; position: relative; padding: 30px 0; } .ss-left, .ss-right{ float: left; width: 48%; position: relative; } .ss-right{ padding-left: 2%; } .ss-left{ text-align: right; float: left; padding-right: 2%; }
每个小段当中的标题:
.ss-container h2{ font-size: 40px; text-transform: uppercase; color: rgba(78,84,123,0.2); text-shadow: 0px 1px 1px #fff; padding: 20px 0px; } .ss-container h3{ margin-top: 34px; padding: 10px 15px; background: rgba(26, 27, 33, 0.6); text-shadow: 1px 1px 1px rgba(26, 27, 33, 0.8) }
现在,我们来处理圆圈图像链接的代码。这里的圆圈主要通过border-radius
来实现,同时我们增加了阴影来美化效果。
.ss-circle{ border-radius: 50%; overflow: hidden; display: block; text-indent: -9000px; text-align: left; box-shadow: 0px 2px 5px rgba(0,0,0,0.7) inset, 0px 0px 0px 12px rgba(61,64,85,0.3); background-size: cover; background-color: #f0f0f0; background-repeat: no-repeat; background-position: center center; } .ss-circle-1{ background-image:url(../images/1.jpg); } .ss-circle-2{ background-image: url(../images/2.jpg); } .ss-circle-3{ background-image: url(../images/3.jpg); } /* and so on... */
搞定之后,我们就开始对它的尺寸进行定制。我们有三种尺寸的链接,因此我们有以下的代码:
.ss-small .ss-circle{ width: 100px; height: 100px; } .ss-medium .ss-circle{ width: 200px; height: 200px; } .ss-large .ss-circle{ width: 300px; height: 300px; } .ss-left .ss-circle{ float: right; margin-right: 30%; } .ss-right .ss-circle{ float: left; margin-left: 30%; }
为了让这些链接、标题能够以树一样的形式与中间的分割线连接,我们再次使用伪元素勾勒出连接线:
.ss-circle-deco:before{ width: 29%; height: 0px; border-bottom: 5px dotted #ddd; border-bottom: 5px dotted rgba(17, 17, 22, 0.3); box-shadow: 0px 1px 1px #fff; position: absolute; top: 50%; content: ''; margin-top: -3px; } .ss-left .ss-circle-deco:before{ right: 2%; } .ss-right .ss-circle-deco:before{ left: 2%; }
连接线上的小箭头我们也通过伪元素来进行绘制:
.ss-circle-deco:after{ width: 0px; height: 0px; border-top: 10px solid transparent; border-bottom: 10px solid transparent; content: ''; position: absolute; top: 50%; margin-top: -10px; } .ss-left .ss-circle-deco:after{ right: 0; border-right: 10px solid rgba(17,17,22,0.8); } .ss-right .ss-circle-deco:after{ left: 0; border-left: 10px solid rgba(17,17,22,0.8); }
调整左右两半部分标题与连接线的关系:
.ss-container .ss-medium h3{ margin-top: 82px; } .ss-container .ss-large h3{ margin-top: 133px; } .ss-container .ss-left h3{ border-right: 5px solid rgba(164,166,181,0.8); } .ss-container .ss-right h3{ border-left: 5px solid rgba(164,166,181,0.8); }
最后是标题本身的样式:
.ss-container h3 span{ color: rgba(255,255,255,0.8); font-size: 13px; display: block; padding-bottom: 5px; } .ss-container h3 a{ font-size: 28px; color: rgba(255,255,255,0.9); display: block; } .ss-container h3 a:hover{ color: rgba(255,255,255,1); }
JavaScript
架子已经打好了,现在我们通过JavaScript
来监听用户的滚动事件,并作出响应,比如不断地移入、移出元素等等。
// the row elements var $rows = $('#ss-container > div.ss-row'), // we will cache the inviewport // rows and the outside viewport rows $rowsViewport, $rowsOutViewport, // navigation menu links $links = $('#ss-links > a'), // the window element $win = $(window), // we will store the window sizes here winSize = {}, // used in the scroll setTimeout function anim = false, // page scroll speed scollPageSpeed = 2000 , // page scroll easing scollPageEasing = 'easeInOutExpo', // perspective? hasPerspective = true, perspective = hasPerspective && Modernizr.csstransforms3d, // initialize function init = function() { // get window sizes getWinSize(); // initialize events initEvents(); // define the inviewport selector defineViewport(); // gets the elements that match the previous selector setViewportRows(); // if perspective add css if( perspective ) { $rows.css({ '-webkit-perspective' : 600, '-webkit-perspective-origin' : '50% 0%' }); } // show the pointers for the inviewport rows $rowsViewport.find('a.ss-circle').addClass('ss-circle-deco'); // set positions for each row placeRows(); },
defineViewport – 确定一个区域是否处于可视范围内。
defineViewport = function() { $.extend( $.expr[':'], { inviewport : function ( el ) { if ( $(el).offset().top < winSize.height ) { return true; } return false; } }); },
setViewportRows - 确定一个小段是否位于可视区域。
setViewportRows = function() { $rowsViewport = $rows.filter(':inviewport'); $rowsOutViewport = $rows.not( $rowsViewport ) },
getWinSize - 确定窗口的长宽尺寸。
getWinSize = function() { winSize.width = $win.width(); winSize.height = $win.height(); },
相关的事件初始化:
initEvents = function() { // 监听顶部菜单点击 $links.on( 'click.Scrolling', function( event ) { // scroll to the element that has id = menu's href $('html, body').stop().animate({ scrollTop: $( $(this).attr('href') ).offset().top }, scollPageSpeed, scollPageEasing ); return false; }); $(window).on({ // 监听窗口的尺寸变化,以便我们重新安排元素 'resize.Scrolling' : function( event ) { // get the window sizes again getWinSize(); // redefine which rows are initially // visible (:inviewport) setViewportRows(); // remove pointers for every row $rows.find('a.ss-circle').removeClass('ss-circle-deco'); // show inviewport rows and respective pointers $rowsViewport.each( function() { $(this).find('div.ss-left') .css({ left : '0%' }) .end() .find('div.ss-right') .css({ right : '0%' }) .end() .find('a.ss-circle') .addClass('ss-circle-deco'); }); }, // 监听页面的滚动 'scroll.Scrolling' : function( event ) { // set a timeout to avoid that the // placeRows function gets called on // every scroll trigger if( anim ) return false; anim = true; setTimeout( function() { placeRows(); anim = false; }, 10 ); } }); },
placeRows - 控制左右两半部分的位置。在不可见时,两半部分的right、left分别为-50%,而在正中时,二者分别为0%。
placeRows = function() { // how much we scrolled so far var winscroll = $win.scrollTop(), // the y value for the center of the screen winCenter = winSize.height / 2 + winscroll; // for every row that is not inviewport $rowsOutViewport.each( function(i) { var $row = $(this), // the left side element $rowL = $row.find('div.ss-left'), // the right side element $rowR = $row.find('div.ss-right'), // top value rowT = $row.offset().top; // hide the row if it is under the viewport if( rowT > winSize.height + winscroll ) { if( perspective ) { // webkit系列专用 $rowL.css({ '-webkit-transform' : 'translate3d(-75%, 0, 0) rotateY(-90deg) translate3d(-75%, 0, 0)', 'opacity' : 0 }); $rowR.css({ '-webkit-transform' : 'translate3d(75%, 0, 0) rotateY(90deg) translate3d(75%, 0, 0)', 'opacity' : 0 }); } else { $rowL.css({ left : '-50%' }); $rowR.css({ right : '-50%' }); } } // if not, the row should become visible // (0% of left/right) as it gets closer to // the center of the screen. else { // row's height var rowH = $row.height(), // the value on each scrolling step // will be proporcional to the distance // from the center of the screen to its height factor = ( ( ( rowT + rowH / 2 ) - winCenter ) / ( winSize.height / 2 + rowH / 2 ) ), // value for the left / right of each side of the row. // 0% is the limit val = Math.max( factor * 50, 0 ); if( val <= 0 ) { // when 0% is reached show the pointer for that row if( !$row.data('pointer') ) { $row.data( 'pointer', true ); $row.find('.ss-circle').addClass('ss-circle-deco'); } } else { // the pointer should not be shown if( $row.data('pointer') ) { $row.data( 'pointer', false ); $row.find('.ss-circle').removeClass('ss-circle-deco'); } } // set calculated values if( perspective ) { var t = Math.max( factor * 75, 0 ), r = Math.max( factor * 90, 0 ), o = Math.min( Math.abs( factor - 1 ), 1 ); $rowL.css({ '-webkit-transform' : 'translate3d(-' + t + '%, 0, 0) rotateY(-' + r + 'deg) translate3d(-' + t + '%, 0, 0)', 'opacity' : o }); $rowR.css({ '-webkit-transform' : 'translate3d(' + t + '%, 0, 0) rotateY(' + r + 'deg) translate3d(' + t + '%, 0, 0)', 'opacity' : o }); } else { $rowL.css({ left : - val + '%' }); $rowR.css({ right : - val + '%' }); } } }); }; return { init : init };
搞定了。