堆叠的页面导航-Page Stack Navigation


This Blueprint is page navigation effect based on the Dribbble shot Stacked navigation by Ilya Kostin. The idea is to show a navigation when clicking on the menu button and transform all pages in 3D and move them to the bottom of the viewport. The next two pages are shown in the back of the current page as a stack. When clicking on a menu item, the respective page comes up.
这是基于Ilya Kostin的Dribbble shot堆叠导航的页面效果,这个效果是在点击菜单按钮时显示导航,并将所有页面转换为3D,并且把它们移动到视口的底部,接下来的两页作为一个堆栈显示在当前页面的后面,当点击菜单项时相应的页面会出现。

查看演示 下载资源

HTML

<!-- navigation -->
<nav class="pages-nav">
	<div class="pages-nav__item"><a class="link link--page" href="#page-home">Home</a></div>
	<div class="pages-nav__item"><a class="link link--page" href="#page-docu">Documentation</a></div>
	<div class="pages-nav__item"><a class="link link--page" href="#page-manuals">Manuals</a></div>
	<div class="pages-nav__item"><a class="link link--page" href="#page-software">Software</a></div>
	<div class="pages-nav__item"><a class="link link--page" href="#page-custom">Customization & Settings</a></div>
	<div class="pages-nav__item"><a class="link link--page" href="#page-training">Training</a></div>
	<div class="pages-nav__item pages-nav__item--small"><a class="link link--page link--faded" href="#page-buy">Where to buy</a></div>
	<div class="pages-nav__item pages-nav__item--small"><a class="link link--page link--faded" href="#page-blog">Blog & News</a></div>
	<div class="pages-nav__item pages-nav__item--small"><a class="link link--page link--faded" href="#page-contact">Contact</a></div>
	<div class="pages-nav__item pages-nav__item--social">
		<a class="link link--social link--faded" href="#"><i class="fa fa-twitter"></i><span class="text-hidden">Twitter</span></a>
		<a class="link link--social link--faded" href="#"><i class="fa fa-linkedin"></i><span class="text-hidden">LinkedIn</span></a>
		<a class="link link--social link--faded" href="#"><i class="fa fa-facebook"></i><span class="text-hidden">Facebook</span></a>
		<a class="link link--social link--faded" href="#"><i class="fa fa-youtube-play"></i><span class="text-hidden">YouTube</span></a>
	</div>
</nav>
<!-- /navigation-->
<!-- pages stack -->
<div class="pages-stack">
	<!-- page -->
	<div class="page" id="page-home">
		<!-- page content -->
	</div>
	<!-- /page -->
	<div class="page" id="page-docu">
		<!-- page content -->
	</div>
	<div class="page" id="page-manuals">
		<!-- page content -->
	</div>
	<div class="page" id="page-software">
		<!-- page content -->
	</div>
	<div class="page" id="page-custom">
		<!-- page content -->
	</div>
	<div class="page" id="page-training">
		<!-- page content -->
	</div>
	<div class="page" id="page-buy">
		<!-- page content -->
	</div>
	<div class="page" id="page-blog">
		<!-- page content -->
	</div>
	<div class="page" id="page-contact">
		<!-- page content -->
	</div>
</div>
<!-- /pages-stack -->
<button class="menu-button"><span>Menu</span></button>
<script src="js/classie.js"></script>
<script src="js/main.js"></script>

CSS

html.js,
.js body {
	overflow: hidden;
	height: 100vh;
}

/* Pages nav */

.pages-nav {
	display: -webkit-flex;
	display: flex;
	-webkit-flex-wrap: wrap;
	flex-wrap: wrap;
	-webkit-justify-content: center;
	justify-content: center;
	-webkit-align-items: center;
	align-items: center;
	padding: 20px;
	text-align: center;
	background: #0e0f0f;
}

.js .pages-nav {
	position: absolute;
	top: 0;
	left: 0;
	width: 100%;
	height: 50vh;
	padding: 30px;
	pointer-events: none;
	opacity: 0;
	background: transparent;
	-webkit-transition: -webkit-transform 1.2s, opacity 1.2s;
	transition: transform 1.2s, opacity 1.2s;
	-webkit-transition-timing-function: cubic-bezier(0.2, 1, 0.3, 1);
	transition-timing-function: cubic-bezier(0.2, 1, 0.3, 1);
	-webkit-transform: translate3d(0, 150px, 0);
	transform: translate3d(0, 150px, 0);
}

.js .pages-nav--open {
	pointer-events: auto;
	opacity: 1;
	-webkit-transform: translate3d(0, 0, 0);
	transform: translate3d(0, 0, 0);
}

