jQueryゼロから / ナビ付きスライドショー

前回のスライドショーによくあるナビつけてみることに。
任意の写真をクリックで選べるようにします。

ナビをクリックすると自動再生されてるアニメーション(フェードイン・フェードアウト)を停止して、指定のスライドを表示、しばらく放置すると自動再生再開するようにします。
アニメーションは setInterval で再生しているので、clearInterval にて停止するだけ。アニメーション再開は一定時間操作しない時間帯を持ちたいので setTimeout で待機するようにします。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var interval;
// スライド再生
function startSlide(wait){
    wait = wait | 0;
    var intervalTime = 3000;
    setTimeout(function(){
        interval = setInterval(function(){
            // アニメーション処理
        }, intervalTime);
    }, wait);
}

// スライド停止
function stopSlide(){
    clearInterval(interval);
}

ナビのロールオーバーとかはJavaScriptのイベントじゃなく、CSSで設定するようにしました。
あとは意外にそんな前のと変わらんので、jQueryのプラグインにして、$(セレクタ).slide(オプション) でスライドショーになるようにしてみた。
サンプル

ナビ付きスライドショー – jsdo.it – share JavaScript, HTML5 and CSS

よくあるWordPress / 投稿の最初か最後を判定する

投稿を一覧表示する際にデザイン上、リストの最初と最後が必要なときに。
記事ループ内だと $wp_query を使って下記のように判定します。
※テンプレ内で使用することを想定

1
2
3
4
5
6
<?php if ($wp_query->current_post === 0) : ?>
    <li class="first">
<?php elseif ($wp_query->current_post === $wp_query->post_count - 1) : ?>
    <li class="last">
<?php endif; ?>
...

自分で一覧取ってくる時もWP_Queryで取得していればだいたい同じ。

1
2
3
4
5
6
7
8
9
10
11
<?php
$result = WP_Query(array('posts_per_page' => 10)); // 適宜欲しい内容を取得
while ($result->have_posts()) {
    $result->the_post();
    if ($result->current_post === 0) {
        echo '<li class="first">';
    } elseif ($result->current_post === $feed->post_count - 1) {
        echo '<li class="last">';
    }
...
}

よくあるWordPress / トップを固定ページにした時に投稿一覧を表示するには

すげえ基本的なことなんだけど、忘れちゃうのでメモ。
CMSとして使う時にトップページはWordPressの固定ページにしたいんだけど、デフォルトのトップはお知らせ一覧として使いたいよって時の設定方法。
結果から言うと、基本機能で出来るんだけどテンプレートで解決しようとして迷わないように。

まずは、固定ページ機能から「トップページ」と「お知らせ一覧ページ」(デフォルトトップの投稿一覧を使いたいページね)を作成します。
トップはそれなりに作るとして、お知らせ一覧は本文は無視されるのでブランクで良いす。

WordPress管理画面の「設定 → 表示」にあるフロントページの表示を下記のように設定します。

そうなのよね、単に「投稿ページ」の所に設定するとそこがこれまでのトップと同様に投稿一覧を表示してくれるようになるのね。
トップを固定ページに差し替えるのはよくやってたけど、こちらは見逃してたわ。

JavaScript で cron ちっくに指定時間で実行

毎時0分に実行、みたいな処理したいなと思って調べた。
jsCron というのがよく使われているみたい。
cronちっくに 0 * * * * Function() のように指定するとその時間に実行する、と。
jsCron, portando Cron a Javascript | aNieto2K

ソース見てみると setInterval で現在時刻をチェックして、指定時間と一致するなら実行、という感じ。
定期的に時刻指定で実行するときは参考に。

応用してこんなのも。
サンプル (HTML5 audioでチャイム鳴らす)

下記は簡単なサンプル。(00秒に赤い★が表示されるだけ)
一秒以下の誤差はざっくりと無視してます。

JavaScriptで毎時実行 – jsdo.it – share JavaScript, HTML5 and CSS

HTML5 / Audio 定期的に再生する

あんまり利用しないケースかもだけど audio 再生で同じ音を繰り返し再生する時にちょっとした使い分けを。

まずは普通に audio 読み込み。

