尽管现在的计算机屏幕已经变得越来越大,但要向用户展示的内容仍旧可能比较多,难以在一个屏幕之内全部展现出来。更关键的是,如果只利用一个屏幕,那么很有可能网页所凸显的重点也变得不那么明确。
现在,设计师们已经开始倾向于使用网页的向下滚动,来将更多原本分属于不同页面的内容,集合在一个页面当中。本文将向你介绍这样的技术,我们将不同的链接以时间顺序串接起来,依靠网页的滚动来逐个展现。
本文的所有代码均来自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 };
搞定了。