Sensebahnのサイト内では、ページを遷移するときにページ全体の更新ではなくページの一部を書き換える方法をとっています。(2013/1/31のデザイン変更で廃止しました。)

そうすることで、ページ全体を読み込むよりも速く遷移でき、さらに、画面がブランクになる瞬間が発生しないので目のチラツキを抑えられます。

仕組みとしてはAjaxを使います。

AjaxはJavaScriptで簡単に使うことができます。

JavaScriptを使って、Ajaxによりページの一部を、他のページの内容に書き換えるのです。具体的には、次のコードでやります。

example.html

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type="text/javascript" src="example.js"></script>
<!-- 以下HTML -->

example.js

var changePage = function(){
	$("読み込んだ内容を格納する要素").load("http://読み込みたいページのURL " + "読み込みたい要素",コールバック関数);
	//読み込みたいページのURLの後ろに半角スペースを入れること
}
$(document).on("click","a",changePage);

JavaScriptフレームワークであるjQueryを読み込んだら、あとはjQueryの.load()を使うだけです。この例では、すべてのa要素をclickしたときに、指定の要素内に、指定のページの指定の要素を読み込ませます。

しかし問題があります…

ページの一部を書き換えているだけなので、ブラウザのアドレスバーが変わらないのです。だから、履歴にも残りませんし、ブックマークもできませんし、Facebookでシェアすることもできません。(全部、はじめに開いたページになってしまいます)

解決するにはpushState

その問題を解決するのが、HTML5で導入されたpushStateというAPIです。

やっと本題です_| ̄|○

pushStateによって、Ajaxを使ってスムーズなページ遷移を実現させつつ、アドレスバーも動的に変えることができます。このpushStateをjQueryで簡単に使えるようにする、PjaxというjQueryプラグインがあります。しかし当サイトでは思い通りの挙動にならなかった(^_^;)ので、プラグインを使わずに素のJavaScriptAPIを呼び出しました。

次のコードでできます。

example.js

var after = function(){
	history.pushState("","","ページの相対パス");
	//アドレスバー変更
}
var changePage = function(){
	$("読み込んだ内容を格納する要素").load("http://読み込みたいページのURL " + "読み込みたい要素",after);
	//Ajaxで一部更新
}
$(document).on("click","a",changePage);

history.pushState()で使えます(第1〜2引数は利用シーンがあまりないと思うので割愛しますね)。注意点としては、pushStateでアドレスバーを変更すると、現在のホストの後部に指定の文字列が追加されるため、相対パスでないといけないということです。(ホストまで変えることができたら悪用されちゃいますから、当然の仕様です)

それと当然ながら、ブラウザがpushStateに対応している必要があります。MDNが対応ブラウザをまとめているので、これが参考になると思います。ページ下部にあるBrowser compatibilityという項目です。

実践

このpushStateのほか、当サイトでは遷移時にアニメーション効果を付けています。より実践的には次のようなコードを使っています。

example.html

<!-- headなど前略 -->
<link href="/css/example.css" rel="stylesheet" type="text/css" media="screen">
<!-- CSS読み込み -->
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<!-- jQuery読み込み -->
<script type="text/javascript" src="/js/jquery.easing.js"></script>
<!-- jquery.easing.js読み込み
http://gsgd.co.uk/sandbox/jquery/easing/ -->
<script type="text/javascript" src="/js/example.js"></script>
<!-- bodyなど中略 -->
<div id="nav">
	<a href="http://〜">リンク</a>
</div>
<div id="ajax-wrapper">
	<div id="ajax-content">
		<div id="main">
		<!-- コンテンツ -->
		</div>
	</div>
</div>
<div id="curtain"></div>
<!-- footerなど後略 -->

example.js

var changePage = function(){
	windowH = $(window).height();
	//画面の高さを取得
	request = $(this).attr("href");
	//リンク先URLを取得
	url = location.host;
	thisProt = location.protocol;
	relativePath = request.replace(thisProt,"").replace("//","").replace(url,"");
	//相対パスの作成
	if(relativePath == ""){
		relativePath = "/";
	}
	//相対パスが空だったときはスラッシュを代入
	after = function(){
		$(".loader").remove();
		//ローダーを削除
	}
	refreshInfo = function(){
		history.pushState("", "", relativePath);
		//pushStateでアドレスバーを変更
		pageTitle = $("h1").text();
		//新しいページタイトルとしてh1を取得
		$("title").text(pageTitle);
		//ページタイトルを変更
		after();
		//afterを実行
	}
	displayContent = function(){
		$("html,body,#main").animate({scrollTop: 0},1000);
		//画面位置を上に戻す
		$("#curtain").animate({"height":0},800,"easeOutExpo",refreshInfo);
		//カーテンの高さを戻したらrefreshInfoを実行
	}
	loadContent = function(){
		$("#ajax-wrapper").load(request + " " + "#ajax-content",displayContent);
		//#ajax-wrapperにリンク先の#ajax-contentを読み込んだらdisplayContentを実行
	}
	_gaq.push(["_trackPageview",request]);
	//GoogleAnalyticsのトラッキングページを変える
	$(this).append('<div class="loader"></div>');
	//リンクの横にローダーを表示
	$("#curtain").animate({"height":windowH},800,"easeOutExpo",loadContent);
	//カーテンを画面の高さぶん動かしたらloadContentを実行
	return false;
}
$(document).on("click","#nav a",changePage);
//#navの中のaがclickされたらchangePageを実行

example.css

a {
	position: relative;
}
.loader {
	position: absolute;
	width: 16px;
	height: 100%;
	left: -17px;
	bottom: 0;
	background-image: url("images/loader.gif");
	background-position: center left;
	background-repeat: no-repeat;
}
#curtain {
	position: fixed;
	width: 100%;
	height: 0;
	background-color: white;
	background-image: url("images/stripe.png");
	z-index: 1;
	top: 0;
}
/* widthは適宜変えてください */

実際には、このサイトの独自仕様などがあるのでもう少し複雑なことをしていますが、一般的な部分ですとこんな感じです。

いかがでしょう。参考になれば幸いです!