JavaScript ライブラリ tmlib.js を使って日食を再現してみた

phiary に引っ越しました. 毎日プログラミングやWebに関する情報を発信しています! RSS 登録してたまに覗いたり, tweet やハテブして拡散してもらえると幸いです.

Pocket

昨日放送された『世界の果てまでイッテQ!』で出川哲朗とデヴィ夫人のコーナーでやっていた金環日食.

金環日食』も『金星の太陽面通過』も当然のようにスルーした私ですが, この放送を観てちゃんと観ておくべきだったと後悔…

ここまでキレイに観れなかったにしろ, やはりロマンを感じますよね.

ちょっと悔しくなったので HTML5 Canvas with tmlib.js で日食を再現してみました. コードも載せておくので, よかったら遊んでください.

それっぽく見えるよう調整しただけなので, 公転の計算はやっていません. (誰か fork してやってくれると嬉しいな♪)

tmlib.js は近々 webgl 対応したやつを公開する予定なので, 3D 化するついでに本格的に計算して 作ってみようかと思っています.

screenshot

皆既日食 金環日食

コード

tmlib.js を使った実装コードの内容です.

/*
 * phi
 */


// 定数
var SCREEN_WIDTH    = 960;
var SCREEN_HEIGHT   = 640;
var SUN_RADIUS      = 200;
// var MOON_RADIUS     = 200;  // total eclipse
var MOON_RADIUS     = 150;  // annular eclipse
var ECLIPSE_TIME    = 20000;
var WAIT_TIME       = 5000;

var SunAxis = tm.createClass({
    superClass: tm.app.CanvasElement,
    
    init: function() {
        this.superInit();
        this.x = SCREEN_WIDTH/2 - 900;
        this.y = SCREEN_HEIGHT/2 + 1000;
        
        var sun = Sun();
        sun.x = 900;
        sun.y = -1000;
        sun.addChildTo(this);
        
        this.animation.addTween({
            prop: "rotation",
            begin: 330,
            finish: 360,
            duration: ECLIPSE_TIME,
        });
        this.animation.addTween({
            prop: "rotation",
            begin: 360,
            finish: 390,
            duration: ECLIPSE_TIME,
            delay: ECLIPSE_TIME+WAIT_TIME,
        });
    },
});

var Sun = tm.createClass({
    superClass: tm.app.Sprite,
    
    init: function() {
        this.superInit(SUN_RADIUS*3, SUN_RADIUS*3);
        this.radius = SUN_RADIUS;
        
        var c = this.canvas;
        c.setTransformCenter();
        
        var grad = tm.graphics.RadialGradient(0, 0, 0, 0, 0, this.radius*1.1);
        grad.addColorStopList([
            { offset: 0.00, color: "hsla(60, 75%, 100%, 1.0)" },
            { offset: 0.75, color: "hsla(60, 75%, 75%, 1.0)" },
            { offset: 0.9, color: "hsla(60, 75%, 50%, 0.2)" },
            { offset: 1.0, color: "hsla(60, 75%, 50%, 0.0)" },
        ]);
        c.setGradient(grad);
        c.setShadow("red", 0, 0, 1);
        c.fillCircle(0, 0, this.radius*1.1);
    },
    
    update: function() {
        
    },
});

var Moon = tm.createClass({
    superClass: tm.app.Sprite,
    
    init: function() {
        this.superInit(MOON_RADIUS*3, MOON_RADIUS*3);
        this.radius = MOON_RADIUS;
        
        var c = this.canvas;
        c.setTransformCenter();
        
        c.fillStyle = "black";
        c.fillCircle(0, 0, this.radius);
    },
});

var MoonAxis = tm.createClass({
    superClass: tm.app.CanvasElement,
    
    init: function() {
        this.superInit();
        this.x = SCREEN_WIDTH/2 + 400;
        this.y = SCREEN_HEIGHT/2 + 400;
        
        var moon = Moon();
        moon.x = -400;
        moon.y = -400;
        moon.addChildTo(this);
        
        this.animation.addTween({
            prop: "rotation",
            begin: 350,
            finish: 360,
            duration: ECLIPSE_TIME,
        });
        this.animation.addTween({
            prop: "rotation",
            begin: 360,
            finish: 370,
            duration: ECLIPSE_TIME,
            delay: ECLIPSE_TIME+WAIT_TIME,
        });
    },
});



window.onload = function() {
    var app = tm.app.CanvasApp("#world");
    app.resize(SCREEN_WIDTH, SCREEN_HEIGHT);
    app.fitWindow();
    
    var sunAxis = SunAxis();
    app.currentScene.addChild(sunAxis);
    
    var moonAxis = MoonAxis();
    app.currentScene.addChild(moonAxis);
    
    // ダブルクリックで保存
    //tm.dom.Element(app.element).event.mdlclick( function() { app.canvas.saveAsImage(); } );
    
    app.run();
};

Reference

日食 – Wikipedia

http://ja.wikipedia.org/wiki/%E6%97%A5%E9%A3%9F

日食観望計画2009:日食の計算方法

http://www.astro.sci.yamaguchi-u.ac.jp/~kenta/eclipse/calc.html

html5で日食アニメーションしてみたよー(*`ω´*) – jsFiddle(@nekosmash)

CreateJS で作られたやつもあったので紹介しときます.

※jsFiddle の問題で Chrome だと動かないかもしれないです.

screenshot

TRACK BACK URL

POST COMMENT

メールアドレスが公開されることはありません。

COMMENT