22
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

jQuery その先のUIアニメーション

Last updated at Posted at 2015-03-08

jQueryを使わないでアニメーションしたくはないでしょうか

別に興味ないですか。私は興味あります。

ブレイクスルーJavaScript フロントエンドエンジニアとして越えるべき5つの壁―オブジェクト指向からシングルページアプリケーションまでを注文しました。

jQueryその先へ、とかそういう文言が今熱いのか。
積ん読たまってて読めるかまったくわからないんですけど。

書籍とは離れますが、jQuery を使用しないでどこまでアニメーションに耐えられるのか、ちょっとやってみました。

https://github.com/tkdn/postjQueryAnimate
※ jQuery は2~使ったので、IE10~,Chrome,Safari,Firefoxいずれも最新くらいがターゲット

Velocity.js という選択

最初はCSSアニメーションでなんとかと思ってたんですが、途中で挫折、jQueryの.animateを使わないでFPSを設定、数値の変更なんか自前でやってられないのと、パフォーマンスが優れているということで、Velocity.jsを選びました。

jQueryのプラグインであるかのような誤解が生まれていますが、スタンドアローンとしても使えます。今回は公式にもあるような使い方で、browserify で。

2つのソース

jQueryだとこんな感じ

$(function() {
  var action = (function(jqObject) {
    var content = jqObject.next('.content');
    var contentParent = content.parent();
    if(contentParent.hasClass('active')){
      content.slideUp('250',function(){
        contentParent.removeClass('active');
      });
    } else {
      contentParent.addClass('active');
      content.slideDown('250');
    }
  });
  $('.jq-accordion').on('click', function(event) {
    event.preventDefault();
    action($(this));
  });
});

actionでアコーディオンに関する動きをひとまとめにしてます。動きをバインドさせたい要素(jQueryオブジェクト)を引数として、

  • 隣接する次要素.contentをアコーディオンの内容とし、これをアニメーション(slideUp,slideDown)
  • その親要素(リポジトリではli)に活性非活性のクラスactiveをtoggleさせ、UIとしての状態を明示、アクションのshow/hideを決めてる
  • 最後に.jq-accordionの要素にactionをバインドさせてる

みたいな感じです。ありがちですね。

これをVelocity.jsとブラウザネイティブでやる

Velocity.js をモジュールとしてロード、グローバル空間にexportしてやる。npm で検索して出てくる、velocity.jsは全く別物なので注意。velocity-animateが本物。

リポジトリではnpm installしたら必要なの全部落ちてきます。

var Velocity = require('velocity-animate');

魔法のrequireでOK。あとはbrowserifyしてあげるだけ。

ソース

document.addEventListener('DOMContentLoaded', function(event) {
  var accodionContents = this.querySelectorAll('.js-accordion + .content');
  for (var i = 0; i < accodionContents.length; i++) {
    var height = accodionContents[i].offsetHeight;
    accodionContents[i].setAttribute('data-height', height);
    accodionContents[i].style.height = 0;
  }
  var action = (function(elemObject){
    var content = elemObject.nextElementSibling;
    var contentParent = elemObject.parentElement;
    var contentHeight = content.getAttribute('data-height');
    if(contentParent.classList.contains('active')){
      contentParent.classList.remove('active');
      Velocity(content, { height: 0 }, 250);
    } else {
      contentParent.classList.add('active');
      Velocity(content, { height: contentHeight }, 250);
    }
  });
  var actionElem = this.querySelectorAll('.js-accordion');
  for (var i = 0; i < actionElem.length; i++) {
    actionElem[i].addEventListener('click',function(event){
      event.preventDefault();
      action(this);
    });
  }
});

jQuery使ってるとおまじないのように、$(function(){...});でDOMREADYで実行させてるのもちゃんとやる。documentのDOMContentLoadedイベントで実行です。

あらかじめ隠しておいた要素に height: auto; を適用するのは無理

jQueryの時とちょっと違うのは、高さを考えないとうまくいかないってことでした。

Velocity(elem, { height: 'auto' }, 250);

みたいなことは出来ない。jQueryの時は要素をdisplay:none;していてもアニメーションできていたけど、Velocity.jsではできない。

ちなみに、CSS3 transition はlength, percentageしか受け付けないのでもちろんautoは値として無理、max-heightmargint-topのネガティブマージンでなんとかしてるのを見たんだけど、もうcssでごちゃごちゃやりたくないんですよ。

というわけで、jsでなんとかした。

  var accodionContents = this.querySelectorAll('.js-accordion + .content');
  for (var i = 0; i < accodionContents.length; i++) {
    var height = accodionContents[i].offsetHeight;
    accodionContents[i].setAttribute('data-height', height);
    accodionContents[i].style.height = 0;
  }

そもそもdisplay:none;しない、DOMloaded時には高さがある状態を作って、そいつらの高さをdata-height属性としてDOMに埋め込み、style属性にheight:0;をセット、をforで回す。全然スマートじゃない気がするけど。

あとは、IE8.9 あたりじゃ使えないのを使います。classListとかそうですね。

ハマりかけたaddEventListenerのところ

document.querySelectorAll('.js-accordion').addEventListener('click',function(){
...
});

みたいなことしたらできないですよね。document.querySelectorAll('.js-accordion')が返してくるのdocumentにある要素全ての配列だから。なので、回して各要素にバインドさせる。

ちょっと気になってるところ

jQueryでもVelocityでもdurationは250msのはずなんだけど、Velocityの方が早い気が…。


やってみて思ったんですが、ベストはjQuery+Velocityで今のところはいいじゃないか、とも。本末転倒ですかそうですか。

本日は以上です。

参考

22
21
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?