使用History Web API进行可爱,平滑的页面过渡

在本教程中,我们将构建一个具有平滑过渡页面的网站,而无需通常进行积极的页面刷新。 浏览演示中的页面以了解我的意思。

为了达到这种效果,我们将使用History Web API 。 简而言之,该API用于更改浏览器历史记录。 它允许我们加载新的URL,更改页面标题,然后同时将其记录为浏览器中的新访问,而无需实际加载页面。

这听起来令人困惑,但是它带来了许多可能性,例如能够提供更平滑的页面过渡并提供快速感,从而改善了用户体验。 您可能已经在许多网站和Web应用程序(例如TrelloQuartzPrivacy)上见证了Web History API的运行。

在继续进行之前,我们先来看一下要在网站上部署的特定API。

简要介绍一下History Web API

要访问Web History API,我们首先编写window.history然后再跟随其中一个API。 方法属性 。 在本教程中,我们将重点介绍pushState()方法,因此:

window.history.pushState( state, title, url );

从上面的代码片段中可以看到, pushState()方法采用三个参数。

  1. 第一个参数state应当是包含任意数据的对象。 然后可以通过window.history.state访问此数据。 在实际的应用程序中,我们将传递诸如页面ID,URL或从表单派生的序列化输入之类的数据。
  2. 最后两个参数是title
  3. url 。 这两个更改了浏览器中的URL和文档标题,并将它们记录为浏览器历史记录中的新条目。

让我们剖析以下示例,以更好地了解pushState()方法的工作方式。

(function( $ ){

	$( "a" ).on( "click", function( event ) {

		event.preventDefault();

		window.history.pushState( { ID: 9 }, "About - Acme", "about/" );
	} );

})( jQuery );

在上面的代码中, click事件附带的链接然后部署pushState()方法。 当我们单击链接时,我们期望代码更改文档标题和URL:

确实如此; 屏幕快照显示URL已按pushState()方法中的定义更改为“ about /”。 由于pushState()方法在浏览器历史记录中创建了一条新记录,因此我们能够通过浏览器的“ 后退”按钮返回到上一页

但是,此示例中的所有浏览器当前都忽略title参数。 您可以从屏幕快照中看到文档并未更改为About-Acme 。 此外,调用pushState()方法也不会触发popstate事件。 历史每次更改都会调度的事件-这是我们需要的! 如MDN中所述,在浏览器如何处理此事件方面存在一些差异:

“浏览器在页面加载时倾向于不同地处理popstate事件。 Chrome(v34之前的版本)和Safari总是在页面加载时发出popstate事件,但Firefox不会。

我们将需要一个库作为后备,以使History Web API在整个浏览器中一致地工作,而没有任何障碍。

认识History.js

由于pushState()方法无法充分发挥作用,因此在本教程中,我们将利用History.js 。 顾名思义,此JavaScript库是polyfill ,它复制了可在不同浏览器上运行的本机History API。 它还公开了与本地API相似的一组方法,尽管差别很小。

如前所述,浏览器本机API是通过history窗口对象以小写字母“ h”调用的,而History.js API是通过History以大写字母“ H”访问的。 给定前面的示例,并假设我们加载了history.js文件,我们可以按如下所示修改代码(再次注意,大写的“ H”)。

window.History.pushState( {}, title, url );

我希望这个简短的解释易于理解。 否则,如果您想了解有关Web History API的更多信息,则这里有一些其他参考。

建立我们的静态网站

在本节中,我们不会详细讨论构建静态网站所需的每个步骤。 我们的网站非常简单,如以下屏幕截图所示:

您不必创建看起来完全相同的网站。 您可以自由添加任何内容并根据需要创建任意数量的页面。 但是,您需要考虑一些有关HTML结构以及对某些元素使用idclass属性的特定要点。

  1. 在文档head加载jQueryHistory.js 。 您可以通过Bower或CDN(例如CDNJS或JSDelivr)将其作为项目依赖加载。
  2. 用ID wrap将header,content和footer wrapdiv<div id="wrap"></div>
  3. 网站页眉和页脚上有一些导航项。 每个菜单应指向一个页面。 确保页面存在并包含内容。
  4. 每个菜单链接都具有page-link类,我们将使用它们来选择这些菜单。
  5. 最后,我们给每个链接一个title属性,该属性将传递给pushState()以确定文档标题。

