読者です 読者をやめる 読者になる 読者になる

平日WEB系SE 週末時々自転車屋

WEB系の技術ネタや大好きなお酒、週末手伝う自転車屋の話などを書きます。

はてなブログでスクロールすると画面上部に固定されるPC・スマホ両方に対応したグローバルメニューを表示する方法(PC・スマホ両方に対応)

 

※2015/7/19に修正版を作りました。 

jitenshaya-se.hatenablog.com

 

 

前回の記事の続きで、画面上部に固定されるグローバルメニューをスマホ用のものと入れ替える機能を実装します。

 

jitenshaya-se.hatenablog.com

 

スマホ用のグローバルメニューはwebフォントを利用

まずグローバルメニュー自体はスマホ用に高さを出したくないのでリンクを三つだけ固定で表示するグローバルメニューに切り替えます。

リンクについては3つに絞ってさみしいので、試しにwebフォントを利用してみました。

webフォントはこちらのブログのサイドメニューのアイコンでも使っているFont Awesomeを使います。

 

fortawesome.github.io

 

使い方は簡単で、ヘッダー内でスタイルシートを読み込み、あとは下のようにタグを書くだけです。

<i class="fa fa-bicycle"></i>自転車

 

※自転車のアイコンが出したくて探したところこちらのwebフォントの最新バージョンであれば出せるようなので、現行の最新バージョンである4.3.0を使っています。

 

詳しい使い方はこちらのページに詳しく書かれているので参考にしてください。

h2ham.net

 

スマホとPC版の切り替え

最初グローバルメニュー自体は下のような構造をしているので、表示位置をそのまま残すために一番外側の<div id="globalmenu"></div>は残しつつ、<nav id="globalnavi"></nav>から内側の部分だけスマホとPCで切り替えようと思いました。 

しかし、jQueryによる要素の追加・削除は重い処理なので、できるだけ処理の軽い要素の表示・非表示(displayのblockとnoneを切り替える方法)を切り替える方法にしました。

<div id="globalmenu">
<nav id="globalnavi">
<ul>
<li></li>
<li></li>
  ・
  ・
<ul>
</nav>
<div>

 

jQueryで表示・非表示の切り替えを行う場合はクラスの切り替えが早いらしい

このページに記載されているのですが、jQueryにはアニメーションしつつ表示・非表示を切り替える、.show().hide()という関数があるのですが、こちらは処理としては重いようなので、記事内で一番早いといわれている、クラスの入れ替えで対応することにしました。

 

PCとスマホの判断については以前書いたこちらの記事の画面幅を利用した方法を利用します。

jitenshaya-se.hatenablog.com

 

作ってみたけど遅い

要素がそろったので、試しに実装したところ、困ったことに表示が遅いのです。

で、色々と試したところ、jQueryははてなのものが読み込まれるより前に自前で読み込んだ方が処理が早く始まり、また少しだけ遅延して追従する部分の処理を読み込ませると体感的に早くなったので、setTimeout()で1秒だけ遅延して開始するようにしてみました。

 

javascriptのコードはこのような形になります。

<script>
<!-- jQueryの読み込みを待つ処理 -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>

$(document).ready(function(){
  // グローバルメニュー表示
//固定用のヘッダー
var title = '<div class="globalmenu" id="staticmenu"><nav class="globalnavi"><ul><li><a href="/archive">記事一覧</a></li>';
var categoryobj = $("#box2-inner").find("div.hatena-module-category li");
for (var i=0; i< categoryobj.length; i++) {
var category = categoryobj.eq(i).find('a');
title = title + '<li><a href="' + category.attr("href") + '">' + category.text() + '</a></li>';
if(i > 3){
break;
}
}
title = title + '</ul></nav><div>';

//スマホ画面移動時のヘッダー
sp_title = '<div class="globalmenu hide" id="fixmenu"><nav class="globalnavi"><ul><li><a href="/archive/category/自転車屋"><i class="fa fa-bicycle"></i>自転車屋</a></li><li><a href="/archive/category/お酒"><i class="fa fa-beer"></i>お酒</a></li><li><a href="/archive/category/はてブロ改造">はてブロ</a></li></ul></nav><div>';

//初期値設定
$("#blog-title").after(title).after(sp_title);

setTimeout(function(){
//グローバルメニューを取得
var globalstaticmenu = $('#staticmenu');
var globalfixmenu = $('#fixmenu');
var menu = "static";
//グローバルメニューの高さを取得
hTop = globalstaticmenu.offset().top;
//画面がスクロールされたときに起きるjQueryのイベント
$(window).scroll(function () {
//今表示している画面の縦方向の位置(画面が下に行くほど数字が大きくなる)
//とグローバルメニューの位置を比較して、画面位置の方が下になったか判定
if($(window).scrollTop() > hTop - 0) {
if(menu == "static"){
//グローバルメニューを画面の一番上(高さ0)に固定
//スマホ用のグローバルメニューを表示
if ($(window).width() < 480) {
globalstaticmenu.addClass('hide').css('position', 'fixed').css('top', '0px');
globalfixmenu.removeClass('hide').css('position', 'fixed').css('top', '0px');
}else{
globalstaticmenu.removeClass('hide').css('position', 'fixed').css('top', '0px');
globalfixmenu.addClass('hide').css('position', 'fixed').css('top', '0px');
}
menu = "fix"
}
}else{
//グローバルメニューを元の位置に固定
globalstaticmenu.css('position', 'static').removeClass('hide');
globalfixmenu.css('position', 'static').addClass('hide');
menu = "static";
}
});
},1000);

});
</script>

 

CSSのコードはこちらになります。

/*グローバルメニュー調整*/
.globalmenu {
z-index: 9000;
background:#ebe9e3;
left:0px;
width:100%;
}

.globalnavi ul{
font-size: 1.4em;
list-style: none;
text-align: center;
margin:0;
padding: 0;
}
.globalnavi ul li{display: inline-block;}
.globalnavi ul li a{
text-decoration: none;
display: block;
padding: 10px;
}
/*スマホ用のグローバルメニュー調整*/
@media screen and (max-width: 480px) {
.globalnavi ul li a{padding: 5px;}
}
.hide {
display: none;
}


スマホの時の見た目はこんな感じです。

 

f:id:jitenshaya_se:20150623163745p:plain

 

思ったよりいい感じにできました!!!