今日は満月ですからっ(≧▽≦)
(ちなみに「今日」とは、この記事がアドベントカレンダーで公開される予定の、2021/12/19
のコトです)
なお、これは天文学的にガチなお月様ではありません~。カレンダーに表示する的なヤツです。
APIから月齢を取得します
こちらのAPIを利用します☆
必須のパラメーターは、
- lat (緯度)
- lon (経度)
それから、省略可能ですが
- time (yyyy-mm-ddTHH:MM)
timeは省略すればサーバーの現在時刻で計算されるようですが、「今日」の月齢と言った場合にはたいがい12:00
のを表示するんだよね。
こんな感じです。
https://mgpn.org/api/moon/v2position.cgi?time=2021-12-19T12:00&lat=35.00&lon=135.00
これへGET送信
してやるだけ!
月齢取得API=「https://mgpn.org/api/moon/v2position.cgi?」
緯度=35.00。経度=135.00。日付=今日の『/』を『-』に置換。
URL=月齢取得API&「time={日付}T12:00&lat={緯度}&lon={経度}」
URLへGET送信した時には
J=対象をJSONデコード。
月齢=J["result"][0]["age"]。
月齢を表示。
ここまで。
できました! 簡単です♪♪
ありがたや~☆
月齢のお月様を描画する
APIのお陰で、あっという間に月齢が取得出来るようになりましたが、しかし、表示したいのは月齢そのものじゃありません。
その月齢のお月様を表示したいのです。
とゆうわけでキャンバスに描画したいですが、なでしこさんの描画命令だと円と楕円くらいしか描けないのでツラい。
組み合わせて何とかなるだろうかと色々考えた結果、半円と楕円を重ねたらできそうな気はしてきた。
前に、自前で扇形を描くヤツを作ったので半円は描ける・・・が・・・?
でもどっちみち半円がJSプラグインで、なでしこの命令だけじゃできないのであれば、なんかもういっそ1からプラグイン作った方が早そげ? と思ったりもして作り始めましたがその途中、いやいやまてまて、楕円描画はふつーに半円が描けるじゃないか! とゆうことに遅まきながら気がつきました(バカ;)
それで、結局両方作ることとなったので、この労力をムダにしないために、コードを比較していく記事としたい。
目標
[x,y]へ半径で月齢の月描画。
って感じで0~30の月齢を指定すると、その月齢のお月様を描画する、という命令にしたいです。
満月を描画する
半月だろうと新月だろうと、月はそこにあるのです。
(・・・その考えが後々悲劇を生みます!!(´д`))
月色に塗り色設定。空に線色設定。
[x,y]へ半径の円描画。
sys.__ctx.beginPath();
sys.__ctx.arc(x, y, r, 0, Math.PI*2);
sys.__ctx.fillStyle = sys.__v0['月色'];
sys.__ctx.fill();
ま、円を描くだけです。
実際の月は真円じゃないとか、そんなガチなヤツじゃありません。
注意点としては、なでしこの描画命令はカンタンに描ける分、fillとstrokeが自動的に付いてくるので、塗りたくない線引きたくない場合は、塗り色、線色に空を指定する必要があります。
じゃばすくりぷとの方は、なでしこのプラグインにするアレなので、こんてきすとはあらかじめsys.__ctx
で使えるようになっておりますです。
半円の影を描きます
角度は0が右端になってるので、頂点は270度の位置ってコトになるんだよね。毎回間違う;
上弦の月は左が影、下弦の月は右が影なので、右回りか左回りかで描き分けています。
暦などには、丁度半月の状態の時に「上弦」「下弦」の表示が付きますが、ここでの場合は、新月から満月までが上弦、満月から次の新月までを下弦と呼んでいます。
旧暦で、上旬の月は上弦、下旬の月は下弦、と覚えたらもう忘れません!
影色に塗り色設定。
回り方は右回転。もし、月齢<15ならば、回り方は左回転。
[x,y,半径,半径,0,270をラジアン変換,90をラジアン変換,回り方]の楕円描画。
var left = false; if (age < 15) left = true;//《左回りか》
sys.__ctx.beginPath();
sys.__ctx.arc(x, y, r, Math.PI*3/2, Math.PI*1/2, left);
sys.__ctx.fillStyle = sys.__v0['影色'];
sys.__ctx.fill();
Javascriptはarcで描けますが、なでしこは楕円描画
のx幅とy幅を同じにすることで描きます。
また、弦の部分には線が引かさらないので、今回の場合はその方が助かりますが、もしか線の閉じた半円を描きたい場合は線描画
で引っ張ってやる必要があります。
影の端位置を計算
今描いた影の弦に当たる部分を膨らましたり凹ましたりすればよいので、その位置を計算します。
出たよ! こさいんのじゅもんだぁ~><
習った時にはこんなもん一生使うわけ無いと思ってカケラも覚えなかったですが、めっちゃ使う!!
cosθ=底辺/斜辺
図にすれば、お月様の半径が斜辺だと分かります。そして、角度θを月齢と考えます(月齢そのものではなく、30日で一巡りの周期を360度(実際にはラジアンですが!)に当てはめる。朔望周期は一定では無いし30には足りないけど、これはそんなガチなヤツじゃないんでっ)
そうすると底辺の長さが判明するので、それを楕円のx幅とします。
楕円x幅=(半径*COS(月齢/30*(360をラジアン変換)))の絶対値。
var dx = Math.abs(r * Math.cos(age/30*Math.PI*2));//《楕円x幅》
Math.absは絶対値です。向きがマイナスでも楕円の幅は一緒なのでっていうかマイナス指定したらエラーなるので。
以前のなでしこ3にはABS
はあったけど絶対値
が無くて(今はあります!♪)v1のつもりで「絶対値」を使っては毎回エラー出していた悲しい思い出がよみがえりますねwww
楕円描画
楕円は、影を描く場合と月を描く場合がありますよ。
上弦の半月から満月を挟んで下弦の半月までは月を、下弦の半月から新月を挟んで上弦の半月までは影を描きます。
また、月を描く場合は、影の時とは回りが逆になります(そうするために、今回は下から上へ描画します)
もし、月齢が7.5から22.5の範囲内ならば、
月色に塗り色設定。
回り方は回り方の向き逆転。
ここまで。
[x,y,楕円x幅,半径,0,90をラジアン変換,270をラジアン変換,回り方]の楕円描画。
こんな些細なif文でも、なでしこなら簡単なのに(´Д⊂ヽ と泣きながらがんばります。
sys.__ctx.beginPath();
if (age > 7.5 && age < 22.5) {
sys.__ctx.fillStyle = sys.__v0['月色'];
left = (left+1)%2 ;//向き逆転
}
sys.__ctx.ellipse(x, y, dx, r, 0, Math.PI*1/2, Math.PI*3/2, left);
sys.__ctx.fill();
こんな感じ?
どこに泣く要素があったのかマッタク不明ですがね・・・;
アンチエイリアス?
できました!
と思ったんですが、アンチエイリアスの影響ですかね? 月の背景を暗い色にすると月の色がうっすらと影部分の周りに見えてしまいます。
それはそれで輪郭を表示するとゆうのもアリかとは思うんですが、邪魔くさい場合もあるので消したいと思って色々試行錯誤してみたり。
Javascriptでもこのアンチエイリアスはオフに出来ないんですかね? オフにしたらしたでまた、表示が美しくなくなりそうではありますが;
で、色々やったんだけど、そうだ、最初に満月を描いてるのが悪いんじゃ?! とゆうコトに気が付いたので・・・こうなった。
# 半月を描画
月色に塗り色設定。空に線色設定。
回り方は左回転。もし、月齢<15ならば、回り方は右回転。
もし、月齢=0でなければ、[x,y,半径,半径,0,270をラジアン変換,90をラジアン変換,回り方]の楕円描画。
半分で良かった;
新月の時には月を描画しない。満月の時には影を描画しない。
結局全て楕円描画で出来ましたね!(^▽^;
動作確認
そんなこんなで、とりあえず貯蔵庫に、nako3プラグインとして上げました。
テストもちゃんと動いています☆ よきーよきー♪
今日のお月様
ではでは、合体させます。
といっても、月描画部分はなでしこプラグインとして別途上げたので、冒頭で取り込むだけ!
なでしこさんは、位置情報取得時
で、現在地の緯度と経度を配列で取得出来ます。
折角なのでそれでやってみる。
!『https://n3s.nadesi.com/plain/moon.nako3』を取り込む。# お月様描画
#---月位置(方位角・高度・月齢)計算API -----
月齢取得API=「https://mgpn.org/api/moon/v2position.cgi?」
#---位置情報取得-----
位置情報取得した時には
緯度=対象[0]。経度=対象[1]。日付=今日の『/』を『-』に置換。
URL=月齢取得API&「time={日付}T12:00&lat={緯度}&lon={経度}」
#---AJAX送信-----
URLへGET送信した時には
J=対象をJSONデコード。//対象を表示
月齢=J["result"][0]["age"]。
#---お月様と月齢を描画-----
[150,165]へ100で月齢の月描画。
「bold 18px sans-serif」に描画フォント設定。
「月齢 {月齢を1で小数点四捨五入}」を300で290に文字中央寄せ描画。
ここまで。
ここまで。
#---背景とタイトル描画-----
影色に塗り色設定。
[0,0,300,300]に四角描画。
「bold 20px sans-serif」に描画フォント設定。白色に塗り色設定。
「今日のお月様」を300で30に文字中央寄せ描画。
「bold 16px sans-serif」に描画フォント設定。
今日を300で55に文字中央寄せ描画。
●(文字列を領域幅でyへ|yに)文字中央寄せ描画
文字幅=文字列の文字描画幅取得。
[領域幅/2-文字幅["width"]/2,y]に文字列を文字描画。
ここまで。
動作確認
できました! やったね!!
おわります
今日は満月なので・・・かえって頑張った甲斐の分からないような、まん丸お月様が表示されておりますよ・・・