考虑到所有这些因素,我们HTML标记大致如下:

<head>
	<script src="jquery.js"></script>
	<script src="history.js"></script>
</head>
<body>
	<div id="wrap">
		<header>
			<nav>
				<ul>
					<li><a class="page-link" href="./" title="Acme">Home</a></li>
					<li><a class="page-link" href="./about.html" title="About Us">About</a></li>
					<!-- more menu -->
				</ul>
			</nav>
		</header>
		<div>
			<!-- content is here -->
		</div>
		<footer>
			<nav>
				<ul>
					<li><a href="tos.html" class="page-link" title="Terms of Service">Terms</a></li>
					<!-- more menu -->
				</ul>
			</nav>
			<!-- this is the footer -->
		</footer>
	</div>
</body>

完成静态网站的构建后,我们可以继续学习本教程的主要部分。

应用History Web API

在开始编写任何代码之前,我们需要创建一个新文件来保存我们JavaScript。 我们将其命名为script.js并将文件加载到文档中的body结束标记之前。

让我们添加第一段代码,以在单击菜单导航时更改文档标题和URL:

// 1.
var $wrap = $( "#wrap" );

// 2.
$wrap.on( "click", ".page-link", function( event ) {
	
	// 3.
	event.preventDefault();
	
	// 4.
	if ( window.location === this.href ) {
		return;
	}
	
	// 5.
	var pageTitle = ( this.title ) ? this.title : this.textContent;
		pageTitle = ( this.getAttribute( "rel" ) === "home" ) ? pageTitle : pageTitle + " — Acme";
	
	// 6.
	History.pushState( null, pageTitle, this.href );
} );

我已将代码分为几个编号部分。 这些将使您更容易使用以下参考来精确定位代码:

  1. 在第一行,我们选择元素<div id="wrap"></div> ,它包装了我们所有的网站内容。
  2. 我们附加点击事件。 但是,正如您在上面看到的那样,我们将其附加到#wrap元素上,而不是将事件直接附加到每个菜单导航上。 这种做法称为事件委托 。 换句话说,我们的#wrap元素负责代表.page-link监听点击事件。
  3. 我们还添加了event.preventDefault()以便不会将用户定向到有问题的页面。
  4. 如果单击的菜单URL与当前窗口相同,则无需继续进行下一个操作,这仅仅是因为没有必要。
  5. pageTitle变量包含从链接标题属性或链接文本派生的标题格式。 除首页外,每个页面标题均遵循{Page Title} — Acme约定。 “ Acme”是我们的虚拟公司名称。
  6. 最后,我们将pageTitle和页面URL传递给History.js pushState()方法。

此时,当我们单击菜单导航时,标题以及URL应该相应更改,如下所示:

但是页面内容保持不变! 它不会更新以匹配新标题和新URL。

内容

我们需要添加以下代码行来替换实际的页面内容。

// 1.
History.Adapter.bind( window, "statechange", function() {
	
	// 2.
	var state = History.getState();
	
	// 3.
	$.get( state.url, function( res ) {

		// 4.
		$.each( $( res ), function( index, elem ) {
			if ( $wrap.selector !== "#" + elem.id ) {
				return;
			}
			$wrap.html( $( elem ).html() );
		} );

	} );
} );

同样,这里的代码被分成几个编号部分。

  1. 代码的第一行监听通过History.js pushState()方法执行的History更改,并运行附加的函数。
  2. 我们检索状态更改,其中包含各种数据,例如URL,标题和ID。
  3. 通过jQuery .get()方法,我们从给定的URL中检索内容。
  4. 最后,我们从检索到的内容中筛选出一个名为wrapid的元素,并最终用它替换当前页面的内容。

添加完毕后,当我们单击菜单导航时,内容现在应该已更新。 如上所述,我们还可以通过浏览器的“ 后退”和“ 前进”按钮来回访问已访问的页面。

此时,我们的网站可以展示。 但是,我们想通过添加一些动画使页面更加生动,从而走得更远,最后,我们的网站更具吸引力。

添加动画和转场

