CoffeeScript – geom2d.Vectorクラス

パッケージ

taustation_geom2d

クラス名

taustation_geom2d.Vector

クラス仕様

概要

x、y二つの成分を持ち、絶対値の計算や加減乗算など2次元ベクトルの代数演算を行うメソッドを提供する。

クラス変数

なし

クラス・メソッド

distance(pos1, pos2)
2つのVectorオブジェクトpos1、pos2を点を表す位置ベクトルとして、2点間の距離を返す。

インスタンス・プロパティ

x
ベクトルのx成分
y
ベクトルのy成分

コンストラクタ

constructor(x, y)
x成分とY成分を指定してVectorのインスタンスを生成する。

インスタンス・メソッド

基本メソッド

set(x, y)
Vectorのx成分とy成分をセットする。
toString()
Vectorの文字列形式の表現を返す。
getClone()
元のVectorオブジェクトと同じ内容のクローンを生成して返す。

演算

abs
Vectorの絶対値(長さ)を返す。
times(coeff)
Vectorに定数coeffを乗じたベクトルを新たに生成して返す。
timesEq(coeff)
Vectorに定数coeffを乗じて変更する。新しいオブジェクトは生成しない。
div(coeff)
Vectorを定数coeffで除したベクトルを新たに生成して返す。
divEq(coeff)
Vectorを定数coeffで除して変更する。新しいオブジェクトは生成しない。
plus(other)
Vectorにotherベクトルを加えたベクトルを新たに生成して返す。
plusEq(other)
Vectorにotherベクトルを加えて変更する。新しいオブジェクトは生成しない。
minus(other)
Vectorからotherベクトルを減じたベクトルを新たに生成して返す。
minusEq(other)
Vectorからotherベクトルを減じて変更する。新しいオブジェクトは生成しない。
inprod(other)
Vectorとotherベクトルの内積値を返す。
ang(other)
Vectorとotherのなす角を計算する(0~π)。

新たなVectorの生成

getUnit()
Vectorと同じ向きの単位ベクトル(長さが1)を新たに生成して返す。
getInverse()
Vectorと逆向きのベクトルを新たに生成して返す。
getOrthogonalR()
Vectorから右に90度回転したベクトルを新たに生成して返す。
getOrthogonalL()
Vectorから左に90度回転したベクトルを新たに生成して返す。
getUnitOrthogonalR()
Vectorから右に90度回転した単位ベクトルを新たに生成して返す。
getUnitOrthogonalL()
Vectorから左に90度回転した単位ベクトルを新たに生成して返す。

判定

isHeadingToRightOf(other)
このVectorオブジェクトの進行方向が、引数のVectorオブジェクトotherの進行方向より右方を指しているときtrue、左方を指しているときfalseを返す。
isHeadingToLeftOf(other)
isHeadingToRightOf()と左右逆の判定結果を返す
isInFrontOf(movingAgent)
このVectorオブジェクトが位置ベクトルとして、その点が引数のMovingAgentオブジェクトの前方(左右180度より進行方向の側)にあるときtrue、後方にあるときfalseを返す。真横の時は前方と判定される。
isIntheRearOf(movingAgent)
isInFrontOf()と前後逆の判定結果を返す。
isOnTheRightOf(movingAgent)
このVectorオブジェクトが位置ベクトルとして、その点が引数のMovingAgentオブジェクトの右方にあるときtrue、左方にあるときfalseを返す。進行方向の延長線上にあるときは右方と判定される。
isOnTheLeftOf(movingAgent)
isOnTheRightOf()と左右逆の判定結果を返す。

コード

 

CoffeeScript – グローバル変数

グローバルにならない

CoffeeScriptでグローバル変数を期待して以下のように書いたとする。

一見すると問題なく動いているように見えるが、これを別ファイルのパッケージにして動かそうとすると問題が顕在化する。以下のように”globalVarが存在しないよ”というエラーが出るのである。

これら2つのファイルをjsにコンパイルしてブラウザのscript要素で読み込んだ場合、そのイメージは以下のようになる。

パッケージでグローバル定義したつもりだが、コンパイル時に無名関数でクロージングされるため、グローバルにならず、他のファイルから読み込むことができない。

解決策1

グローバル変数をwindowオブジェクトの要素にしてしまう。

解決策2

rootコンテキストで、以下のパターンを使う。

 

