1.概要
HuTimeでは、全ての図形は、Layerオブジェクトが持つcanvas要素に描画される。一般に、canvas要素への図形の描画は、おおよそ、以下の手順で進められる。
- canvas要素のgetContextメソッドによりコンテキストを取得
- コンテキストが持つメソッド(beginPath, moveTo, lineTo など)を使って図形のパスを描画
- コンテキストが持つメソッド(stroke, fill など)を使って図形を表示
HuTimeにおいては、基本的な図形について、1から3までの全ての手順、および、1から2までの途中までの手順を実施するメソッドが用意されている。これらのメソッドはHuTime.Drawingクラスに属しており、円を描く場合を例にすれば、1から3までの図形を表示する手順はHuTime.Drawing.drawCircleメソッドで、1から2までのパスを描画する手順はHuTime.Drawing.pathCircleメソッドでそれぞれ実施される。
2.図形の描画
それぞれの図形について、HuTime.Drawingクラスでレイヤに図形を表示するメソッドとパスを描画するメソッドが定義されており、通常は図形を表示するメソッドを使用する。
図形の表示
HuTime.Drawing.method(style, layer, 位置指定, 大きさ・形状指定 [, rotate [, canvas]])
ここで、methodは、"draw"から始まり、図形ごとに異なるメソッド名である(例:drawCircle)。また、位置指定、大きさ・形状指定の引数も、図形ごとに異なる。これらの引数の詳細は、各図形の解説で示す。一方、そのほかの引数は、すべての図形で共通で、詳細は下記のとおりである。
- style
- 型:HuTime.FigureStyle
- 図形の書式(色、線の太さなど)を指定する。
- layer
- 型:HuTime.Layer
- 図形を描画するレイヤ。
- rotate
- 型:数値
- 図形を回転させる角度(単位:度)。指定は任意で、省略した場合は、0が指定される。回転の中心は、その図形の中心となる。線、円など、いくつかの図形では指定できない。
- canvas
- 型:canvas要素
- 図形を描画するcanvas。指定は任意で、省略した場合は、layer.canvasが指定される。年表レイヤやグラフレイヤなど、複数のcanvas要素を持つLayerオブジェクトが対象の場合に使用。
パスの描画
HuTime.Drawing.method(layer, 位置指定, 大きさ・形状指定 [, rotate [, canvas]])
パスを描画するメソッドは、canvas上にパスを設定するのみで、図形は表示されない。図形の領域を取得する場合などに使用する。ここで、methodは、"path"から始まり、図形ごとに異なるメソッド名である(例:pathCircle)。図形を表示するメソッドと異なり、図形の書式を指定するための引数はない。ほかの引数は、図形を表示するメソッドと同様である。
3.図形の種類
HuTimeでは、複数の種類の基本図形について、レイヤ上に描画するためのしくみをサポートしている。各図形において、図形を表示するメソッドとパスを描画するメソッド、および、描画位置や大きさ・形状を指定する方法の詳細を以下に示す。
線(ポリライン)
HuTime.Drawing.drawLine(style , layer, positions [, canvas])
HuTime.Drawing.pathLine(layer, positions [, canvas])
線のノードの位置をPositionオブジェクトの配列として指定する。ポリゴンとは異なり、パスを閉じない。回転(rotate)は指定できない。
- positions
- 型:HuTime.Positionの配列
- 線のノードの位置の集合。
多角形(ポリゴン)
HuTime.Drawing.drawPolygon(style , layer, positions [, canvas])
HuTime.Drawing.pathPolygon(layer, positions [, canvas])
多角形の頂点の位置をPositionオブジェクトの配列として指定する。配列の最後の位置と最初の位置を接続し、パスを閉じる。回転(rotate)は指定できない。
- positions
- 型:HuTime.Positionの配列
- 多角形の頂点の位置の集合。
正方形
HuTime.Drawing.drawSquare(style, layer, position, width [, rotate [, canvas]])
HuTime.Drawing.pathSquare(layer, position, width [, rotate [, canvas]])
位置は正方形の中心をPositionオブジェクトで指定し、大きさは幅(辺の長さ)をpx単位で指定する。回転(rotate)に45を指定すると、ひし形になる。
- position
- 型:HuTime.Position
- 正方形の中心位置。
- width
- 型:数値
- 正方形の幅(単位:px)。辺の長さに相当。
矩形
HuTime.Drawing.drawRect(style, layer, position1, position2 [, rotate [, canvas]])
HuTime.Drawing.pathRect(layer, position1, position2 [, rotate [, canvas]])
位置と大きさは、矩形の対角線をなす2つの頂点の位置をPositionオブジェクトで指定する。
- position1
- 型:HuTime.Position
- 矩形の対角線をなす一方の頂点の位置。
- position2
- 型:HuTime.Position
- 矩形の対角線をなす他方の頂点の位置。
円
HuTime.Drawing.drawCircle(style, layer, position, width [, canvas])
HuTime.Drawing.pathCircle(layer, position, width [, canvas])
位置は円の中心をPositionオブジェクトで指定し、大きさは幅(直径)をpx単位で指定する。回転(rotate)は指定できない。
- position
- 型:HuTime.Position
- 円の中心位置。
- width
- 型:数値
- 図形の幅(単位:px)。円の直径に相当。
円弧
HuTime.Drawing.drawArc(style, layer, position, radius, startAngle, endAngle [, canvas])
HuTime.Drawing.pathArc(layer, position, radius, startAngle, endAngle [, canvas])
位置は円弧を含む円の中心をPositionオブジェクトで指定し、大きさと形状は、その円の半径(単位:px)、および、開始・終了位置の角度(単位:度)で指定する。回転(rotate)は指定できない。
- position
- 型:HuTime.Position
- 円弧を含む円の中心位置。
- radius
- 型:数値
- 円弧を含む円の半径(単位:px)。
- startAngle
- 型:数値
- 円弧の開始角度(単位:度)。
- endAngle
- 型:数値
- 円弧の終了角度(単位:度)。
扇形
HuTime.Drawing.drawPie(style, layer, position, radius, startAngle, endAngle [, canvas])
HuTime.Drawing.pathPie(layer, position, radius, startAngle, endAngle [, canvas])
位置は扇形を含む円の中心をPositionオブジェクトで指定し、大きさと形状は、その円の半径(単位:px)、および、開始・終了位置の角度(単位:度)で指定する。回転(rotate)は指定できない。
- position
- 型:HuTime.Position
- 型:HuTime.Position
- radius
- 型:数値
- 扇形を含む円の半径(単位:px)。
- startAngle
- 型:数値
- 扇形の開始角度(単位:度)。
- endAngle
- 型:数値
- 扇形の終了角度(単位:度)。
三角形
HuTime.Drawing.drawTriangle(style, layer, position, width [, rotate [, canvas]])
HuTime.Drawing.pathTriangle(layer, position, width [, rotate [, canvas]])
位置は三角形の中心(重心)をPositionオブジェクトで指定し、大きさは幅(底辺の長さ)をpx単位で指定する。
- position
- 型:HuTime.Position
- 三角形の中心(重心)位置。
- width
- 型:数値
- 三角形の幅(単位:px)。底辺の長さに相当。
プラス記号
HuTime.Drawing.drawPlusMark(style, layer, position, width [, rotate [, canvas]])
HuTime.Drawing.pathPlusMark(layer, position, width [, rotate [, canvas]])
位置は記号の中心をPositionオブジェクトで指定し、大きさは幅(線分の長さ)をpx単位で指定する。回転(rotate)に45を指定すると、X記号になる。
- position
- 型:HuTime.Position
- 記号の中心位置。
- width
- 型:数値
- 記号の幅(単位:px)。記号を構成する線分の長さに相当。
4.描画のタイミング
HuTime.Drawingの各メソッドを用いで描画した図形は、レイヤが再描画されると消えてしまう。このため、レイヤの再描画に合わせてHuTime.Drawingの各メソッドが実施されるよう工夫する必要がある。実際には、レイヤの再描画に合わせた動作を追加できるHuTime.Layer.processBeforeRedrawメソッド(再描画の前)、または、HuTime.Layer.processAfterRedrawメソッド(再描画の後)の中に記述する。processBeforeRedrawメソッドを利用した場合は、年表レイヤのレコード、グラフレイヤのプロット、レイヤ上のオブジェクトなどの下に図形が描画される。反対に、processAfterRedrawメソッドを利用した場合は、これらの上に図形が描画される。

