風車エフェクトを作る1
風車エフェクトは、脱獄アプリのCylinderを紹介した時に、サンプルとして紹介しました。
そして、エフェクトの作り方を続けていると、Cylinderのアップデートがあり、幾つかのエフェクトが追加されました。
その中に、ViktorX11の「EmotionUI」がありますが、風車の動きをしています。
確認したのがiPhone6Plusだからなのか分かりませんが、見切れてしまっています。
ソースを確認したのですが、作り込んだ印象はありません。
どちらかと言うと、バグ取りが上手くできず、何とか修正しながら動きを合わせたという印象です。
やりたいことは分かるのですが、その1つ1つの根拠を聞きたくなる記述なので、「結果オーライ」感が否めないのです。
せっかく、アップデートで既存エフェクトの仲間入りした「EmotionUI」ですが、動きが残念なため、別の作り方を紹介しようと思います。
風車のイメージを固める
「風車」で検索しましたが、ドンピシャの画像だらけでした。
この風車が回るイメージを、iPhoneの画面上に再現しようとしています。
回転中心は画面中央なので、アイコンを4つの羽に見立てて・・・
これでは、風車っぽく見えるとは思えません。
どちらかと言うと、1つの羽に見立てる方がイメージが湧きます。
画像のオレンジの羽1つ1つにiPhoneがあると思うと・・・
これならイメージしやすいのではないでしょうか?
画像の羽にiPhoneを重ねたので傾いていますが、iPhoneを固定して、アイコンのみが回転するイメージなら抱きやすいかと思います。
これをiPhone主体の画像に置き換えてみると・・・
4つのiPhoneを並べました。
上のiPhoneに注目します。
ページを移動すると、90°回転して次のページが入ってくるというイメージです。
これを、プログラムで表現する方法を考えましょう。
考え方
基本的な考え方は同じです。
offsetからpercentを算出するのですが、ページ移動に伴って回転する角度は、最大で90°とします。
ページ全体が、徐々に回転するようにするのですが、それに伴って、回転中心も円弧上を移動するようにしなければなりません。
問題はその円弧で、円弧の中心と、その半径が重要になります。
回転によって出て行くページは、回転後には完全に画面から出ていないといけないので、先ほどの画像に4つのiPhoneがありましたが、その中央の赤い×印くらいの場所が回転中心でなければなりません。
具体的には、画面幅の半分だけ離れた場所で良いと思います。
そうすると、回転半径は、画面縦幅の半分と画面横幅の半分ということになります。
今回は、ドックの部分も含めた画面で考えますので、引数のscreen_heightとscreen_widthを使って算出します。
視覚的には、以下のように考えます。
赤い矢印が回転角度を表します。
回転はangleで算出すれば良いのですが、回転と同時に移動も考えなければなりません。
その移動量を表したのが、青線と緑線です。
半径と角度が分かっているので、これらは三角関数で算出できます。
考え方はこんな感じですが、実際にプログラムを組む時は、プログラム的な約束もあります。
縦方向については、数学的には上がプラスですが、プログラムを組む時は下がプラスです。
回転については、水平軸が0°ですので、赤い矢印(angle)だけ回すためには、90°多く指定する必要があります。
サンプル
では、実際にプログラムを記述してみましょう。
local percent = offset/page.width
local angle = percent*math.pi*2
local r = (screen_height + screen_width)/2
local dx = r * math.cos(angle+math.pi/2)
local dy = r - r * math.sin(angle+math.pi/2)
page:translate( offset )
page:translate( dx, dy )
page:rotate( -angle )
end
effect31_1
横方向の移動量は緑線で表されるのですが、向きはマイナス方向です。
三角関数のコサインで求めることができますが、その値はマイナスですので、符号変換の必要はありません。
縦方向の移動量は青線で表されるのですが、向きはプラス方向です。
三角関数のサインで求めることができますが、青線の部分は、半径との差になります。
どちらの角度も、90°進めています。
こんな感じです。
風車エフェクト
できてしまうと、簡単ですね。
角度と半径と移動量を計算したら、移動と回転するだけなので、プログラムもそんなに長くありません。
しかし、個人的には1行の長さをできるだけ短くしたいので、書き直してみます。
加法定理を利用して書き直してみました。
local percent = offset/page.width
local angle = percent*math.pi*2
local r = (screen_height + screen_width)/2
local dx = -r * math.sin(angle)
local dy = r * (1 - math.cos(angle))
page:translate( offset + dx, dy )
page:rotate( -angle )
end
effect31_1_2
cos(90°+θ) = -sinθ
sin(90°+θ) = cosθ
これらを使ってシンプルにしたのと、移動指定を1行にまとめました。
この程度でも、エフェクト的には十分かと思います。
当サイトの更新状況を、アラートで表示するかどうかの設定をします。
保存する