WordPress – Faviconの追加

概要

WordPressで作っているサイトのアイコン(ブラウザのお気に入りなどで表示される小さいアイコン)が透過色の書類マークのままで殺風景なので、自分用のFaviconを作って適用してみた。

Faviconとは、Favorite Iconの略だそうである。

アイコン画像の準備

アイコン画像を作成し、透過色を指定してPNGやGIFで保存する。

今回は、PowerPointで作成した図柄をPNG形式で保存し、ペイントアプリケーションで切り取ってPNG形式で保存。

透過色の指定は、Exce使った方法で行った。

icoファイル化

FavIcon from Picsというサイトで、PNGファイルをicoファイル化。Webサイトにファイルをアップロードし、変換されたファイルをダウンロード。

WordPressへのFaviconの登録

Faviconファイルやその元となったファイルをWordPressのメディアに登録。

テーマのheader.phpを編集する方法とプラグインを利用する方法があるが、今回はFavicon Rotatorというプラグインを使った。

Favicon RotatorをインストールするとWordPressの”外観”メニューに”Favicon”メニューが追加されるので、それをクリック。

ファイルを新たにアップロードするとメディアに追加されるが、ここでは先にメディアに追加済のicoファイルを指定。

これでお気に入りに表示されるFaviconが変更される。

 

WordPressでCanvas要素が消える

消えるcanvas

WordPressのテキストモードでcanvas要素を書いて、ビジュアルモードに切り替えてもう一度テキストモードに戻ったとき、canvas要素が消えてしまうことがあった。

いろいろと試しているうちに、以下のような挙動があることがわかってきた。

  • <canvas>タグと</canvas>タグを直接一行でつないだ時に消えるらしい
  • canvas要素の前後が空行かどうかでも結果が変わるらしい

そこで、タグの書き方と前後の空行の入れ方の組み合わせで、canvasが消えるかどうかをチェックした。

canvasが消える条件

<canvas></canvas>のように開始タグと改行タグが連続して書かれていて、なおかつ以下のケースの時にcanvas要素が消える。

ケース1:ファイルの中に単独で書いた場合

開始タグと終了タグが<canvas></canvas>のように連続しており、それのみがファイルの中に書かれている場合、ビジュアルエディタを経由すると要素が消える。行末の改行があってもなくても結果は同じ。

ケース2:前後に空行がある場合

開始タグと終了タグが<canvas></canvas>のように連続しており、その行の前後に空行がある場合、ビジュアルエディタを経由すると要素が消え、&nbspに書き換えられる。

実質的にファイルの中にcanvas要素のみがあることは稀なので、問題となるのは上記の”<canvas></canvas>の前後に空行がある場合”となる。

canvasが消えない条件

canvasが消えない条件は、上の「canvasが消える条件」の裏返しも含めて以下のようになる。

ケース1:開始タグと終了タグの間に文字があること

開始タグと終了タグの間に文字があれば、周辺条件がどうであってもcanvas要素は消えない。

canvas要素非対応のブラウザ対応のために、この方針をとることには意義がある。

ただし、間にある文字がスペースだけの場合は意味がなく、開始タグと終了タグが連続している場合と同様の結果になる。

ケース2:開始タグと終了タグの間で改行されていること

開始タグと終了タグの間で改行されていれば、周辺状況がどうであってもcanvas要素は消えない。

canvas要素内に文を書かない場合は、簡易な一つの解決策。

ただし、開始タグと終了タグの間に空行が入っている場合は結果は複雑で、要素全体が消えたり、いずれかのタグだけが消えたりと結果は複雑になる。

ケース3:前後に空行がないこと

前後に行があれば(どちらも空行でなければ)開始タグと終了タグが連続していてもcanvas要素は消えない。

ただし、確実にこの記述方法に拠ることを担保しがたい。

結論

以下の2つのうちいずれかを推奨。

  • 開始タグと終了タグの間にcanvas非対応用の文を書く
  • 開始タグ<canvas>の後で改行し、すぐ次の行に終了タグ</canvas>を書く

 

Windows – 透過色の図形

Windowsで透過色を含んだpngやgifファイルを作成するのに、同梱アプリケーションの「ペイント」では、疑似的にしか再現できない。