図形描画の例(下記サンプルコード)。円はprocessBeforeRedrawメソッド内で描画されたので、グラフの下に表示されている。一方、三角形は、processAfterRedrawメソッド内で描画されたので、グラフの上に表示されている。
サンプルコード(実行例はこちら)。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script type="text/javascript" src="http://web.hutime.org/js/HuTime.min.js"></script> <title>Sample Code</title> </head> <body> <div id="timeline"></div> <script type="text/javascript"> var ht = new HuTime(); var pnls = new HuTime.PanelCollection(200, 400); ht.appendPanelCollection(pnls, document.getElementById("timeline")); var pnl = new HuTime.TilePanel(200); pnls.appendPanel(pnl); var lyr = new HuTime.LineChartLayer( new HuTime.CalendarChartRecordset("Weather201507.csv", "Date", "Date", "Temperature")); pnl.appendLayer(lyr); var posCircle = new HuTime.TVPosition(HuTime.timeToJd(2015, 7, 10), 25); var styCircle = new HuTime.FigureStyle("lime"); lyr.processBeforeRedraw = function (layer) { HuTime.Drawing.drawCircle(styCircle, layer, posCircle, 120); }; var posTriangle = new HuTime.TVPosition(HuTime.timeToJd(2015, 7, 25), 30); var styTriangle = new HuTime.FigureStyle("aqua"); lyr.processAfterRedraw = function (layer) { HuTime.Drawing.drawTriangle(styTriangle, layer, posTriangle, 120, 30); }; ht.redraw(HuTime.timeToJd(2015, 7, 1), HuTime.timeToJd(2015, 8, 1)); </script> </body> </html>
5.パスの利用
各図形で定義されているパスを描画するメソッドは、マウスが図形の中にあるかどうかを判断する場合などに利用できる。下記のサンプルコードでは、図形内にマウスが入ると、図形の色が変化する。
サンプルコード(実行例はこちら)。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <script type="text/javascript" src="http://web.hutime.org/js/HuTime.min.js"></script> <title>Sample Code</title> </head> <body> <div id="timeline"></div> <script type="text/javascript"> var ht = new HuTime(); var pnls = new HuTime.PanelCollection(200, 400); ht.appendPanelCollection(pnls, document.getElementById("timeline")); var pnl = new HuTime.TilePanel(200); pnls.appendPanel(pnl); var lyr = new HuTime.Layer(200, 0, 0, 100, 0); pnl.appendLayer(lyr); pos = new HuTime.TVPosition(100, 50); styOut = new HuTime.FigureStyle(3, "red", "white"); styIn = new HuTime.FigureStyle(3, "red", "green"); lyr.processBeforeRedraw = function processBeforeRedraw(layer) { HuTime.Drawing.drawCircle(styOut, layer, pos, 100); }; lyr.mouseEventCapture = HuTime.EventCapture.All; lyr.addEventListener("mousemove", function(ev) { var ctx = HuTime.Drawing.pathCircle(ev.target, pos, 100); if (ctx.isPointInPath(ev.offsetX, ev.offsetY)) HuTime.Drawing.drawCircle(styIn, ev.target, pos, 100); else HuTime.Drawing.drawCircle(styOut, ev.target, pos, 100); } ); ht.redraw(50, 150); </script> </body> </html>