.pages-nav__item {
	width: 33%;
	padding: 1em;
}

.js .pages-nav__item {
	padding: 0 10%;
}

.pages-nav .pages-nav__item--social {
	width: 100%;
	opacity: 0;
	-webkit-transition: -webkit-transform 1.2s, opacity 1.2s;
	transition: transform 1.2s, opacity 1.2s;
	-webkit-transition-timing-function: cubic-bezier(0.2, 1, 0.3, 1);
	transition-timing-function: cubic-bezier(0.2, 1, 0.3, 1);
	-webkit-transform: translate3d(0, 20px, 0);
	transform: translate3d(0, 20px, 0);
}

.pages-nav--open .pages-nav__item--social {
	opacity: 1;
	-webkit-transition-delay: 0.35s;
	transition-delay: 0.35s;
	-webkit-transform: translate3d(0, 0, 0);
	transform: translate3d(0, 0, 0);
}

.link {
	font-size: 0.85em;
	font-weight: bold;
	position: relative;
	letter-spacing: 1px;
	text-transform: uppercase;
}

.link:hover,
.link:focus {
	color: #fff;
}

.link--page {
	display: block;
	color: #cecece;
}

.link--page:not(.link--faded)::before {
	content: '';
	position: absolute;
	top: 100%;
	left: 50%;
	width: 30px;
	height: 2px;
	margin: 5px 0 0 -15px;
	background: #fff;
	-webkit-transition: -webkit-transform 0.3s;
	transition: transform 0.3s;
	-webkit-transform: scale3d(0, 1, 1);
	transform: scale3d(0, 1, 1);
}

.link--page:hover:before {
	-webkit-transform: scale3d(1, 1, 1);
	transform: scale3d(1, 1, 1);
}

.link--faded {
	color: #4f4f64;
}

.link--faded:hover,
.link--faded:focus {
	color: #5c5edc;
}

.link--page.link--faded {
	font-size: 0.65em;
}

.link--social {
	font-size: 1.5em;
	margin: 0 0.75em;
}

.text-hidden {
	position: absolute;
	display: block;
	overflow: hidden;
	width: 0;
	height: 0;
	color: transparent;
}

/* Pages stack */

.js .pages-stack {
	z-index: 100;
	pointer-events: none;
	-webkit-perspective: 1200px;
	perspective: 1200px;
	-webkit-perspective-origin: 50% -50%;
	perspective-origin: 50% -50%;
}

.js .page {
	position: relative;
	z-index: 5;
	overflow: hidden;
	width: 100%;
	height: 100vh;
	pointer-events: auto;
	background: #2a2b30;
	box-shadow: 0 -1px 10px rgba(0, 0, 0, 0.1);
}

.js .pages-stack--open .page {
	cursor: pointer;
	-webkit-transition: -webkit-transform 0.45s, opacity 0.45s;
	transition: transform 0.45s, opacity 0.45s;
	-webkit-transition-timing-function: cubic-bezier(0.6, 0, 0.4, 1);
	transition-timing-function: cubic-bezier(0.6, 0, 0.4, 1);
}

.js .page--inactive {
	position: absolute;
	z-index: 0;
	top: 0;
	opacity: 0;
}

/* page content */

.info {
	font-size: 1.25em;
	max-width: 50%;
	margin-top: 1.5em;
}

.poster {
	position: absolute;
	bottom: 4vh;
	left: 60%;
	max-width: 100%;
	max-height: 80%;
}

/* Menu button */

.menu-button {
	position: absolute;
	z-index: 1000;
	top: 30px;
	left: 30px;
	width: 30px;
	height: 24px;
	padding: 0;
	cursor: pointer;
	border: none;
	outline: none;
	background: transparent;
}

.no-js .menu-button {
	display: none;
}

.menu-button::before,
.menu-button::after,
.menu-button span {
	background: #5f656f;
}

.menu-button::before,
.menu-button::after {
	content: '';
	position: absolute;
	top: 50%;
	left: 0;
	width: 100%;
	height: 2px;
	pointer-events: none;
	-webkit-transition: -webkit-transform 0.25s;
	transition: transform 0.25s;
	-webkit-transform-origin: 50% 50%;
	transform-origin: 50% 50%;
}

.menu-button span {
	position: absolute;
	left: 0;
	overflow: hidden;
	width: 100%;
	height: 2px;
	text-indent: 200%;
	-webkit-transition: opacity 0.25s;
	transition: opacity 0.25s;
}

.menu-button::before {
	-webkit-transform: translate3d(0, -10px, 0) scale3d(0.8, 1, 1);
	transform: translate3d(0, -10px, 0) scale3d(0.8, 1, 1);
}