ネット上で調べると、以下のような方法があることがわかったので記録。

  1. 「ペイント」などで図形を描いて保存(pngやgifで)
  2. 図形ファイルをExcelで読み込み
  3. 「書式」→「色の変更」→「透過色を指定」
  4. 透過色に変更したい色の部分をクリック
  5. web形式で保存し、必要なファイルを取り出す

 

CoffeeScript – パッケージ管理

パッケージ化の方法について

簡単な方法~齟齬あり

クラス/オブジェクトのプロパティにする

クラスやオブジェクトをパッケージの名前とし、パッケージ内のクラスなどはそのプロパティとして定義する。

ただしこの方法は、最適とは言えない。

1行目で名前空間に用いるクラスを定義し、7行目でMyClassPack1のプロパティとしている。

10行目で名前空間に用いるオブジェクトを定義し、16行目でMyClassPack2のプロパティとしている。

20行目でMyClass単独を用いた場合、直前に13行で定義されたMyClassが参照される。

パッケージ内での名前参照の祖語

パッケージ間で名前が重複する場合、下手をすると想定外のオブジェクトが使われてしまう。

次の例は、Pack1Pack2の2つのパッケージで同じクラス名を使い、各パッケージの中ではパッケージ名なしで使おうとしたもの。

ところが29行目で、Pack1のクラスのはずのところがInnerClassにはPack2のものが使われてしまっている。

これは、25行目以降の実行文の前にグローバル変数InnerClassの内容Pack1のものからPack2のものへと上書き定義されたため。

結局この方法だと、各パッケージの中でもクラス名の前にパッケージ名をつけないといけないようで、コーディング上は元のクラス名に識別子を組み込むのとあまり変わらない。

有効な方法~即時実行関数

先の方法は、すべてグローバル領域で行われていたため、パッケージ内でのみ参照するクラスも上書きされてしまった。

そこで、パッケージごとに即時実行される無名関数で括ってみる。

1行目のようにグローバル領域でパッケージ名に使うオブジェクト/クラスを定義し、パッケージごとに即時無名関数で括る。

パッケージ内ではパッケージなしでアクセスし、外からアクセスするときはパッケージ名を付してアクセス。

これで一応、パッケージ化とコーディングの簡易化を両立させることができる。

パッケージ名について

パッケージ名は、「世界規模での名前衝突を避ける」ように潔癖を極めるなら、Javaで行われているようなドメイン名管理が答となる。

なお、Javaの場合はimport文で指定したパッケージはクラス名のみで使えるが、Javascriptではエイリアスを明示的に指定しなければならないらしい。

JavaScriptスタイルガイドでは、「長い型名をエイリアスし可読性を向上させる」ために以下のように示唆されている。

“ローカルのエイリアスを使うことで長い型名の可読性を向上できる場合はそうしてください. エイリアスの名前は型名の最後の部分にしてください.”

なお、npmのサイトでいろいろなパッケージを見てみると、区切りにはアンダースコア(_)ではなくマイナス(-)を使っている。

 

CoffeeScript – タイマ

setInterval

setInterval()関数の引数に、アニメーションフレームを描画する関数と時間間隔を指定する。時間間隔はミリ秒単位。

描画の開始/停止をコントロールするには、setInterval()関数の戻り値を変数に保存しておき、停止するときにclearInterval()関数の引数でその変数を指定する。

一時停止/再開の機能は特に実装されていないが、描画関数を工夫することで可能。

描画関数を、以下のように無名関数で書くこともできる。

この処理を他のオブジェクトのメソッドの中に書いて、オブジェクトのプロパティを利用する場合は、1行目のアローをファットアロー(=>)にする。

 

CoffeeScript – クラスのメソッド

アクセス可能性

以下のコードで、クラスの関数へのアクセス可能性を確認する。

各関数へのアクセス可能性は以下の通り。

定義\引用 クラス インスタンス メソッド内
(@なし)
 メソッド内
(@つき)
fnc: ->  TypeError  ○ ReffError
@fnc: ->  ○ TypeError ReffError TypeError
fnc = -> TypeError TypeError TypeError
@fnc = -> TypeError ReffError TypeError

なお、上記コードの定義部分のJavaScriptコンパイル結果は以下の通り。

クラス・メソッド

クラス内で@つきでメソッドを定義すると、クラスメソッドになる。

上記のいずれもJavaScriptへのコンパイル結果は同じになる。

クラスメソッドは、クラス内で呼び出すときでもクラス名をつける。

