iphone/ipadサイト

マークアップエンジニアとかWEBディレクターとかをやってる僕が、自分が詰まって、解決したことをここに残しておきますよ。

androidでも速いハンバーガーメニュー(開閉メニュー)をつくる

スマホといえば、もう最近はほぼハンバーガーメニューだよね。
タップで上から降りてくる。
バツボタンをタップでまたあがっていく、というような。

普通につくると、以下のようにやりたくなる。

$('header nav').css({"top":"-1000px"});
$('#openMenu').click(function(ev){
ev.stopPropagation();//①
$('header nav').height($(window).height());//②
$('header nav').animate({top:0});//③
$('body,html').css({"overflow":"hidden","height":"100%"});//④
}); 

あらかじめ上のほうにメニューをふっとばしておいて、
#openMenuボタンをクリックしたらanimateでtop:0まで降りてくる。 

細かく説明すると、
①android対策等で親要素にクリックが伝搬しないようにする
②降りてくるメニューはウィンドウと同じ高さにセット(必要に応じて使う)
③メニューをtop:0の一までおろしてくる
④メニュー内をスワイプしてるときに背景がスクロールしちゃうのを防ぐ

わりとシンプル。
iphoneだけならこれでも全然いい。

※閉じるの処理はちょっと割愛してます。


でもandroidだと

「なんか遅いんですけど」
とか言われたりする。

そういうときは、めんどくさいけど、css3でアニメーションさせることになる。

んで作ったのが以下の様な感じ。

css

header nav{
width:100%;
top:-1000px;
overflow:scroll;
transform:translate(0px,0px);
-webkit-transform:translate(0px,0px);
transition: transform 0.3s ease-out;
}