.menu-button::after {
	-webkit-transform: translate3d(0, 10px, 0) scale3d(0.8, 1, 1);
	transform: translate3d(0, 10px, 0) scale3d(0.8, 1, 1);
}

.menu-button--open span {
	opacity: 0;
}

.menu-button--open::before {
	-webkit-transform: rotate3d(0, 0, 1, 45deg);
	transform: rotate3d(0, 0, 1, 45deg);
}

.menu-button--open::after {
	-webkit-transform: rotate3d(0, 0, 1, -45deg);
	transform: rotate3d(0, 0, 1, -45deg);
}

@media screen and (max-width: 60em) {
	.info {
		max-width: 100%;
	}
	.poster {
		position: relative;
		top: auto;
		left: auto;
		display: block;
		max-width: 100%;
		max-height: 50vh;
		margin: 0 0 0 50%;
	}
	.pages-nav__item {
		width: 50%;
		min-height: 20px;
	}
	.link--page {
		overflow: hidden;
		white-space: nowrap;
		text-overflow: ellipsis;
	}
	.link--social {
		margin: 0 0.1em;
	}
}

@media screen and (max-width: 40em) {
	.js .pages-nav {
		display: block;
		padding: 10px 20px 0 20px;
		text-align: left;
	}
	.js .pages-nav__item {
		width: 100%;
		padding: 4px 0;
	}
	.js .pages-nav__item--small {
		display: inline-block;
		width: auto;
		margin-right: 5px;
	}
	.pages-nav__item--social {
		font-size: 0.9em;
	}
	.menu-button {
		top: 15px;
		right: 10px;
		left: auto;
	}
	.info {
		font-size: 0.85em;
	}
	.poster {
		margin: 1em;
	}
}

JavaScript

/**
 * main.js
 * http://www.codrops.com
 *
 * Licensed under the MIT license.
 * http://www.opensource.org/licenses/mit-license.php
 * 
 * Copyright 2015, Codrops
 * http://www.codrops.com
 */