这种情况下的动画仅需简单,因此我们将从头开始编写所有内容,而不是通过Animate.cssZURB的 Motion UIEffeckt.css之类的库加载动画。 我们将动画命名为slideInUp ,如下所示:

@keyframes slideInUp {
	from {
		transform: translate3d(0, 10px, 0);
		opacity: 0;
	}
	to {
		transform: translate3d(0, 0, 0);
		opacity: 1;
	}
}

顾名思义,动画将页面内容与元素的不透明度一起从底部滑动到顶部。 将动画应用于包裹页面主要内容的元素,如下所示。

.section {
	animation-duration: .38s;
	animation-fill-mode: both;
	animation-name: slideInUp;
}

一旦应用了动画,从一页到另一页的过渡现在应该感觉更流畅。 在这里,您可以停下来打电话一天! 我们的网站已完成,我们准备将其部署给全世界。

但是,您可能还需要考虑添加一件事,特别是对于那些想要监视访问次数和访问者在您网站上的行为的用户而言。

我们需要添加Google Analytics(分析)来跟踪每个页面视图

谷歌分析

由于我们的页面将被异步加载(加载的初始页面除外),因此跟踪页面浏览量也应异步进行。

首先,请确保您有标准的谷歌Analytics(分析)在文档中添加head 。 该代码通常如下所示:

<script>
		(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
			(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
			m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
		})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');

		ga('create', 'UA-XXXXXX-XX', 'auto');
		ga('send', 'pageview');

	</script>

然后,我们需要调整JavaScript代码以包括Google Analytics(分析)跟踪代码,以便异步加载的每个页面也都将作为页面视图进行度量。

我们有几种选择。 首先,我们可以从用户单击导航链接,更改页面标题和URL或页面内容完全加载时开始计数。

我们将选择后者,它可以说是最真实的,并且在这样做时,我们在更改页面内容后利用jQuery promise()方法,如下所示:

$wrap.html( $( elem ).html() )
		.promise()
			.done( function( res ) {

			// Make sure the new content is added, and the 'ga()' method is available.
			if ( typeof ga === "function" && res.length !== 0 ) {
				ga('set', {
					page: window.location.pathname,
					title: state.title
				});
				ga('send', 'pageview');
		}
	});

仅此而已,我们现在将页面视图记录在Google Analytics(分析)中。

结语

在本教程中,我们使用Web History API改进了一个简单的静态网站,以使页面转换更加平滑,加载更快,并总体上为用户提供了更好的体验。 在本教程的最后,我们还实现了Google Analytics(分析)以异步记录用户页面视图 。 此外,如上所述,我们的网站是搜索引擎机器人的理想爬网工具 ,因为它只是一个简单HTML网站。

这是一个内容丰富的教程,介绍了CSS Animation,jQuery Ajax和jQuery Promise之类的许多内容。 这里有一些参考资料供您参考,以增强您所学的知识。

最后,不要忘记访问本教程的演示站点以及资源库中的源代码

