ホーム画面の壁紙を切り替える(キューブ編)

前回のフリップ編で終わろうと思ったのですが、都合が悪くなったので、もう1つやっておきます。
いろいろな壁紙チェンジャーを作ろうと、画面を分割することを始めたのですが、これまでの説明に出てきていないやり方で進めてしまったので、こちらで紹介しておきます。
画像を背景で表示させるだけなんですけどね・・・

紹介するなら、さらに拡張したもので紹介したいので、今回は「フリップ」の3Dをさらに拡張し、立体を回転させてみましょう。
マックを使っている方は、見たことのある方もいらっしゃることでしょう。

基本ファイルとその確認

サンプルファイル構成

今回作るサンプルウィジェットを含むテーマファイルの基本構成は右図の通りですが、前回のフリップ編に手を加えただけのものです。
ファイルのダウンロードはこちらーー>ダウンロード

<注意>
各ウィジェットの最初のサンプルには画像を入れてありますが、その後のサンプルには画像を用意しておりませんので、最初のサンプルにある画像をコピーしたり、各自で用意するなどして下さい。

では、ファイルを1つ1つ見ていきましょう。

サンプルHTML

HTMLから見ていきましょう。
以下に示すのが、Wallpaper.htmlの中身(ソース)です。

<?xml version="1.0" encoding="utf-8"?>
<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()">
  <div id="cube">
   <div id="front"></div>
   <div id="right"></div>
  </div>
 </body>
</html>

サンプルHTMLソース1

フリップ編と違うのは、imgタグがdivタグになったところです。
正面と右サイドに配置するため、それぞれ"front"と"right"でidを振りました。
さらにそれを"cube"というidのdivタグで囲みました。
フリップ編でも登場しましたが、3D効果を得るための対応です。
画像用のdivタグには、imgタグはありません。
今回は、divの背景に画像を指定する方法で説明します。
これまでは、2枚の画像をそれぞれ変化させていましたが、今回は、2つの画像をcube上でグループ化し、cubeを変化させることで、2枚の画像をまとめて変化させようという流れです。

ページトップへ

サンプルJavaScript

では、JSファイルを見ていきましょう。
以下に示すのが、script.jsの中身(ソース)です。
フリップ編と違う部分を赤くしています。

var interval;
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 elm;
var img0;
var img1;

function init() {
 interval = 5;
 imgCount = imageArray.length;
 current = 0;
 next = 1;
 elm = document.getElementById("cube");
 img0 = document.getElementById("front");
 img1 = document.getElementById("right");
 elm.className = "stay";
 img0.style.backgroundImage= "url('./images/" + imageArray[current] +"')";
 img1.style.backgroundImage= "url('./images/" + imageArray[next] +"')";
 wait();
}
function wait() {
 setTimeout(rotate, interval * 1000);
}
function rotate() {
 elm.className = "rotate";
 elm.addEventListener(
    'webkitTransitionEnd',
    rotate_end,
    false
 );
}
function rotate_end() {
 elm.removeEventListener(
    'webkitTransitionEnd',
    rotate_end,
    false
 );
 current = next;
 next=(current + 1) % imgCount;
 img0.style.backgroundImage= "url('./images/" + imageArray[current] +"')";
 img1.style.backgroundImage= "url('./images/" + imageArray[next] +"')";
 elm.className = "stay";
 wait();
}

サンプルJavaScript1

キューブ編へ移行するために、"flip"を"rotate"にしてあります。
このrotateへの変更に関する部分は、これまでの流れでお馴染みになったと思うので、説明を省きます。

var elm;
var img0;
var img1;

前回では、画像を要素(エレメント)として捉えやすくするために、画像要素をelm0とelm1にしていましたが、今回は、要素として捉えたいのがcubeの1つなので、cube用にelmを用意し、画像はそれぞれimg0とimg1にしました。

elm = document.getElementById("cube");
img0 = document.getElementById("front");
img1 = document.getElementById("right");

宣言した変数にそれぞれ対応する要素を入れていきます。
これももうお馴染みのやり方になりましたでしょうか?

elm.className = "stay";

これも今までのやり方に沿っていますので、お馴染みかと思いますが、今回変化させるのはcubeだけですので、cubeに対応したelmのクラスだけを"stay"にします。
待機状態ですね。

img0.style.backgroundImage= "url('./images/" + imageArray[current] +"')";
img1.style.backgroundImage= "url('./images/" + imageArray[next] +"')";

これが今回の目玉です。
これまでは、画像を配置していましたが、今回は背景画像として指定するので、このような書き方になりました。
ポイントは、"url('ファイル名')"の部分です。
ファイル名が動的に変化するので、書き方に工夫が必要です。

elm.className = "rotate";

今回のチェンジャー心臓部(今回:rotate)です。
今回は要素が1つなので、これだけで済みました。

