それの全段階としてCoffeeScriptとHTML5のCanvasでアニメーション処理を書いてみた。 まずmain.coffee。
次に、2次元のデータ点を表現するpoint2d.coffee。Point2D = require('../src/point2d').Point2D main = ()-> canvas = document.getElementById('canvas') context = canvas.getContext('2d') num_points = 9 labels = ["abc", "bcd", "cde", "def", "efg", "fgh", "ghi", "hij", "ijk", "jkl"] points = [] for i in [0..num_points] x = canvas.width /2 + Math.floor(Math.random() * 200) - 100 y = canvas.height /2 + Math.floor(Math.random() * 200) - 100 vx = Math.random() * 5.0 - 2.5 vy = Math.random() * 5.0 - 2.5 points.push new Point2D(x, y, 10, vx, vy, labels[i], canvas.width, canvas.height, context) points[i].draw() mainloop = ()-> context.save() context.beginPath() context.clearRect(0, 0, canvas.width, canvas.height) context.restore() for i in [0..num_points] points[i].update_position() points[i].reflect() points[i].draw() setTimeout(mainloop, 30) mainloop() window.onload = main
無駄にテストコードも書いてしまった。class Point2D constructor: (x, y, r, vx, vy, label, wnd_width, wnd_height, context) -> @x = x @y = y @r = r @vx = vx @vy = vy @label = label @wnd_width = wnd_width @wnd_height = wnd_height @context = context update_position: -> @x += @vx @y += @vy reflect: -> if @x - @r < 0 @x = @r @vx *= -1.0 if @x + @r > @wnd_width @x = @wnd_width - @r @vx *= -1.0 if @y - @r < 0 @y = @r @vy *= -1.0 if @y + @r > @wnd_height @y = @wnd_height - @r @vy *= -1.0 draw: -> @context.beginPath() @context.strokeStyle = '#00F' @context.fillStyle = '#00F' @context.arc(@x, @y, @r, 0, Math.PI * 2, false) @context.fill() @context.stroke() @context.restore() @context.beginPath() @context.font = "18px 'MS Pゴシック'" @context.fillStyle = "blue" @context.fillText(@label, @x, @y-@r) @context.restore() exports.Point2D = Point2D
ちなみにjasmine-nodeを使っております。
ここまでの実行結果はこんな感じ。Point2D = require('../src/point2d').Point2D describe "Point2D", -> p1 = undefined p2 = undefined p3 = undefined p4 = undefined p5 = undefined p6 = undefined beforeEach -> p1 = new Point2D(0, 0, 0, 0, 0, "", 0, 0, undefined) p2 = new Point2D(100, 200, 30, 2.0, 2.0, "test", 640, 480, undefined) p3 = new Point2D(5, 200, 30, 2.0, 2.0, "test", 640, 480, undefined) p4 = new Point2D(630, 200, 30, 2.0, 2.0, "test", 640, 480, undefined) p5 = new Point2D(100, 10, 30, 2.0, 2.0, "test", 640, 480, undefined) p6 = new Point2D(100, 470, 30, 2.0, 2.0, "test", 640, 480, undefined) it "should be x and y axis value are 0", -> expect(p1.x).toEqual 0 expect(p1.y).toEqual 0 expect(p1.r).toEqual 0 expect(p1.vx).toEqual 0 expect(p1.vy).toEqual 0 expect(p1.wnd_width).toEqual 0 expect(p1.wnd_height).toEqual 0 expect(p1.label).toEqual "" it "should be x and y axis value are 5, 10", -> expect(p2.x).toEqual 100 expect(p2.y).toEqual 200 expect(p2.r).toEqual 30 expect(p2.vx).toEqual 2.0 expect(p2.vy).toEqual 2.0 expect(p2.wnd_width).toEqual 640 expect(p2.wnd_height).toEqual 480 expect(p2.label).toEqual "test" it "should add velocity for x and y to 102.0 and 202.0", -> p2.update_position() expect(p2.x).toEqual 102.0 expect(p2.y).toEqual 202.0 it "should reflect with left side", -> p3.reflect() expect(p3.x).toEqual 30 expect(p3.vx).toEqual -2.0 it "should reflect with right side", -> p4.reflect() expect(p4.x).toEqual 610 expect(p4.vx).toEqual -2.0 it "should reflect with left side", -> p5.reflect() expect(p5.y).toEqual 30 expect(p5.vy).toEqual -2.0 it "should reflect with left side", -> p6.reflect() expect(p6.y).toEqual 450 expect(p6.vy).toEqual -2.0
さて、後は多次元尺度構成法のアルゴリズムを乗っければ完成だ。I want to watch a statistical algorithm’s behavior,
so I wrote animation program with Coffee Script and Canvas on HTML5 before it.