翻译自: https://webdesign.tutsplus.com/tutorials/lovely-smooth-page-transitions-with-the-history-web-api--cms-26405

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
@font-face{ font-family:"Raphaelicons"; src:url('fonts/raphaelicons-webfont.eot'); src:url('fonts/raphaelicons-webfont.eot?#iefix') format('embedded-opentype'), url('fonts/raphaelicons-webfont.ttf') format('truetype'), url('fonts/raphaelicons-webfont.woff') format('woff'), url('fonts/raphaelicons-webfont.svg') format('svg'); font-weight: normal; font-style: normal; } html,body,.container,.st-container{ height: 100%; } body{ font-family:Arial,Georgia,serif; background-color: #ddd; font-weight: bold; font-size: 15px; color: #333; overflow: hidden; -webkit-font-smoothing:antialiased; } a{ text-decoration: none; color: #555; } .clr{ width: 0; height: 0; overflow: hidden; clear: both; padding:0; margin:0; } .st-container{ width: 100%; height: 100%; position: absolute;; top:0; left:0; font-family: Arial,"Josefin Slab","Myriad Pro",sans-serif; } .st-container > input,.st-container > a{ width: 20%; height: 40px; line-height: 40px; position:fixed; bottom:0; cursor: pointer; } .st-container > input{ opacity:0; z-index: 1000; } .st-container > a{ z-index: 10; font-weight: 700; font-size: 16px; background-color: #e23a6e; color: #fff; text-align: center; text-shadow:1px 1px 1px rgba(151,24,64,0.2); -webkit-transition:all 0.5s; -moz-transition:all 0.5s; transition:all 0.5s; } #st-control-1,#st-control-1 + a{ left:0%; } #st-control-2,#st-control-2 + a{ left:20%; } #st-control-3,#st-control-3 + a{ left:40%; } #st-control-4,#st-control-4 + a{ left:60%; } #st-control-5,#st-control-5 + a{ left:80%; } .st-container input:checked + a,.st-container input:checked:hover + a{ background-color: #821134; } .st-container input:checked + a:after{ content: ''; width: 0; height: 0; overflow: hidden; border:20px solid transparent; border-bottom-color:#821134; position: absolute; bottom:100%; left:50%; /*transform:translateX(-50%);*/ margin-left: -20px; } .st-container input:hover + a{ background-color: #ad244f; } /*内容区域*/ .st-scroll, .st-scroll .st-panel{ height: 100%; width: 100%; position: relative; } .st-scroll{ left:0; top:0; -webkit-transform:translate3d(0,0,0); -moz-transform:translate3d(0,0,0); transform:translate3d(0,0,0); -webkit-backface-visibility:hidden; -webkit-transition:all 0.6s ease-in-out; -moz-transition:all 0.6s ease-in-out; transition:all 0.6s ease-in-out; } .st-panel{ background-color: #fff; overflow: hidden; } .st-color{ background-color: #fa96b5; color: #fff; } #st-control-1:checked ~ .st-scroll{ -webkit-transform:translateY(0%); -moz-transform:translateY(0%); transform:translateY(0%); } #st-control-2:checked ~ .st-scroll{ -webkit-transform:translateY(-100%); -moz-transform:translateY(-100%); transform:translateY(-100%); } #st-control-3:checked ~ .st-scroll{ -webkit-transform:translateY(-200%); -moz-transform:translateY(-200%); transform:translateY(-200%); } #st-control-4:checked ~ .st-scroll{ -webkit-transform:translateY(-300%); -moz-transform:translateY(-300%); transform:translateY(-300%); } #st-control-5:checked ~ .st-scroll{ -webkit-transform:translateY(-400%); -moz-transform:translateY(-400%); transform:translateY(-400%); } .st-desc{ width: 200px; height: 200px; background-color: #fa96b5; position: absolute; left:50%; top:0; margin-left: -100px; -webkit-transform:translateY(-50%) rotate(45deg); -moz-transform:translateY(-50%) rotate(45deg); transform:translateY(-50%) rotate(45deg); } .st-color .st-desc{ background-color: #fff; } [data-icon]:after{ content: attr(data-icon); width: 200px; height: 200px; color: #fff; font-size: 90px; text-align: center; line-height: 200px; position: absolute; left: 50%; top:50%; margin: -100px 0 0 -100px; -webkit-transform:rotate(-45deg) translateY(25%); -moz-transform:rotate(-45deg) translateY(25%); transform:rotate(-45deg) translateY(25%); font-family:"Raphaelicons"; text-shadow:1px 1px 1px rgba(151,24,64,0.2); } .st-color [data-icon]:after{ color: #fa96b5; text-shadow:1px 1px 1px rgba(0,0,0,0.1); } .st-panel h2{ color: #e23a6e; font-size: 54px; line-height: 50px; text-align: center; font-weight: 900; width: 80%; position: absolute; left:10%; top:150px; text-shadow: 1px 1px 1px rgba(151,24,64,0.2); -webkit-backface-visibility:hidden; } .st-color h2{ color: #fff; text-shadow:1px 1px 1px rgba(0,0,0,0.1); } #st-control-1:checked ~ .st-scroll #st-panel-1 h2, #st-control-2:checked ~ .st-scroll #st-panel-2 h2, #st-control-3:checked ~ .st-scroll #st-panel-3 h2, #st-control-4:checked ~ .st-scroll #st-panel-4 h2, #st-control-5:checked ~ .st-scroll #st-panel-5 h2{ -webkit-animation:moveDown 0.6s ease-in-out 0.2s backwards; -moz-animation:moveDown 0.6s ease-in-out 0.2s backwards; -o-animation:moveDown 0.6s ease-in-out 0.2s backwards; -ms-animation:moveDown 0.6s ease-in-out 0.2s backwards; animation:moveDown 0.6s ease-in-out 0.2s backwards; } @-webkit-keyframes moveDown{ 0%{ -webkit-transform:translateY(-40px); opacity:0; } 100%{ -webkit-transform:translateY(0px); opacity:1; } } @-moz-keyframes moveDown{ 0%{ -moz-transform:translateY(-40px); opacity:0; } 100%{ -moz-transform:translateY(0px); opacity:1; } } @-o-keyframes moveDown{ 0%{ -o-transform:translateY(-40px); opacity:0; } 100%{ -o-transform:translateY(0px); opacity:1; } } @-ms-keyframes moveDown{ 0%{ -ms-transform:translateY(-40px); opacity:0; } 100%{ -ms-transform:translateY(0px); opacity:1; } } @keyframes moveDown{ 0%{ transform:translateY(-40px); opacity:0; } 100%{ transform:translateY(0px); opacity:1; } } .st-panel p{ font-size: 25px; color: #8b8b8b; line-height: 1.8; text-align: left; text-indent: 2em; font-weight: 700; width: 70%; position: absolute; left:15%; top:280px; text-shadow: 1px 1px 1px rgba(151,24,64,0.2); -webkit-backface-visibility:hidden; } .st-color p{ color:rgba(255,255,255,0.8); text-shadow:1px 1px 1px rgba(0,0,0,0.1); } #st-control-1:checked ~ .st-scroll #st-panel-1 p, #st-control-2:checked ~ .st-scroll #st-panel-2 p, #st-control-3:checked ~ .st-scroll #st-panel-3 p, #st-control-4:checked ~ .st-scroll #st-panel-4 p, #st-control-5:checked ~ .st-scroll #st-panel-5 p{ -webkit-animation:moveUp 0.6s ease-in-out 0.2s backwards; -moz-animation:moveUp 0.6s ease-in-out 0.2s backwards; -o-animation:moveUp 0.6s ease-in-out 0.2s backwards; -ms-animation:moveUp 0.6s ease-in-out 0.2s backwards; animation:moveUp 0.6s ease-in-out 0.2s backwards; } @-webkit-keyframes moveUp{ 0%{ -webkit-transform:translateY(40px); opacity:0; } 100%{ -webkit-transform:translateY(0px); opacity:1; } } @-moz-keyframes moveUp{ 0%{ -moz-transform:translateY(40px); opacity:0; } 100%{ -moz-transform:translateY(0px); opacity:1; } } @-o-keyframes moveUp{ 0%{ -o-transform:translateY(40px); opacity:0; } 100%{ -o-transform:translateY(0px); opacity:1; } } @-ms-keyframes moveUp{ 0%{ -ms-transform:translateY(40px); opacity:0; } 100%{ -ms-transform:translateY(0px); opacity:1; } } @keyframes moveUp{ 0%{ transform:translateY(40px); opacity:0; } 100%{ transform:translateY(0px); opacity:1; } } @media screen and (max-width:520px){ .st-panel h2{ font-size: 42px; } .st-panel p{ font-size: 18px; width: 90%; left:5%; top:240px; } .st-container > a{ font-size: 13px; } .st-desc{ width: 160px; height:160px; margin-left: -80px; } [data-icon]:after{ font-size: 75px; -webkit-transform:rotate(-45deg) translateY(20%); -moz-transform:rotate(-45deg) translateY(20%); transform:rotate(-45deg) translateY(20%); } } @media screen and (max-width:360px){ .st-panel h2{ font-size: 42px; } .st-panel p{ font-size: 18px; width: 90%; left:5%; top:240px; } .st-container > a{ font-size: 10px; } .st-desc{ width: 120px; height:120px; margin-left: -60px; } [data-icon]:after{ font-size: 60px; -webkit-transform:rotate(-45deg) translateY(15%); -moz-transform:rotate(-45deg) translateY(15%); transform:rotate(-45deg) translateY(15%); } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值