img0.style.backgroundImage= "url('./images/" + imageArray[current] +"')";
img1.style.backgroundImage= "url('./images/" + imageArray[next] +"')";
elm.className = "stay";

変化終了後の処理ですが、やっていることは説明済みです。
次の画像を指定し、待機状態にします。

ページトップへ

サンプルスタイルシート
* {
  margin: 0;
  padding: 0;
  border: 0;
}
body {
  width: 640px;
  height: 960px;
  -webkit-perspective: 2000;
  -webkit-transform: scale(0.84);
}
div {
  position: absolute;
  top: 0px;
  left: 0px;
  width: 640px;
  height: 960px;
  -webkit-background-size: 640px 960px;
  -webkit-transform-style: preserve-3d;
}
#front {
  -webkit-transform: rotateY(0deg);
  -webkit-transform: translateZ(320px);
}
#right {
  left: 320px;
  -webkit-transform: rotateY(90deg);
}
#cube.stay {
  -webkit-transition-property: none;
  -webkit-transform: rotateY(0deg);
}
#cube.rotate {
  -webkit-transition-property:
             -webkit-transform;
  -webkit-transition-duration: 1s;
  -webkit-transform: rotateY(-90deg);
}

サンプルスタイルシート1

次に、スタイルシート(style.css)を見ていきましょう。

いきなりbodyから変更がありますが、立体表示のためのものです。動き自体には関係ありません。

次に、divがありますが、iPhoneの画面サイズを意識して、すべてのdivを対称に設定してあります。div自体の大きさも必要ですが、背景サイズの指定が今回のポイントです。

正面(#front)は、何の回転も必要ないのですが、キューブの回転軸と面が重なってはいけないため、手前に320移動させています。これも今回のポイントです。

右面(right)は、幅半分だけ移動し、90°回転させることで、正面の端とピッタリくっつきます。正面も幅半分の320移動したことによる結果です。

待機状態(stay)は、変化無し(none)の回転無し(0deg)です。

rotateが今回の変化ですが、目に見える画像はすべてcube上にあるので、今回の変化の指定は、この1箇所だけです。

ここで、bodyのscaleについて追記します。
画面いっぱいのサイズで表示させていたのですが、キューブの回転軸から手前に移動させたことで、画像が画面よりも大きく表示されることになってしまったのです。
そのため、scaleによって画面に収まる大きさに縮小しました。
この縮小率は、perspectiveの数値によって変化しますので、ご注意下さい。

ページトップへ

サンプル表示

変化前

基本サンプルファイルは、個々でダウンロード&実行して確認していただきたいのですが、スクリーンショットを紹介します。

今回は何枚もスクリーンショットを用意する必要がないと判断したため、一番分かりやすいであろう思われる画像を大きめに表示しておきます。

サイコロのイメージですね。

サンプルファイルのダウンロードは、こちらからどうぞーー>ダウンロード

ページトップへ

構造を少し改良する

キューブの動きを確認していただいたところで、内部構造も確認してみましょう。
と言っても、無駄を省くだけなんですけどね。

javascriptの説明で、とても気になっていたことなのですが、初期設定(init)とアニメーション終了(rotate_end)で同じ記述があります。
どちらも画像の入れ替えをしているのですが、このプログラムの流れを見ると、待機(wait)内に統合することができます。
つまり、アニメーションが始まる前の画像指定も、アニメーションが終わった後の画像指定も、どちらも待機しているのだから、待機中に画像を入れ替えましょう!ということです。
そう考えると、結構省けますね。

javascriptの変更

変更部分を赤くしています。
変数宣言部分は省きました。

function init() {
 interval = 5;
 imgCount = imageArray.length;
 current = 0;
 next = 1;
 elm = document.getElementById("cube");
 img0 = document.getElementById("front");
 img1 = document.getElementById("right");
 wait();
}
function wait() {
 img0.style.backgroundImage= "url('./images/" + imageArray[current] +"')";
 img1.style.backgroundImage= "url('./images/" + imageArray[next] +"')";
 elm.className = "stay";
 setTimeout(rotate, interval * 1000);
}
function rotate() {
 elm.className = "rotate";
 elm.addEventListener(
    'webkitTransitionEnd',
    rotate_end,
    false
 );
}
function rotate_end() {
 elm.removeEventListener(
    'webkitTransitionEnd',
    rotate_end,
    false
 );
 current = next;
 next=(current + 1) % imgCount;
 wait();
}

サンプルJavaScript2

init()とrotate_end()にあった画像指定とクラス指定が、wait()内に配置されました。
なのに、処理の順番は変わっていません。
興味のある方は、順番を追ってみて下さい。

ページトップへ

サンプル表示

表示は、前サンプルと何も変わりません。


今回のサンプルファイルのダウンロードは、こちらからどうぞーー>ダウンロード

ページトップへ

2011/10/10