尽管现在的计算机屏幕已经变得越来越大,但要向用户展示的内容仍旧可能比较多,难以在一个屏幕之内全部展现出来。更关键的是,如果只利用一个屏幕,那么很有可能网页所凸显的重点也变得不那么明确。

现在,设计师们已经开始倾向于使用网页的向下滚动,来将更多原本分属于不同页面的内容,集合在一个页面当中。本文将向你介绍这样的技术,我们将不同的链接以时间顺序串接起来,依靠网页的滚动来逐个展现。

本文的所有代码均来自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 };

搞定了。

demo查看

demo下载

About liuyanghejerry

富有激情的前端工程师,专注GUI开发。

Comments are closed.

Post Navigation