;(function(window) {

	'use strict';

	var support = { transitions: Modernizr.csstransitions },
		// transition end event name
		transEndEventNames = { 'WebkitTransition': 'webkitTransitionEnd', 'MozTransition': 'transitionend', 'OTransition': 'oTransitionEnd', 'msTransition': 'MSTransitionEnd', 'transition': 'transitionend' },
		transEndEventName = transEndEventNames[ Modernizr.prefixed( 'transition' ) ],
		onEndTransition = function( el, callback ) {
			var onEndCallbackFn = function( ev ) {
				if( support.transitions ) {
					if( ev.target != this ) return;
					this.removeEventListener( transEndEventName, onEndCallbackFn );
				}
				if( callback && typeof callback === 'function' ) { callback.call(this); }
			};
			if( support.transitions ) {
				el.addEventListener( transEndEventName, onEndCallbackFn );
			}
			else {
				onEndCallbackFn();
			}
		},
		// the pages wrapper
		stack = document.querySelector('.pages-stack'),
		// the page elements
		pages = [].slice.call(stack.children),
		// total number of page elements
		pagesTotal = pages.length,
		// index of current page
		current = 0,
		// menu button
		menuCtrl = document.querySelector('button.menu-button'),
		// the navigation wrapper
		nav = document.querySelector('.pages-nav'),
		// the menu nav items
		navItems = [].slice.call(nav.querySelectorAll('.link--page')),
		// check if menu is open
		isMenuOpen = false;

	function init() {
		buildStack();
		initEvents();
	}

	function buildStack() {
		var stackPagesIdxs = getStackPagesIdxs();

		// set z-index, opacity, initial transforms to pages and add class page--inactive to all except the current one
		for(var i = 0; i < pagesTotal; ++i) {
			var page = pages[i],
				posIdx = stackPagesIdxs.indexOf(i);

			if( current !== i ) {
				classie.add(page, 'page--inactive');

				if( posIdx !== -1 ) {
					// visible pages in the stack
					page.style.WebkitTransform = 'translate3d(0,100%,0)';
					page.style.transform = 'translate3d(0,100%,0)';
				}
				else {
					// invisible pages in the stack
					page.style.WebkitTransform = 'translate3d(0,75%,-300px)';
					page.style.transform = 'translate3d(0,75%,-300px)';		
				}
			}
			else {
				classie.remove(page, 'page--inactive');
			}

			page.style.zIndex = i < current ? parseInt(current - i) : parseInt(pagesTotal + current - i);
			
			if( posIdx !== -1 ) {
				page.style.opacity = parseFloat(1 - 0.1 * posIdx);
			}
			else {
				page.style.opacity = 0;
			}
		}
	}

	// event binding
	function initEvents() {
		// menu button click
		menuCtrl.addEventListener('click', toggleMenu);

		// navigation menu clicks
		navItems.forEach(function(item) {
			// which page to open?
			var pageid = item.getAttribute('href').slice(1);
			item.addEventListener('click', function(ev) {
				ev.preventDefault();
				openPage(pageid);
			});
		});

		// clicking on a page when the menu is open triggers the menu to close again and open the clicked page
		pages.forEach(function(page) {
			var pageid = page.getAttribute('id');
			page.addEventListener('click', function(ev) {
				if( isMenuOpen ) {
					ev.preventDefault();
					openPage(pageid);
				}
			});
		});

		// keyboard navigation events
		document.addEventListener( 'keydown', function( ev ) {
			if( !isMenuOpen ) return; 
			var keyCode = ev.keyCode || ev.which;
			if( keyCode === 27 ) {
				closeMenu();
			}
		} );
	}

	// toggle menu fn
	function toggleMenu() {
		if( isMenuOpen ) {
			closeMenu();
		}
		else {
			openMenu();
			isMenuOpen = true;
		}
	}

	// opens the menu
	function openMenu() {
		// toggle the menu button
		classie.add(menuCtrl, 'menu-button--open')
		// stack gets the class "pages-stack--open" to add the transitions
		classie.add(stack, 'pages-stack--open');
		// reveal the menu
		classie.add(nav, 'pages-nav--open');

		// now set the page transforms
		var stackPagesIdxs = getStackPagesIdxs();
		for(var i = 0, len = stackPagesIdxs.length; i < len; ++i) {
			var page = pages[stackPagesIdxs[i]];
			page.style.WebkitTransform = 'translate3d(0, 75%, ' + parseInt(-1 * 200 - 50*i) + 'px)'; // -200px, -230px, -260px
			page.style.transform = 'translate3d(0, 75%, ' + parseInt(-1 * 200 - 50*i) + 'px)';
		}
	}

	// closes the menu
	function closeMenu() {
		// same as opening the current page again
		openPage();
	}

	// opens a page
	function openPage(id) {
		var futurePage = id ? document.getElementById(id) : pages[current],
			futureCurrent = pages.indexOf(futurePage),
			stackPagesIdxs = getStackPagesIdxs(futureCurrent);

		// set transforms for the new current page
		futurePage.style.WebkitTransform = 'translate3d(0, 0, 0)';
		futurePage.style.transform = 'translate3d(0, 0, 0)';
		futurePage.style.opacity = 1;

		// set transforms for the other items in the stack
		for(var i = 0, len = stackPagesIdxs.length; i < len; ++i) {
			var page = pages[stackPagesIdxs[i]];
			page.style.WebkitTransform = 'translate3d(0,100%,0)';
			page.style.transform = 'translate3d(0,100%,0)';
		}

		// set current
		if( id ) {
			current = futureCurrent;
		}
		
		// close menu..
		classie.remove(menuCtrl, 'menu-button--open');
		classie.remove(nav, 'pages-nav--open');
		onEndTransition(futurePage, function() {
			classie.remove(stack, 'pages-stack--open');
			// reorganize stack
			buildStack();
			isMenuOpen = false;
		});
	}

	// gets the current stack pages indexes. If any of them is the excludePage then this one is not part of the returned array
	function getStackPagesIdxs(excludePageIdx) {
		var nextStackPageIdx = current + 1 < pagesTotal ? current + 1 : 0,
			nextStackPageIdx_2 = current + 2 < pagesTotal ? current + 2 : 1,
			idxs = [],

			excludeIdx = excludePageIdx || -1;

		if( excludePageIdx != current ) {
			idxs.push(current);
		}
		if( excludePageIdx != nextStackPageIdx ) {
			idxs.push(nextStackPageIdx);
		}
		if( excludePageIdx != nextStackPageIdx_2 ) {
			idxs.push(nextStackPageIdx_2);
		}

		return idxs;
	}

	init();

})(window);
文章链接:https://www.sbkko.com/page-stack-navigation.html
文章标题:堆叠的页面导航-Page Stack Navigation
文章版权:SBKKO 所发布的内容,部分为原创文章,转载请注明来源,网络转载文章如有侵权请联系我们!

人已赞赏
网页布局资源

缩放幻灯片-Zoom Slider

2017-11-15 20:10:08

网页布局资源

多级菜单-Multi-Level Menu

2017-11-15 20:18:10

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索