サイトトップ

Director Flash 書籍 業務内容 プロフィール

HTML5テクニカルノート

EaselJSの次期バージョンにおけるオブジェクトの幅と高さの取得

ID: FN1307004 Technique: HTML5 and JavaScript Library: EaselJS NEXT

EaselJSのDisplayObjectインスタンスについては、基本的にオブジェクトの幅や高さが調べられません。CreateJS Blogの記事「Width & Height in EaselJS」にそれが難しい理由と、次期バージョン(NEXT)に備わる簡易的なメソッドが紹介されました。その記事にもとづいて解説します。


01 Shapeオブジェクト

ベクターシェイプは大きな課題のひとつです。ちょっと考えると、境界領域を求めるのは、さほど難しくないように感じられます。すでにあるShapeオブジェクトのデータは変わりませんから、新たなパスが加わったときにその範囲を調べて、最大値・最小値から改めて矩形領域を決めればよさそうです。

単純な直線くらいでしたら、それでよいでしょう(図001左図)。けれど、線に加えられるプロパティの様々な定めを考えると、たちまち複雑になります。線幅を20ピクセルにすれば、端の増減する領域を三角関数で計算しなければなりません(図001中左図)。しかも、端のかたち(buttやsquare、あるいはround)も考え合わせなければなりません(「EaselJSのGraphicクラスで2次ベジエ曲線を描く」表001参照)。

図001■連続した座標を軌跡として描く
図001

20ピクセルの線を曲げると、領域の計算はさらに難しくなります。数学的にはできるとしても、線の幅や2次ベジエと3次ベジエを正確に計算することが求められます。曲線の端の角度も求めなければ、正しく領域が定められません(図001中右図)。

線の角のかたち(bevelやround、あるいはmiter)も、忘れてはいけません(前出「EaselJSのGraphicクラスで2次ベジエ曲線を描く」表002参照)。さらに、線の角のとがり方(miterLimit)の計算も含まれます(図001右図)。

これらすべての計算ができたとしても、きわめて負荷は高くなります。そこまでしても、実装すべきかどうかが問われます。


02 オブジェクトの変形

オブジェクトの変形について考えます。コンテンツを境界ボックスで囲み、それを変形すればよいのでしたら、計算は楽です。境界ボックスの四角を変形して、新たな矩形領域を決めればよいからです。けれど、ベクターシェイプではそうはいきません。

つぎの図002の左のような単純な曲線を、45度回したとします。境界ボックスの四角から新たな矩形領域を求めれば、図002の真ん中のようになってしまいます。しかし、正しい領域は図002の右のように定めなければならないでしょう。

図002■ベクターシェイプを変形したときの矩形領域
図002

すると、シェイプ上の適切な点すべてについて、変換行列の演算を行わなければなりません。点を間引くロジックで処理が減らせるとしても、負荷は高いでしょう。とくに、表示リストの異なる階層から領域を調べると、座標空間ごとに計算はし直すことになります。


03 Textオブジェクト

Textオブジェクトの扱いは、さらに難しくなります。CanvasのテキストのAPIからは、領域を求めることができません。ただ、幅は調べられるので、テキストの配置にもとづいて正しくオフセットできます。

高さは求められません。そこで、正確には程遠いものの、文字「M」の幅から推測することが考えられます。高さが大まかにでも捉えられれば、Text.textBaselineプロパティ(次期バージョンから値は、"top"と"hanging"、"middle"、"alphabetic"、"ideographic"、および"bottom"の6つ)にもとづいてオフセットが決められます。

図003■Text.textBaselineプロパティの設定
図003

Textオブジェクトの矩形領域は、今のところ求められません。Canvas APIは新たにテキストのメトリクスを拡張したので、この計算ができるようになります。ただし、今のところサポートするブラウザがありません。


04 次期バージョンでgetBounds()メソッドが備わる

DisplayObjectインスタンスの矩形領域は、今のところ調べる手段を備えるのは難しいようです。その代わり、次期バージョンに簡易なメソッドとして、SpriteおよびBitmapクラスにgetBounds()が加わります[*1]。つぎのようなことが考えられています。

  • キャッシュされたオブジェクトに適用できる。
  • Containerオブジェクトに適用したとき、子オブジェクトのメソッドを呼出して領域を調べる。
  • setBounds()メソッドで領域が変えられる。
  • TextオブジェクトはText.textBaselineプロパティを"top"にしたとき大まかな領域が得られる。

記事「Width & Height in EaselJS」では、このような考えに対して混乱や不満が生じないか、ユーザーの意見を求めています。


[*1]「EaselJS vNEXT API Documentation」によると、オブジェクトの変形は反映されないようです。



作成者: 野中文雄
作成日: 2013年7月24日


Copyright © 2001-2013 Fumio Nonaka.  All rights reserved.