1
2
3
4
5
6
7
8
9
10
11
12
try {
  var audio = new Audio('');
  if (audio.canPlayType('audio/ogg') {
    audio.src = 'chime.ogg';
  } else if (audio.canPlayType('audio/mp3') {
    audio.src = 'chime.mp3';
  } else {
    throw('非対応');
  }
} catch(e) {
  alert('非対応');
}

これを例えば定期的に同じ音を再生しようと下記のようにします。

1
2
3
setInterval(function(){
  audio.play();
}, 1000);

この時、繰り返し間隔が短い場合、再生中の音が終わるまでは次の音は再生されません。
これを意図的に音を中断して、再生したい場合は下記のようにします。

1
2
3
4
setInterval(function(){
  audio.load();
  audio.play();
}, 1000);

audio.load() で初期状態にリセットされるので、また先頭からの再生になります。
audio.currentTime = 0; という方法もあるけれど、一度も再生されていない時に使用すると firefox でエラーとなるみたい。
この時、audio.mute や audio.volume はそのまま。

続・jQueryの書き方

ノンプログラマに jQuery のおまじない部分でつまずくと言われたのと、自分も少し使い分けが整理できてきたのでまとめてみる。意外とルーブとか条件判定は悩まんけど、その前後にあるごにょごにょした部分がひかかるのだとか。

誤解を恐れずにまとめると JavaScript はグローバル変数を汚染しやすく、コンフリクトしたら嫌なので回避しようぜってコトよね。
んで、その書き方がいくつかありますよと。

<head> タグ内でサクッと済ませたい時

1
2
3
jQuery(function($){
    // $('#id').click() とかココに書いてく…
});

Onload前に実行したい場合にこう書いてます。
<head> タグ内だけじゃなく別ファイルでも使えるけど、ちょっと試したい時とか、簡単な処理の時によく使うかな。

$(function(){…}); って書き方もあるけど、古くは prototype.js と競合したり、気が付けばWordPressのデフォルトで呼ばれる jQuery が noConfrict になってて使えなかったりするので、こう書くようにしてます。
また、noConfrict をあえて宣言して $ を使わず、$j = jQuery; として置き換えたり、潔く全て jQuery(…) で書いてもいいんだけど、$ で書くのが手軽だし最初にこう書くだけで、その中ではいつも通りというのが楽なんよね。

先読みするファイル内で jQuery 使いたい時

1
2
3
(function($){
    // $('#id').click() とかココに書いてく…
})(jQuery);

自前の関数とかでも jQuery 使いたい時とか。別ファイルだと読み込みのタイミングで評価されるので、実行部分よりも関数とかあらかじめ指定する時によく使うかな。
(function(){})(); って書き方は function ooo(){…} 的な指定と ooo(); って実行をまとめて書いてるだけです。これに引数として jQuery を渡して、内側では $ で記述できるようにしてます。

あ、でも、関数定義して他の js ファイルからもこれを利用したい場合は、そのままでは使えません。その場合は、下記のようにしてあえてグローバルにしたりします。

1
2
3
4
5
6
(function($){
    function ooo(){
        ...
    }
    window.ooo = ooo;
})(jQuery);

※蛇足かも…

jQuery のプラグイン

1
2
3
jQuery.fn.ooo = function(){
...
};

これプラグイン書かないと使わないので、なんでこんな書き方なんだという説明だけしとく。
jQuery も当たり前にコンフリクト対策してあって、グローバル変数は jQuery と $ しか使わないように工夫されてます。プラグインであってもこのルールに乗っかれるようになってて、jQuery.fn.ooo のように指定すれば、$(‘#id’).ooo() といった統一の書き方になるように作られてます。

たまにコンフリクト考えてなくて $.fn.ooo から書かれてるプラグインあったりするので、その場合は2番目の方法でプラグイン指定を囲んでやると良いす。一行目に (function($){ 、最後の行に })(jQuery); って書けばうまく行く事もあれば、行かない事もあるよ。

あ、ちなみに JavaScript では下記2つは大体同じ意味です。
※厳密には評価されるタイミングが違う

1
2
3
4
5
6
7
function ooo() {
...
}

var ooo = function(){
...
};

うーん、あんまりまとまってないかな?
んでも、書き方はイロイロあるけど簡潔に書かれてるものが好まれてるだけと思う。

HTML5 / Canvas で拡大・縮小・回転

前回、CSS3とJavaScriptでもやったので今度はCanvasでやってみる。

変換系は移動が translate(x, y)、回転が rotate(r)、拡大・縮小が scale(sx, sy) と用意されてます。
が、回転の中心が左上になるため、最初に対象物の中心にずらす移動が必要です。

1
2
3
4
5
ctx.translate(x, y);
ctx.rotate(r);
ctx.scale(sx, sy);
ctx.translate(-w/2, -h/2);
ctx.fillRect(0, 0, w, h);

変換は実行する逆順に処理していくことに注意。

一連の処理をまとめて行列で指定できる setTransform もあります。上記の処理を同じように行列で指定すると下記のようになります。
※前もって行列計算してあります

1
2
3
4
5
6
7
8
9
10
11
var sin = Math.sin(r);
var cos = Math.cos(r);
var m = [
    sx * cos,
    sx * sin,
    -sy * sin,
    sy * cos,
    -sx * cos * w/2 + sy * sin * h/2 + x,
    -sx * sin * w/2 - sy * cos * h/2 + y
];
ctx.setTransform(m[0], m[1], m[2], m[3], m[4], m[5]);

これでフレームごとに各値を変えていけばアニメーションにも使えます。
サンプル

Canvas Transform – jsdo.it – share JavaScript, HTML5 and CSS

HTML5 / Audio

Video同様ブラウザごとに違いがある模様。下記を参考にしながら試してみた。
ブラウザーのネイティブなオーディオ – html5doctor – HTML5.JP
ASCII.jp:HTML5 Audioで作るiTunes風音楽プレイヤー|古籏一浩のJavaScriptラボ

まずはファイルのサポート形式が違うので、Firefox, Opera 用に ogg、Safari 用に mp3 を用意します。Chrome は両方OK。
※試したバージョンは Chrome 12.0.742.122, Safari 5.1, Firefox 5.0.1, Opera 11.50

<audio> タグと <video> タグは src の指定を複数できるけど、これに未対応な(1個目しか読まない) Firefox を優先して下記のように記述。

1
2
3
4
5
<audio controls autobuffer>
    <source type="audio/ogg" src="audio.ogg" />
    <source type="audio/mpeg" src="audio.mp3" />
    <p>非対応です</p>
</audio>

controls で再生ボタンなどのインターフェイスが表示され、autobuffer でバッファしてくれます。他にも autoplay でOpera以外は自動再生、loop でFirefox以外はルーブ再生します。

それから、source は type を指定しとくと、ファイルを読み込む前に再生可能か判断してくれるそうです。指定しないと読み込んでから判断するみたいなので、やった方がイイよね。

controls 指定しないと画面に何も表示されんけどどうすんのと思うけど、ちゃんと JavaScript で制御できます。getElementById とかで取得して play() や stop() が使えます。
※例は jQuery で onload 時に再生

1
2
3
4
5
6
<script>
jQuery(function($){
    var audio = $('#audio')[0];
    audio.play();
});
</script>

他にも JavaScript で生成できます。

1
2
3
4
5
6
7
8
9
10
11
12
13
try {
    var audio = new Audio('');
    if (audio.canPlayType('audio/ogg')) {
        audio.src = 'audio.ogg';
    } else if (audio.canPlayType('audio/mpeg')) {
        audio.src = 'audio.mp3';
    } else {
        throw '非対応です';
    }
    audio.play();
} catch(e) {
    alert('非対応です');
}

Opera が引数なしの new Audio() だとNGなので、Audio(”) のようにします。あとは、ブラウザの差異があるので canPlayType で再生できるか判断する必要があります。
音声ファイルが大きい時は Image() の時と同様に preload した方がイイみたい。

サンプル

音は下記サイトのものを使用しました。
音楽素材/魔王魂

Transform / 回転・拡大縮小

2012.05.31 追記
ブラウザ判定がうまく動かなくなってたので、transform が使用できるかで判定するように変更しました。
機能の判定はブラウザのバージョンアップで変わってくので別の用途には使うべきじゃないね…

CSS3どころかCSSも普段あまりいじらないけど、回転・拡大縮小できる transform があるというコトなのでやってみる。
んでも、まだまだブラウザごとに実装が異なるらしく、jquery-css-transform.jsjquery-animate-css-rotate-scale.js っていう jQuery プラグイン使いましょうってのが多かったので、これを参考にしてみた。

CSS3では、transform: rotate(30deg) で要素を時計回りに30度回転、transform: scale(1.5) で要素を1.5倍とかいった指定が可能。んで、これが今んとこブラウザによって違ってて Chrome/Safari なら -webkit-transform、Firefox なら -moz-transform という具合。

これを jQuery で設定するには下記の感じ。JavaScript と CSS でパラメータ名が若干違うのに注意。

1
2
3
4
5
6
7
8
// Chrome / Safari (webkit) の場合
$('#target').css({ WebkitTransform: 'rotate(30deg) scale(1.5)' });
// firefox の場合
$('#target').css({ MozTransform: 'rotate(30deg) scale(1.5)' });
// Opera の場合
$('#target').css({ OTransform: 'rotate(30deg) scale(1.5)' });
// IE9 の場合
$('#target').css({ msTransform: 'rotate(30deg) scale(1.5)' });

rotate だけ、scale だけでもよいす。座標移動の translate もあるけど割愛。
これをブラウザ判定して使い分けます。jquery-css-transform.js だと transform, WebkitTransform, MozTransform,… と順にプロパティがあるかループで調べて判定してます。正式に tranform に対応したらそちらで処理するようにって事だと思う。(※2012.05.31追記 jquery-css-transform.jsのやり方がベンダープレフィックスが取れた時にも対応できるのでよりイイです)

パラメータの指定方法見ると、値に数値以外の文字もあるので jQuery の animate メソッドが使えないんよね。それで、jquery-animate-css-rotate-scale.js も別途用意されてる模様。

んで、試しに画像に適用したのが下記サンプルです。一応、プラグイン使わずにやってみた。
サンプル

もやもや – jsdo.it – share JavaScript, HTML5 and CSS

jQueryゼロから / slideToggle

クリックで開いたり閉じたりするのをサクっとつくるのに slideToggle 使うと便利。
slideUp, slideDown 組み合わせてもいいんだけど、こっちのが楽ね。

1
2
<span id="slide">ここをクリック</span>
<p id="target">なんか表示</p>

slideToggle にも引数でアニメーションの速度指定できます。
ただ、slideUp, slideDown の速度を使い分けるとかは出来ないんかな。

1
2
3
$('#slide').click(function(){
    $('#target').slideToggle('slow');
});

サンプル

jQuery Toggle Slide – jsdo.it – share JavaScript, HTML5 and CSS