header nav.on{
transform:translate(0px,1000px);
-webkit-transform:translate(0px,1000px);

js

$('#openMenu').on('click',function(ev){
ev.stopPropagation();
$('header nav').height($(window).height());
$('header nav').addClass('on');//⑤
$('body,html').css({"overflow":"hidden","height":"100%"});
}); 

jsはもともとのとほとんど同じだけど、animateで動かしてたのを消して、addClassだけになった。
⑤class="on"をnavタグにつける。

そしてアニメーション処理をやらせてるのは、cssのほう。

transitionでアニメーションで動くようにして、
.onがついてるのとついてないので、transform:translate(x,y)の位置を変えるという処理。

※閉じるの処理は割愛


 androidでtransformが効かなくて30分ほどロスしたけれども、ただ-webkit-プレフィクスをつけるだけだったという。

注意ですわね。 

スマホでメニューを開いた時に後ろはスクロールしないようにする

地味にはまってしまった。

スマホサイトのメニューって大体ハンバーガーメニューだよね。最近は。

38
(ハンバーガーメニューというやつ)

これをタップすると、ズルーっとグローバルメニューがかぶさるようにおりてくる、というのが一般的。

さて、そのメニュー内をスワイプしていると、後ろ側の ページが動いてしまうという現象に悩まされた。
タップでスクロールを禁止させるというのも見つけたが、
メニュー内はスクロールできるようにしたいため、背景だけスクロールを不可にしたい。


んで、しらべてみたら、htmlとbodyに対して、height:100%とoverflow:hiddenを割り当てればよいということがわかった。

実際に書くとこんな感じ。
閉じるときは解除も忘れずに。

$('#openMenu').click(function(){
$('header').fadeIn();
$('body,html').css({"overflow":"hidden","height":"100%"});
});
$('#closeMenu').click(function(){
$('body,html').css({"overflow":"visible","height":"auto"});
$('header').fadeOut();
});

手持ちのiphone6ではうまくいっている様子。

-------------追記-------------------

htmlも見たいというコメントをいただいたのでサンプルのhtmlのせますね。

<header>
<div class="headerInner">
<div class="headerLogo">
<h1><img src="img/logo.png" alt="ロゴ"></h1>
</div>
<a href="#" id="openMenu"><img src="img/icon_menu_sp.png" alt="menu"></a>
</div>
<nav class="gnav">
<ul>
<li><a href="#">メニュー</a></li>
<li><a href="#">メニュー</a></li>
<li><a href="#">メニュー</a></li>
<li><a href="#">メニュー</a></li>
<li><a href="#">メニュー</a></li>
</ul>
<a href="#" id="closeMenu"><img src="img/icon_menu_sp.png" alt="menu"></a>
</nav>
</header>

 今回のサンプルだとこんな感じ。

開くボタンと閉じるボタンがわかれてるパターン。
(開くも閉じるも1つのボタンっていうパターンも多いのでそれはまた別の記事で)


mp4とgifアニメがandroidやiphoneでちゃんと表示されるか調べた

そういうサイトがなにげに見つからなかったので調べたよ。

スマホサイトを作っていて浮かんだ疑問1
「そもそもgifアニメってandroidでもiphoneでも動くんだっけ?」


サンプルを作ってみたのでいろいろな端末でみてみよう


 ■結論
実験の結果、htmlに貼り付けた状態のgifアニメは、、
iOS8のsafari → ちゃんと動く
Android2.3ブラウザ(AQUOS phone) → ちゃんと動く
Android4.1のブラウザ(Galaxy S3) → ちゃんと動く

※その他の端末は 見てないごめんね。


スマホサイトを作っていて浮かんだ疑問2
「mp4ファイルにリンクを張った場合、androidやiphoneではどういう処理になるんだっけ?」 



上記のサンプルのページの一番下にある、mp4へのリンクをクリックしてみる。

■結論
iOS8のsafari → その場で動画が再生される。ローカル保存はできない。
Android2.3ブラウザ(AQUOS phone) → 開くアプリを選べる。デフォはその場で再生。
Android4.1のブラウザ(Galaxy S3) → デフォは「マイファイル」に保存される。

ここはなにげに端末やOSによって動きがわかれたぞ!気をつけろ!!


 
 スマホサイトを作っていて浮かんだ疑問3
「じゃぁmovファイルならiphoneで保存させられる?」 



mp4だとその場で再生が始まるだけというのはわかった。そんじゃぁ、movファイルへリンクを貼ればiphoneでもカメラロールに保存させるページが作れるのかな?

■結論
できない。
長押ししたりいろいろやってみたけど、movファイルでも再生されるだけで保存はできない。

なにかアプリを導入せずに動画ファイルをローカルに保存させることはiphoneではできないみたいね。


 
 スマホサイトを作っていて浮かんだ疑問4
「gifアニメなら保存させられる?」 



mp4動画はあきらめよう。代わりにgifアニメならローカルに保存させられるのかな?
さっきのサンプルに貼り付けたgifアニメを長押しして保存してみたよ。

■結論
iOS8のsafari → カメラロールに保存できるが、カメラロール内ではgifアニメは動かない。
Android2.3ブラウザ(AQUOS phone) → ローカルに保存されるがローカルではgifアニメは動かない。
Android4.1のブラウザ(Galaxy S3) → 「マイファイル」に保存される。ローカルでも動く。


難しいねぇ。

以上、スマートフォンの動画周りの挙動調査でした。 

失礼します! 

iOS8.4.1でa:hoverにopacityつけるとリンクが飛ばなくなる

iOS8.4.1にアップデートされたiPhoneやiPadのsafariで起きてる問題。

a:hoverにopacityをつけると、hoverに1タップ消費されてしまい、2タップしないとリンク先に飛ばない事件。

まずはこのサンプルを見て欲しい↓
サンプルページPCのブラウザでクリック

 3つのボタンを並べている。

1つめはhoverで色がかわる。
2つめと3つめはhoverでhover:0.5にしていて、半透明になるようになっている。
マウスをのせてみるとそのとおりになるよね。

クリックしてみても、普通にリンクとして次のページに飛ぶ。



んじゃ次にiOS8.4.1にアップデートされたiPhoneのsafariで同じページを見てみてほしい。
↓QRカメラでもいけるよ!
chart

 そして、各ボタンをタップしてみてほしい。

・・・・・

おわかりいただけただろうか...(怖い声で) 


1つめのボタンは普通にタップでページ遷移するのに、
2つめと3つめのボタンは、1度目のタップで、ページ遷移せずになんと半透明になってしまうんだ!!! 

a:hover{opacity:0.7}

などと設定するとhoverで1タップ消費されてしまう事変。

iOS8.4.1からおこる現象だから、最近登場したピカピカの新人バグだ(バグなの?)

これ、ユーザビリティを著しく下げるよね。

ユーザーはページ遷移したくてボタンをタップするのに、何の変化もしない。
(ように見える。実際は少し透明になってる。)

「なんだよこのサイト。壊れてるのかよ」

ってなる。

実際僕は普通に調べ物をしてて、どこかのサイトでそう思った。

これはコンバージョンをガッツリ取りたいサイトにとっては、かなりのダメージなんじゃないかと思う。



■レスポンシブに悪影響

普通のスマホサイトだったらhoverなんて設定してないだろうし、この問題 でダメージを負うことはないかもしれない。

一番やられるのはレスポンシブサイトじゃないだろうか。

レスポンシブはpcでもスマホでも同じソース&cssを読ませたりするから、aタグには当然hoverがついていたりするし、hoverにはopacityがついていたりする。


■jsで対処してみる

jQueryでiOSの場合のみhoverでも遷移するというのを書いてみた。
これをそのままコピペで一応使える。
target="_blank"やhref="#top"などのページ内リンクでも使えるように調整してある。

var userAgent = navigator.userAgent;
var UA_iPhone = (userAgent.indexOf('iPhone') > -1)? true:false;
var UA_iPad = (userAgent.indexOf('iPad') > -1)? true:false;

$(function() {
if(UA_iPhone || UA_iPad){
$('a').bind("mouseover",function(ev){
var link = $(this).attr("href");
var target = $(this).attr("target");
var linktype = link.substring(0,1);
if(linktype != "#"){
if(target == "_blank"){
window.open(link);
} else{
location.href = link;
}
}
});
}
});

このjsを追加したページがこちら
iOS用の処置をしたサンプルページ
 
QRはこちら
chart2

iPhoneでタップでも一応hoverで1タップ消化されずに飛ぶようになった。



■そもそもhoverでopacity等は使わないほうがいいかもしれない

上記のjsで対処はできたけど、もしiOSが今後アップデートされていってもこの問題が残るようなら、 hover{opacyty:●}という記述は使わないほうがよさそう。

半透明にしたいなら、jsでやるとか。


なんかもっと良いやりかたあるんかな。

 






 

bxsliderでレスポンシブ利用時に表示エリアが1枚になったときにガクンとずれるバグの対策

スライダーライブラリのbxsliderをつかって複数画像のスライダーを作っていた。

こういうやつ
blog20150831

設定はこんな感じだ

$('#bnrSlider').bxSlider({
mode: 'horizontal',
pager:true,
auto: true,
slideWidth: 300,
speed:1000,
pause:5000,
moveSlides:1,
minSlides: 1,
maxSlides: 3,
slideMargin: 40
}); 
3枚のバナーをみせて、スライドするときは1枚ずつスライドさせるっていう設定だね。

bxsliderはレスポンシブに対応していて、画面サイズが短くなると表示枚数を減らすといった臨機応変対応をしてくれる。

そのあたりをやってくれるのが、minSlidesやmaxSlidesだ。 

画面をぎゅーっと縮めてスマホサイズにするとこうなる

blog201508312

便利なライブラリだね。

でもここでバグがおきた。

 画面をぎゅーっと縮めてスマホサイズでみたときには、スライダーで表示されてるバナー画像は1つになっているのだけれど、このときに変な挙動をする。


・ 下のページャーアイコン(◯◯●ってやつ)と画像があってない。ズレてる。
・最後の画像が表示されたあとに、最初の画像にパっと突然切り替わってしまう。んでガクンって感じにみえる。
・ずっと右に動き続けてて欲しいのに、3枚目→1枚目を表示するときにぎゅーんて巻き戻したみたいに逆方向に一気に動く


パラメータをいろいろいじってみたら、 これを引き起こしているパラメータが2つあった。

maxSlides:3
slideMargin:40

の2つ。

1つの表示エリアしかないのにmaxSlidesが2以上の数字が入ってるとばぐる。
slideMarginが設定されてるとなぜかバグる。

なので、ためしに
maxSlides:1
slideMargin:0

にしてみたら直る。

でもレスポンシブなのでpc表示時には、3つのバナー画像を出したいし、marginもとりたい。

困った。

困り果てて、しょうがないので分岐を書いて対応することにした。

もともとのやつ 

$('#bnrSlider').bxSlider({
mode: 'horizontal',
pager:true,
auto: true,
slideWidth: 300,
speed:1000,
pause:5000,
moveSlides:1,
minSlides: 1,
maxSlides: 3,
slideMargin: 40
}); 


分岐を書いて対応したやつ

var bnrSlideOpt = {
mode: 'horizontal',
pager:true,
auto: true,
slideWidth: 300,
speed:1000,
pause:5000,
moveSlides:1,
minSlides: 1,
maxSlides: 3,
    slideMargin: 40
}
var bnrslider = $('#bnrSlider').bxSlider(bnrSlideOpt);
topBnrSlider();
function topBnrSlider(){
if(window.innerWidth < 750){
bnrSlideOpt['maxSlides'] = 1;
bnrSlideOpt['slideMargin'] = 0;
} else{
bnrSlideOpt['maxSlides'] = 3;
bnrSlideOpt['slideMargin'] = 40;
}
bnrslider.reloadSlider();


ちょっとわかりにくいかもしれないので、説明をする。

まずbxsliderのオプション(パラメータのやつら)は配列の形で一式変数にいれちゃう

var bnrSlideOpt = {ここにオプションかいていく}

次に発動させるbxsliderを変数にいれとく

var bnrslider = $('#bnrSlider').bxSlider(bnrSlideOpt);

↑オプションはbnrSlideOptの形でまとめてあったから1行でいけるね。

それで、bxsliderを実際に呼び出すわけなんだけれども、そのときに分岐を書く。


if(window.innerWidth < 750){
bnrSlideOpt['maxSlides'] = 1;
bnrSlideOpt['slideMargin'] = 0;
} else{
bnrSlideOpt['maxSlides'] = 3;
bnrSlideOpt['slideMargin'] = 40;
}

 
 ウィンドウサイズが750px以下だったら、maxSlides:1 slideMargin:0
にしてしまう。

750pxという数字は各自変えてもらえればいいと思う。

僕の場合は750pxでスライダー枠を1つにする分岐をcss側で書いていたので それと対応させただけ。

んで 最後に設定しなおされたオプションでスライダーを再読み込み。

bnrslider.reloadSlider();


こういう流れ。

レスポンシブを考えると

$(window).resize(function(){
topBnrSlider();
}); 

も書いておくとより良いと思う。


アミーゴ! 
記事検索

リモキュー

お仕事のご依頼・お問い合わせはこちら

コーディングのお仕事が得意です。

https://twitter.com/tacshock
タグクラウド
QRコード
QRコード
  • ライブドアブログ