ホーム画面の壁紙を切り替える3(フリップ編)
前回までに、「フェード」と「スライド」という切り替え方法による壁紙チェンジャーを紹介しました。
フェードは透過率の変化のみで、「動き」の変化がないため、違和感はありませんでした。
スライドは、実機で確認された方もいると思いますが、動きがスムーズではありません。まるでiPhoneユーザーがアンドロイドを使ってみた時に感じる違和感のようです。
さすがに作り直したくなるくらいですね。
今回は、その場で回転する「フリップ」による壁紙チェンジャーを紹介します。
基本ファイルとその確認
サンプルファイル構成
今回作るサンプルウィジェットを含むテーマファイルの基本構成は右図の通りですが、前回のスライド編に手を加えただけのものです。
といっても、スライド編の完成形からの変更ではなく、作り直す前(slide5)のファイルと比較して下さい。
ファイルのダウンロードはこちらーー>ダウンロード
では、ファイルを1つ1つ見ていきましょう。
サンプルHTML
HTMLから見ていきましょう。
以下に示すのが、Wallpaper.htmlの中身(ソース)です。
<html>
<head>
<meta name="viewport" content="width=device-width,minimum-scale=0.5,initial-scale=0.5"/>
<script src="./script.js" type="text/javascript"></script>
<link href="./style.css" rel="stylesheet" type="text/css" />
</head>
<body onload="init()">
<img src="images/img_01.jpg"/>
<img src="images/img_02.jpg"/>
<img src="images/img03.png"/>
<img src="images/img04.png"/>
<img src="images/apple1.gif"/>
<img src="images/ume.gif"/>
<img src="images/candybars.tiff"/>
<img src="images/apple2.tiff"/>
</body>
</html>
サンプルHTMLソース1
スライド編と何も変わりません。
サンプルJavaScript
では、JSファイルを見ていきましょう。
以下に示すのが、script.jsの中身(ソース)です。
スライド編と違う部分を赤くしています。
//var delay;
var imageArray;
var imageCount ;
var current ;
function init() {
interval = 5;
// delay = 3;
imageArray = document.getElementsByTagName("img");
imgCount = imageArray.length;
current = 0;
wait();
}
function wait() {
setTimeout(flip, interval * 1000);
}
function flip() {
prev=(current + imgCount-1) % imgCount;
next=(current + 1) % imgCount;
imageArray[prev].className = 'stay';
imageArray[current].className = 'out';
imageArray[next].className = 'in';
// current = next ;
imageArray[current].addEventListener(
"webkitTransitionEnd",
flip_end,
false
);
}
function flip_end() {
imageArray[current].removeEventListener("webkitTransitionEnd",
flip_end,
false);
current = next ;
wait();
}
サンプルJavaScript1
基本的にはスライド編と何も変わりません。
フリップ編へ移行するために、"slide"を"flip"にしただけです。
サンプルスタイルシート
margin: 0px;
padding: 0px;
border: 0px;
}
body {
width: 640px;
height: 960px;
}
img {
position: absolute;
top: 0px;
left: 0px;
width: 640px;
height: 960px;
-webkit-transition-property: -webkit-transform;
-webkit-transition-duration: 3s;
opacity: 0;
-webkit-transform: rotateY(-180deg);
-webkit-backface-visibility: hidden;
}
img.out {
-webkit-transform: rotateY(180deg);
opacity: 1;
}
img.in {
-webkit-transform: rotateY(0deg);
opacity: 1;
}
img.stay {
-webkit-transform: rotateY(-180deg);
opacity: 0;
}
サンプルスタイルシート1
次に、スタイルシート(style.css)を見ていきましょう。
こちらもjavascriptと同じで、スライド編からフリップ編への移行作業のみです。
アニメーションさせるプロパティですが、移動させるために使っていたleftを変更します。回転はrotateYを使いますが、回転も変形の一部ですので、プロパティ自体はtransformを使います。
このtransformも、ベンダープレフィックスである-webkit-を付加します。
今回のポイントは、2つあります。
1つ目は、裏側を見せないことです。
裏返った画像は、反転した状態でしっかり表示されるので、裏面表示の可否を指定できるbackface-visibilityというプロパティを導入しています。
2つ目は、必要のない画像を消していることです。
スライドのままz-indexで奥に配置していたら、思いっきり表示されてしまったので、「消す」という表現は違いますが、opacityで見えなくしています。
回転角は、deg指定で分かりやすいと思います。
回転方向を考えて、マイナス側の裏面から回転し、その回転方向のまま裏へ回転させています。
stay(-180deg) ー> in(0deg) ー> out(180deg) といった具合です。
これでフリップによるアニメーションが実現できます。
サンプル表示
基本サンプルファイルは、個々でダウンロード&実行して確認していただきたいのですが、スクリーンショットを紹介します。
変化前
回転開始
裏返ってなお回転
切り替え終了
とりあえず4枚紹介しましたが、こちらはなおのこと個々の実機で確認していただくのが一番かと思います。
今回のサンプルファイルのダウンロードは、こちらからどうぞーー>ダウンロード
構造を大幅に改良する
ではここで、持ち越しとなっていた課題に取り組んでいきましょう。
これまではずっと、HTMLに必要な画像を配置し、Javascriptでその画像を操作していました。
しかし、切り替えたい画像は、その種類も数も人それぞれです。
ここでのサンプルのように数枚の画像なら問題ないのですが、やはり数が増えると、その画像をすべて読み込んでからの動作になるので、とても重くなってしまいます。
そもそも配置する画像は、切り替わるための2枚だけで良いのではないでしょうか?
切り替わったら、それが切り替えられる側になるだけの話なのではないでしょうか?
どうせ、切り替え中の2枚以外は消すんだし・・・
ということで、HTMLに配置する画像は2枚だけにしましょう。
そして、その2枚に表示される画像をjavascriptで指定するという形にしましょう。
HTMLの変更
変更部分を赤くしています。
<html>
<head>
<meta name="viewport" content="width=device-width,minimum-scale=0.5,initial-scale=0.5"/>
<script src="./script.js" type="text/javascript"></script>
<link href="./style.css" rel="stylesheet" type="text/css" />
</head>
<body onload="init()">
<img id="front"/>
<img id="back"/>
</body>
</html>
サンプルHTMLソース2
画像が2枚になり、それぞれに"front"と"back"というidを付けました。
フリップによる切り替えなので、表と裏を意識できるように命名しました。
javascriptの変更
変更部分を赤くしています。
var imageArray = ["img_01.jpg",
"img_02.jpg",
"img03.png",
"img04.png",
"apple1.gif",
"ume.gif",
"candybars.tiff",
"apple2.tiff"];
var imageCount;
var current;
var next;
var elm0;
var elm1;
function init() {
interval = 5;
imgCount = imageArray.length;
current = 0;
next = 1;
elm0 = document.getElementById("front");
elm1 = document.getElementById("back");
elm0.src = "./images/" + imageArray[current];
elm0.className = "stay";
elm1.src = "./images/" + imageArray[next];
elm1.className = "stay";
wait();
}
function wait() {
setTimeout(flip, interval * 1000);
}
function flip() {
elm0.className = "flip";
elm1.className = "flip";
elm1.addEventListener(
"webkitTransitionEnd",
flip_end,
false
);
}
function flip_end() {
elm1.removeEventListener(
"webkitTransitionEnd",
flip_end,
false);
current = next;
elm0.src = "./images/" + imageArray[current];
elm0.className = "stay";
next=(current + 1) % imgCount;
elm1.src = "./images/" + imageArray[next];
elm1.className = "stay";
wait();
}
サンプルJavaScript2
HTMLで画像を表示させない代わりに、javascriptで画像を指定するので、今回のjavascriptは大幅な変更があります。
その大幅な変更には2つのポイントがあります。
では、1つ目のポイントから見ていきましょう。
画像を格納する変数でしたが、今回から、画像のファイル名を格納する配列変数になります。
変数宣言と同時に、画像ファイル名を代入しています。
この変更に伴い、画像を格納しておく変数の変更が2つ目のポイントです。
var elm1;
画像は2つなので、用意する変数も2つと決まっているため、配列変数にはしていません。
変数名は、elm0とelm1とし、それぞれ、消えていく画像と出てくる画像を割り当てます。
今回のフリップで言うところの、elm0が表で、elm1が裏になります。
ここからは、このelm0とelm1に対して記述していきます。
elm1 = document.getElementById("back");
今まではimgタグの要素すべてを取り込んでいたのですが、今回からは画像は2枚ですし、それぞれにidを振ってあるので、document.getElementByIdを使って要素を特定しています。
elm0.className = "stay";
elm1.src = "./images/" + imageArray[next];
elm1.className = "stay";
elm0とelm1のそれぞれに画像を指定し、そのクラスも指定します。
スタイルシートは後ほど紹介しますが、同じ"stay"というクラスでも、表と裏ではスタイルが違います。どちらも待機することには違いありませんが、待機する向きが違いますからね。
elm1.className = "flip";
チェンジャー心臓部(今回:flip)ですが、とてもシンプルになっています。
変化させる画像も変数もスタイルも3つあったところが、画像2つスタイル1つになったのですから、シンプルなのは当然なのですが、前画像(prev)や次画像(next)の計算も省き、スタイルの指定だけで変化させています。もちろん変化終了検出付きです。
elm1.removeEventListener(
'webkitTransitionEnd',
flip_end,
false
);
current = next;
elm0.src = "./images/" + imageArray[current];
elm0.className = "stay";
next=(current + 1) % imgCount;
elm1.src = "./images/" + imageArray[next];
elm1.className = "stay";
wait();
}
変化終了後の処理をすべて表示してしまいました。
変化終了を検出してここへ飛んできたので、まずそれを解除します。
すでに変化が終了しているので、次の準備をここですべてやっておきます。
変化によって表に出てきた画像は、次に消えていく画像となるので、currentを書き換え、そのcurrentで画像のセッティングをします。
そのセッティングは初期設定(init)と同じで、画像とスタイルの指定です。
nextもcurrentから算出されるので、次画像も同様にnextによってセッティングします。
セッティングが終わったら、waitで本気の待機です。
スタイルシートの変更
-webkit-transition-property: none;
-webkit-transform: rotateY(0deg);
}
#back.stay {
-webkit-transition-property: none;
-webkit-transform: rotateY(180deg);
}
#front.flip {
-webkit-transition-property: -webkit-transform;
-webkit-transition-duration: 2s;
-webkit-transform: rotateY(180deg);
}
#back.flip {
-webkit-transition-property: -webkit-transform;
-webkit-transition-duration: 2s;
-webkit-transform: rotateY(360deg);
}
サンプルスタイルシート2
今回のポイントは、特定した画像それぞれに、変化のスタイルと待機のスタイルを指定したところです。
#frontと#backそれぞれに、stayとflipがあるので4通りになります。
それぞれ見てもらえれば分かると思いますが、回転角度には注意して下さい。
360°と0°は違うということです。
180°回転させて裏にしておいたとしても、360°へ向かう回転方向と0°へ向かう回転方向とでは、全く回転が逆になってしまいます。
サンプル表示
表示は、前サンプルと何も変わりません。
今回のサンプルファイルのダウンロードは、こちらからどうぞーー>ダウンロード
流行りの3D表示にする
今回は「回転」させているのですが、冷静に見てみると(悪く言うと)、画像が潰れてるようにしか見えません。
映画もテレビもDSも、3D移行しているので、このサンプルも3D表示にすることで、本当に回転していることをアピールしたいと思います。
ある意味、3D表示をしたくて内部構造を変更したようなものです。
3D表示は、「見た目」の問題ですので、今回はjavascriptの変更はありません。
HTMLの変更
目的の3D表示を実現するために、HTMLを少し変更します。
3Dにするには、3Dにする要素(画像)ではなく、その親要素のスタイルに指定する必要があります。
そのため、画像をdiv要素で囲み、それを親要素とします。
さらに、そのidをflipとしました。
スタイルシートの変更
{
-webkit-transform-style: preserve-3d;
-webkit-perspective: 3000;
-webkit-perspective-origin: 320px 480px;
}
サンプルスタイルシート3
変更と言うより追加ですね。
transform-styleをpreserve-3dにすることで3D表示が可能になるのですが、3D特有の指定も必要です。
perspectiveを3000にしていますが、大きくすると遠くから見る状態となり、3D的な変化が小さくなります。
逆に小さくすると、近くで見ている状態となり、変化を大きく見ることができます。
今回はさらに、中心も指定しています。
サンプル表示
実機で確認して頂きたいのですが、今回のサンプルはスクリーンショットでも分かりやすいと思います。
先程のperspectiveの違いも合わせて紹介します。
perspective:1000
perspective:2000
perspective:3000
perspective:4000
右に行く程(perspectiveが大きくなる程)遠くから見ている感じになることがお分かりでしょうか?
回転する画像の角を見比べてみて下さい。
その高さが微妙に違います。
実機で確認していただければ一目瞭然です。
今回のサンプルファイルのダウンロードは、こちらからどうぞーー>ダウンロード