publicなインスタンス・メソッド

最も多く用いる形で、クラス内でコロン(:)によって関数を定義すると、インスタンス・メソッドになる。

JavaScriptへのコンパイル結果では、prototype宣言されている。

同じクラスのメソッド内で呼び出すときは、@つきで。

privateなクラス・メソッド

クラス内でfnc = ->のように定義すると、クラスの外からは見えないprivateなメソッドになる。

JavaScriptコードでは、クラス内のスコープで宣言されており、外からは見えない。

 

CoffeeScript – クラスのプロパティ

アクセス可能性

以下のコードで、クラスに関する変数へのアクセス可能性を確認する。

各変数へのアクセス可能性は以下の通り。

定義\引用 クラス インスタンス メソッド内
(@なし)
メソッド内
(@つき)
クラス直下 v=val undef undef undef
@v=val undef undef RefError undef
v:val undef RefError
@v:val undef RefError undef
コンストラクタ v=val undef undef RefError undef
@v=val undef RefError

この表から、以下のように整理できる。特にpublicなインスタンス・プロパティとstaticなクラス・プロパティを使っていくことになる。

クラス直下で@v:val定義 staticなクラス・プロパティ
クラス直下でv:val publicなインスタンス・プロパティ
 コンストラクタで@v=val publicなインスタンス・プロパティ
 クラス直下でv=val  privateなクラス・プロパティ

なお、定義部分のJavaScriptへのコンパイル結果は以下の通り。

クラス・プロパティ

クラス直下で@v:valでプロパティを定義する場合、プロパティはクラスに一つの共有のものとして扱われる。コンパイルされたJavaScriptコードでは正に”[クラス名].[プロパティ名]“となっている

インスタンスの中から参照する場合も、[クラス名].[プロパティ名]で参照する。

publicなインスタンス・プロパティ

クラス直下でv:valと定義した場合とコンストラクタで@v=valと定義した場合は、いずれもインスタンス・プロパティとして扱われる。

挙動としては同じなのでどちらでもよさそうだが、インスタンス・プロパティとしてはコンストラクタで定義する形式の方がよいと考えた。

以下のように、それぞれの定義方法でJavaScriptのコードが異なるが、メソッドのようにクラス内で共通化したい場合はprototypeがよいが、そもそもインスタンスごとに異なる値をとることを想定しているプロパティの場合は、thisによる定義の方が意味に即している。

privateなクラス・プロパティ

クラス直下でv=valと定義すると、そのクラスの各インスタンスで共有されたprivateなプロパティになる。

JavaScriptコードを見るとクラス宣言の最初でvar宣言されているため、クラス内スコープで外からは見えない変数となる。

 

CoffeeScript – jQueryによるINPUT要素の操作

jQueryによるINPUT要素の操作

ボタンのテスト

ここではボタン操作に対するイベントを確認している。

ボタンはinput要素のタイプの一つとして作成される。
ボタンが押された時のイベントはonclick属性で定義してもよいが、ここではそれを使わず、jQueryのハンドラで処理している。

ボタンが押下されたときのイベントは、(そのボタンが動的に後から追加されたものでなければ)click()で捕捉される。

テキストボックスのテスト

入力:
出力:

ここではテキストボックスの内容の取得や書き込みについて確認している。

テキストボックスの内容の取得や設定はval()メソッドで行う。

チェックボックスのテスト

チェックボックスの確認。

チェックボックスのチェック状態の取得には、prop()メソッドを用いる。

ラジオボタンのテスト

通知エリア

  

ラジオボタンの動作を確認している。ここでは選択状態が変わるごとにイベントが発生して、通知エリアの表示が変わる。

上段はブラウザ側のonchange属性でイベントハンドラを指定し、下段はjQueryのハンドラを使っている。

セレクトボックスのテスト

通知エリア




セレクトボックス(ドロップダウンリスト)の例。

  • ボックス内の選択肢を選ぶたびに通知エリアの表示が変わる
  • “LONDONへ”ボタンを押すと、ロンドンが選択された状態になる。
  • “追加”ボタンで選択肢に”パリ”が追加され、”削除”ボタンで削除される

セレクトボックスの状態変化のイベントは、change()メソッドで捕捉される。

“追加”と”削除”のボタンはprop()メソッドを使って選択状態をトグルさせているが、ページのテーマ/デザインによっては明確にはわからないことがある。