
前回の復習をしておきますね。
Math.ceil(n)・・・切り上げする。与えられた数値以上の最小の整数値を返す。
Math.ceil(7.4)・・・8になります。Math.ceil(-7.4)・・・-7になります(-7は-7.4よりも大きい)。
Math.floor(n)・・・切り捨てる。与えられた数値以下の最大の整数値を返す。
Math.floor(7.4)・・・7になります。Math.floor(-7.4)・・・-8になります(-8は-7.4よりも小さい)。
Math.abs(n)・・・絶対値を返す。absはabsolute(Absolute
value)。
Math.abs(-7.4)・・・7.4になります。Math.abs(7.4)・・・7.4になります。
与えられた数値の符号を得たい(+1か-1を得たい)
n/Math.abs(n)・・・但し0で割り算することはできないので、nは0ではないこと。
※前回のひな形ではzxとlxが等しい時には関数を実行しないので、(zx-lx)が0になることはなく、問題ありません。
今回から円運動を考えてみます。これには三角関数の知識が不可欠ですので説明しておきます。ここで扱う三角関数はそれほど難しいものではありません。
まず円については、ある特定の一点から同じ距離にある点の軌跡(集合)が円です(平面状において)。特定の一点とは円の中心であり、距離は半径になります。そして皆さんご存知のように、円周の長さは直径の約3.14倍です。この比率は一定であり定数といいます。そしてこの定数をπ(パイ)と定義されています。
πは直径に対する円周の長さの倍率です。
さて三角関数では半径を1とする円において角度と円周上の座標の関係を示したものです。半径が1ということは直径は2ですね。
角度ですが、360度で一周します。中心が(0,0)で半径1の円を考えますと、座標(1,0)から円周上を一周すると元の(1,0)に戻ります。360度で元に戻ります。この一周する距離はまさしく円周の長さですから、2πになります(直径が2なのですから)。この一周する角度を2πとしたものが、ラジアンという単位での角度です。これは360度ですから、2π=360度ですね。180度はπになり、90度はπ/2(二分の一π)です。このように考えると、円周の長さで角度を表したものがラジアンであるともいえます。
2π分の長さがある角度は2π(360度)。です。ということは円周の長さが1である場合の角度はどうなりますか?そうラジアンでは1ですね。デグリー(一周を360度とした場合)ではどうでしょう?
2πと360度が対応していますから、2π:360=1:x・・・これによりx=360/(2π)=180/πになります。これはどういうことかといいますと、ラジアン単位の角度をデグリー単位に変換するには180/πという値をかければいいということです。
逆にデグリー単位の角度をラジアン単位に変換するにはπ/180でかけるとよいこともわかります。
デグリー単位でn度をラジアン単位に変換する・・・n*π/180
ラジアン単位でnをデグリー単位に変換する・・・n*180/π
この計算は円運動などのひな形でもよく出てきますので、しっかり理解しておきましょう。というのもJavaScriptに用意されている三角関数計算はラジアン単位なんです。
例えばsin30°ですが、これは1/2つまり0.5です。sin(30*π/180)・・・JavaScriptでは次のように書きます。
Math.sin(30*Math.PI/180)・・・これはMath.sin(Math.PI/6)で、やはり0.5になります。
Math.PI・・・円周率πを得る数学定数です。JavaScriptでは3.141592653589793という数値です。
・・・誤差が生じますね。まあひな形では問題になる誤差ではありません。

ところで円の方程式ですが、r2=(x-x1)2+(y-y1)2も一応予備知識。rは半径、(x1,y1)は中心座標です。(x,y)は円周上任意の座標です。
ここまで予備知識でした。
HTMLドキュメント上では、Y軸は下方向が正(プラス)、上方向が負(マイナス)であることに注意してください。X軸は右方向が正、左方向が負なので、下図のようになります。

