スマホサイト作っててハマったことメモ(2013/06/13時点)

window.scrollTo(0, 1);でアドレスバーが隠れない

以下のようにJavaScriptからスクロール位置をY軸方向に1px動かすことで、アドレスバーを引っ込めることができますが、
これが動くことは動くんですが、すぐに隠れずに、4〜5秒ぐらいしてからヒョコッと隠れる。

自分で作った他のサイトでは、すぐに引っ込むのになんでだろう、、、と

(function () {
  $(window).bind("load", function (e) {
    setTimeout(doScroll, 100);
  });

  $(window).bind("orientationchange", function (e) {
    // e.orientation === "portrait" ? "縦" : "横"
    setTimeout(doScroll, 100);
  });

  function doScroll() {
    if (window.pageYOffset === 0) {
      window.scrollTo(0, 1);
    }
  }

  window.doScroll = doScroll;
})();

そもそもjQueryMobileを使っていると内部的に↑のようなことはしてくれるので、自分で実装する必要はないのですが、
jQueryMobileを使ってもアドレスバーが引っ込むタイミングが遅い!

早く引っ込むサイトとそうでないサイトを見比べると、Mobile Safariのアドレスのところに「リーダー」というのが出てる。
(あやしい、、、)

そこで、このリーダーを消す作業をしました。

  1. JavaScript疑う
  2. CSSを疑う
  3. 心が折れる
  4. htmlを削り始める

この最後でbodyの中身をスッカラカンにすると、リーダーがなくなり、最終的にarticleタグが全体を囲っているとどうもリーダーが出ちゃう可能性が高い
という結論に到達しました。
とりあえずdivにしたんですが、それでもダメな場合があるらしく、そのあたりは以下の記事がわかり易かったです。

リーダーのせいでmobile safariのアドレスバー隠しが遅れる – < /gecko >

jQueryMobileでTransitionが効かない場合がある

jQueryMobileの特徴として、次の画面をAjaxで取得しDomに追加し、アニメーションしながら遷移できる。
というのがありますが、ここでの醍醐味は、アニメーションで遷移できる点かなーと思っています。

このアニメーション効果、つまりTransitionがつかずに遷移する場合があったので、ここにメモ。

Transitionがつかないと、Ajax遷移には間違いないんですが、一瞬で次の画面に行くので、
普通に画面遷移しちゃったのかな?と思うぐらいよくわからない。

そしてこれが起きる原因は、サイトの全体の高さがある一定以上を超える場合に起きる可能性が高い。

以下にjQueryMobileのコードから抜粋してみました。

Line: 3652

Math.max( $.mobile.window.scrollTop(), toScroll ) &gt; $.mobile.getMaxScrollForTransition()

Line: 3771

defaultGetMaxScrollForTransition = function() {
  return $.mobile.getScreenHeight() * 3;
};

Line: 3797

// Set the getMaxScrollForTransition to default if no implementation was set by user
$.mobile.getMaxScrollForTransition = $.mobile.getMaxScrollForTransition || defaultGetMaxScrollForTransition;

$.mobile.getScreenHeight() * 3;ここの部分が該当の箇所だと思うのですが、
スクロール位置が、画面のScreenの高さを3倍したものを超えた状態でAjax遷移をするとTransitionが効かないという感じです。

実際にconsole.logで出力しながらやってみたら、まさしくそのとおりでした。

ここは割り切るか、画面の高さを縮めるか、という感じですかね。
個人的にはこの配慮はパフォーマンスを意識して書かれていると思うので、Transitionが効かないときがあってもいいのかなーと思っています。
普通の画面遷移よりはどのみち速いので。

jQueryMobileのローディングにアニメーションgifが表示されない

CoreなCSSだけあればよかったので、「jquery.mobile.structure-1.3.1.css」を読み込んでいたのですが、
どうもアニメーションgifの部分のCSSクラスが定義されていなく、ローディングが一瞬出るのですが中身のグルグルがない状態でした。

なので、本体のCSSから以下をコピーしてきました。

/* loading icon */
.ui-icon-loading {
  background: url(images/ajax-loader.gif);
  background-size: 46px 46px;
}

これで動いたけど、みんなどうしているのかな?

jQueryMobileとanimate.cssの相性が悪い

animate.cssに書かれている以下の内容がどうもダメっぽく、Transitionでアニメーションしたあとに少しチラつきがでちゃいます。

body { /* Addresses a small issue in webkit: http://bit.ly/NEdoDq */
  -webkit-backface-visibility: hidden;
}

なので、animate.cssはインクルードせずにSassを使って以下のように組み込みました。

@include keyframes(bounceIn) {
  0% {
    @include transform(scale(.3));
    @include opacity(0);
  }
  60% {
    @include transform(scale(1.05));
    @include opacity(1);
  }
  80% {
    @include transform(scale(.9));
  }
  100% {
    @include transform(scale(1));
  }
}

Sass楽ちん!

スマートなrequestAnimationFrameのクロスブラウザ対応

スマートかどうか微妙ではありますが、
またもCSS 3D Cloudsのコードを読んでて発見したコード。
いままで以下のようにコードを使っていたんですが、

window.requestAnimFrame = (function(){
    return  window.requestAnimationFrame       ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame    ||
            window.oRequestAnimationFrame      ||
            window.msRequestAnimationFrame     ||
            function( callback ){
              window.setTimeout(callback, 1000 / 60);
            };
  })();

こっちの書き方のほうがキレイだなーということで今後はこっちを使ってみます。
コードの雰囲気からすると↑のほうが把握しやすいですが。

(function() {
  var lastTime = 0;
  var vendors = ['ms', 'moz', 'webkit', 'o'];
  for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
    window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
    window.cancelRequestAnimationFrame = window[vendors[x] + 'CancelRequestAnimationFrame'];
  }

  if (!window.requestAnimationFrame)
    window.requestAnimationFrame = function(callback, element) {
      var currTime = new Date().getTime();
      var timeToCall = Math.max(0, 16 - (currTime - lastTime));
      var id = window.setTimeout(function() { callback(currTime + timeToCall); }, timeToCall);
      lastTime = currTime + timeToCall;
      return id;
    };

  if (!window.cancelAnimationFrame)
    window.cancelAnimationFrame = function(id) {
      clearTimeout(id);
    };
}())

github

スマートなrequestAnimationFrameのクロスブラウザ対応 — Gist

Foundation HTML5 Animation With Javascript (Foundations Apress)
Billy Lamberta
friendsofED
売り上げランキング: 96806