では早速円運動するスクリプトを考えてみましょう。円運動するためには円の中心と半径が必要になりますね。中心を(cx,cy)、半径をhnとしましょうか。また円運動するということは角度が一定の量で変化(増加または減少)し、その角度における円周上の座標を求めるということになります。角度は見慣れているデグリー(度)で扱うことにします。
ではある瞬間の角度をdegとして、その時のX座標とY座標を求めます。このX座標が画像のLEFTになり、Y座標が画像のTOPになれば回転できそうです。勿論角度を変化させては座標を求めてLEFTとTOPに代入するを繰り返し実行させなければ動かないのはもうおわかりでしょう。
半径が1の時、角度がdegであるならX座標はcos(deg)です。今半径はhnなので、hn倍しなければなりませんね。またdegはデグリーですから、ラジアンに変換しなければなりません。また中心は原点ではないので、その分加算しなければなりません。
求めるX座標=Math.cos(deg*Math.PI/180)*hn+cx・・・弧の値は小数になることがあります。これをLEFTにそのまま入れても問題ありません。ピクセル単位である場合、小数部分は無視されます。つまり切り捨てされるのと同じなんです(負の場合は切り上げ)。
求めるY座標=Math.sin(deg*Math.PI/180)*hn+cy
角度変化量は変数を用意してセットしておきましょう。
var dd=5//角度変化量(プラスで右回り、マイナスで左回り)
それから角度degは最初0度からスタートしましょうか。
var deg=0//スタート位置角度
角度を変化させて座標も求め、LFETとTOPに入れる処理を関数en()として記述します。en()関数は繰り返し実行しないと円運動しませんから、setTimeout()で繰り返させます。タイマー時間は100ミリ秒にとりあえずしておきます。
function en(){
img1.style.pixelLeft=Math.cos(deg*Math.PI/180)*hn+cx
img1.style.pixelTop=Math.sin(deg*Math.PI/180)*hn+cy
deg=deg+dd//deg+=ddでもOK
setTimeout("en()",100)
}
[ソース]
<HTML>
<head>
<meta http-equiv="content-type"
content="text/html; charset=shift_jis">
<META http-equiv="Content-Style-Type"
content="text/css">
<title></title>
</head>
<body onload="setTimeout('en()',3000)"
style="overflow:auto; margin:0px; padding:0px">
<img
id="img1" src="octopus.gif" style="position:absolute;
left:-1000px; top:0px">
<script>
var
dd=5//角度変化量(プラスで右回り、マイナスで左回り)
var deg=0//スタート位置角度
var
cx=300//中心X座標
var cy=200//中心Y座標
var hn=150//半径
function
en(){
img1.style.pixelLeft=Math.cos(deg*Math.PI/180)*hn+cx
img1.style.pixelTop=Math.sin(deg*Math.PI/180)*hn+cy
deg=deg+dd//deg+=ddでもOK
setTimeout("en()",100)
}
</script>
</body>
</html>
このスクリプトは実は中心に対し、右下方向にずれが生じます。なぜなら求めた座標をLEFTとTOPにしていますね。LEFTとTOPはエレメントの左上端の位置を設定するものです。エレメントには幅がありますからエレメントの中心を求めた座標にしなければなりません。
そこで修正しましょう。エレメントの中心はLEFT位置に対してエレメントの横幅の半分だけ右の位置に、TOP位置に対してエレメントの縦幅の半分だけ舌の位置にあります。ということはLEFTとTOPを、求めた値よりも幅の半分だけ減算して代入すればいいことになります。
エレメントの幅を取得するのもobject.style.pixelWidthやobject.clientWidthやobject.offsetWidthなどいくつか用意されていますが、基本的にはobject.style.widthとobject.style.pixelWidthは使い勝手がよくありません。object.clientWidthかobject.offsetWidthがいいかと思います。
img1.style.pixelLeft=Math.cos(deg*Math.PI/180)*hn+cx-img1.clientWidth/2
img1.style.pixelTop=Math.sin(deg*Math.PI/180)*hn+cy-img1.clientHeight/2
次回は複数のエレメントを円運動させてみたいと思います。