ラベル JavaScript の投稿を表示しています。 すべての投稿を表示
ラベル JavaScript の投稿を表示しています。 すべての投稿を表示

2014年1月27日月曜日

SVGで画像内のデータをJavaScriptから操作する

最近、後輩の仕事に関する相談をプライベートで解決するようになってきた…。

今回相談受けたのは、Webサイトに回路図のような画像を載せて、かつ図の中のデータをサーバ内のデータに応じて可変にしたいというもの。 元々は、それをHTMLでやりたい!と言っていたんだけど、さすがにその解決策は思いつかなくて、持ち帰り宿題化。

結局、解決策として提示したのがタイトルにもあるSVGを使ったアプローチ。 別の解決策として、HTML 5のCanvasタグを使って、画像を描くってのもあったけど、 Canvasタグが良く分かってなかった+SVGの方が目的には簡単だったので却下。

やったことは、InkscapeでSVGファイルを作って、それをJavaScriptで操作すること。 SVGファイルを作るのにInkscapeを使ったのは、SVGの規格標準なファイルが作れることと、 Illustratorとは違ってフリーで使えたから。

MacにInkscapeをインストール

InkscapeはX11アプリなので、単純にダウンロードしてインストールじゃ動かない。 まずは、X11のインストールが必要。と言っても、昔はMac OS XにX11も含まれてたと思うけど、 今は含まれていないのでXQuartzをインストール。

Xquartzは、XQuartzのWebサイトからダウンロードしてきて インストール。

続いてInkscapeのインストールだけど、手順は公式サイトが 詳しく書いているので割愛。

Inkscapeで画像を描く

画像のように、ごくごく簡単な画像をInkscapeで描く。今回は、「80w」の部分を可変にするイメージ。

で、可変にしたい部分は、プロパティでIDを付与する。これは自動的にも付与されるんだけど、自分で付けた方がわかりやすいと思う。

画像を描いたら、SVGファイルとして保存する。

JavaScriptから操作する

SVGファイルはXMLになっているので、テキストエディタで開いてHTMLへコピペする。

今回は、以下のようなHTMLを用意した。テキストボックスに値を入れて、「書き換え」ボタンを押すと画像が変わる。


  
  画像マッピングテスト
  


  
image/svg+xml 80w
ワット数を書き換える:

JavaScriptでこれを操作するのは、こんなコード。jQuery使ってる。

$(document).on("click", "#wButton", function() {
  console.log($("#textW01").text());
  $("#textW01").text($("#textW01edit").val());
});

こんな感じで、結構簡単に画像とJavaScriptのコラボレーションができた。

と、感動して後輩に伝えたら、上司に良くわからないものを使うな、と言われたらしい。 自分が知らないものを「良くわからないもの」で片付けるのは老害というのでは…。

2012年12月21日金曜日

VDM++のgetter・setterを生成するサクラエディタのマクロ書いた

VDM++は、仕様記述言語かつオブジェクト指向言語。VDM++にはレコード型という構造体のような型が組み込まれているし、仕様記述言語なので、タイトルにあるようなgetter・setterは使いたくない所ではある。
ただ、例えば汎用的なフレームワークやライブラリーを書きたいシーンや、コード生成を前提に周辺クラスとの連携をするシーンにおいては、インスタンス変数とgetter・setterのセットが含まれたクラスを書くこともある。
その時、このgetter・setterを書くのが面倒だと、常日頃思ってた。定型的な書き方なのに記述量は割りと多い。これを解決するには、2つの方法がある。
  • インスタンス変数をpublicにする
  • getter・setterの記述を生成する仕組みを作る
今回は、2.の生成する仕組みをサクラエディタのマクロとして実現した。Windowsでサクラエディタを使ってVDM++を書くという、超ニッチなニーズがどこにあるのか分かんないけど、少なくとも自分は常用するマクロなので、どこか他の人にもで役に立つといいなと思って公開する。

ダウンロード

GitHubからダウンロードしてください。
VDMgetterSetterGen.js

使う準備

まずは、サクラエディタにマクロの登録をする。
任意の場所にマクロを置いて、[設定] -> [共通設定]。[マクロ]タブの空いている所に、以下のように設定して、[設定]ボタンを押す。
WS001
WS001 posted by (C)mas
続いて、[キー割り当て]タブにてキーを割り当てる。例えば自分の場合は[Shift+Ctrl+g]にしてる。
WS002
WS002 posted by (C)mas
こうすれば、[ツール] -> [登録済みマクロ]以下に、設定したマクロとキーが設定されているはず。

使い方

まずは、以下のようにクラスにインスタンス変数を定義する。1行に1インスタンス変数にする。初期値はあってもなくても良い。

class EntityClass

instance variables
  id : nat := 0;
  flag : bool := true;
  aClass : Aclass;

end EntityClass

次に、getter・setterを生成するインスタンス変数を選択してコピーする。
WS003
WS003 posted by (C)mas
コピーした状態で生成したい場所にカーソルを移動し、マクロを設定したキーを押す。すると、getter・setterが生成される。
WS004
WS004 posted by (C)mas
ちなみに、boolのインスタンス変数で生成した場合は、getterがis○○になる仕様。
WS005
WS005 posted by (C)mas

仕様

  • 操作名は、「getインスタンス変数名」と「setインスタンス変数名」
  • インスタンス変数名の最初は大文字にする
  • boolのインスタンス変数は、getterが「isインスタンス変数名」になる
  • 改行コードはCRLF
もし想定通りに動かないとか、こうした方が良い、があればぜひご意見お願いします。

2012年12月9日日曜日

astah Scriptでパッケージを取り払ったXMI出力するスクリプト書いた

いや、ホントは書いてからだいぶ時間経っちゃったけど…。

astah Scriptが出た時に、これはおもしろいということで、何か作ることにした。例によって、VDM関連でできたら良いな、というものがあったので、それを作ることに。

作ったのは、パッケージに分けられたクラス構造から、パッケージが全くないフラットなクラス構造にしたXMI出力するスクリプト。

何に使うかというと、VDM++にはパッケージの概念がないので、これまでastah→VDMToolsにクラス構造をXMIエクスポートしてくると、パッケージ内のクラスが反映されなかった。

でも、クラス構造をUMLで見る場合はツリー構造になってる方が分かりやすい。そこで、XMI出力する時だけパッケージ構造を取り払うことにした。

仕様

  • パッケージを全て取り払ったクラス構造のXMI出力をします
  • XMLファイルは、元の.astaファイルがある場所に「exportFlat.xml」という固定ファイル名で出力します
  • パッケージ構造を取り払うのは一時的で、元の.astaファイルには反映されません
  • パッケージを越えて同じクラス名があった場合は、先に見つかった方が優先されます
    この時、astahのスクリプトウィンドウ下部に、「duplicate class -> クラス名」と表示されます

使い方

  1. ここからダウンロードして、ExportFlatClassXMI.jsを任意の場所に置く
  2. クラス構造を含む.astaファイルを開く
  3. メニューの [ツール] -> [スクリプト] で、スクリプトウィンドウを表示する
  4. ここからスクリプトウィンドウでの操作
    1. [ファイル] -> [開く]で、保存したExportFlatClassXMI.jsを指定
    2. [アクション] -> [実行] でスクリプト実行

制限事項

  • astahのXMI出力機能を使うため、astah* professionalが必要です
  • パッケージを全てなくしてしまうため、パッケージをまたがって同じクラス名があった場合は、 最初に発見したクラスを優先します
  • Macにおいて、円マークをファイル名やディレクトリ名に使用した場合の動作は保証できません

試行錯誤したとこ

パッケージのない構造が元ファイルに保存されると困るので、XMI出力した後で保存しないで閉じる→再度開くをしてる。もうちょっとスマートなやり方ないもんかな。

トップのパッケージをスクリプトで取得するのに、全パッケージをループして親がいないパッケージを探索する関数を書いたけど、途中で「astah.getProject()」で取れることに気づいた…。ちなみに、最初は以下のようなコードで取ってた。

function getTopPackage() {    packages = astah.findElements(IPackage);        for(var j in packages) {        if (packages[j].getOwner() == null) {            topPacakge = packages[j];        }    }    return topPacakge;}

これを使うと、astahでおおよそのクラス構造を書いて、VDMにXMIで持っていくのが便利になった。自分では常用しそうだから、スクリプトじゃなくてプラグインにしちゃった方が良いかな???

2012年12月7日金曜日

Proxy経由でastahプラグインの開発環境を作る時の注意点

astahのプラグイン開発環境を作るには、公式の開発チュートリアルがあるので、通常は特に迷うことなく環境が作れるはず。

がっ!世の中には閉鎖的な環境というのがあるもんで、Proxyのある環境ではチュートリアル通りに行かない。 ここでは、そんな環境で注意すべき点を1つ紹介。

試した環境は、Windows XPのCygwin環境。環境変数のhttp_proxyは設定してあるけど、それではダメ。astahプラグインSDKを置いた場所(ASDK_HOME)以下に設定ファイル(ASDK_HOME/conf/settings.xml)があるので、それを編集する。

90行目付近に、Proxy関連の設定があるので、それを生かすようにする。

  
    
      optional
      true
      http
      proxyuser
      proxypass
      proxy.host.net
      80
      local.net|some.host.com
    
  

動作確認するには、これを設定した上で「astah-launch」してastahが起動すればOK。

2012年8月31日金曜日

astah Scriptで遊ぼう

astah*が、JavaScriptでastahにアクセスできるプラグイン「astah Script」を出してた。ホントはETロボコンのモデルを書かなきゃいけないから遊んでる場合じゃないんだけど、遊んでたらおもしろかったので…。色々書いてみて遊んだメモを残しておく。

インストールや基本的な動かし方は、公式サイトを見てください。あと、今回作ったスクリプトは別エントリで公開しようと思ってる。例によって、VDM絡みのスクリプト。

気をつけること

getNameで取れるのは、JavaScriptのStringではない

Javaのjava.lang.Stringじゃないかと。
文字列比較が == ではできなくてequals使う必要あるし、typeofするとObjectになる。

getProjectで取れる要素の意味

開いているプロジェクトのトップ階層がAPI説明で言うところの「起点となるモデル」。
最初分からなくて、自分で取得するメソッド書いてた…。

JavaScriptのArrayクラスが持つindexOfは使えない

なぜだろう???そんなメソッドないエラーが出る。

Tips

UML版やPro版で可能なモデルの編集にはimportを追加する

importPackage(com.change_vision.jude.api.inf.editor);

XMIエクスポートみたいに、ファイルやディレクトリが絡むとMacとWindowsの関係が面倒

下のような関数を作って対応。ただし、ファイル名やディレクトリ名に円マーク使った場合は正常に動かない
var dirName = getCurrentDirectory(astah.getProjectPath());

function getCurrentDirectory(fullPath) {
  var enPos = fullPath.lastIndexOf("¥¥");
  var slaPos = fullPath.lastIndexOf("/");
  return fullPath.substring(0, enPos >= slaPos ? enPos + 1 : slaPos + 1);
}

配列に含まれているか?のindexOfは、自分で実装

Arrayとastahから取れるStringをもらって判定。仕様はJavaScriptのindexOfと一緒で、見つからなければ-1を返す。
function indexOf(org, element) {
  for (var i in org) {
    if (org[i].equals(element)) {
      return i;
    }
  }
  return -1;
}

astah.close()すると、モデルを書き換えていてもいきなり閉じる

保存しますか?ダイアログ出ないので注意
今回の用途だと、モデルは一時的に書き換えたいだけだから良かった

要求図で、起点モデルから要求の包含関係を辿るスクリプト

ただし、satisfyやderiveReqtで繋がる要求まではカバーしない
importPackage(com.change_vision.jude.api.inf.model);

var req = astah.findElements(IRequirement);
for(var i in req) {
  if (req[i].getNestedClasses().length != 0) {
    if (req[i].getOwner().getName() == astah.getProject().getName()) {
      println(req[i].getName());
      printNestClass(req[i], 1);
    }
  }
}

function printNestClass(req, depth) {
  var nestClasses = req.getNestedClasses();
  for(var j in nestClasses) {
    for(var k = 0; k < depth; k++) { print("    "); }
      println("|- " + nestClasses[j].getName());
      if (nestClasses[j].getNestedClasses().length != 0) {
        printNestClass(nestClasses[j], ++depth);
      }
    }
  }

使ってみて思ったこと

  • おもしろい、簡単
  • JavaScript上の問題なのかJavaの問題なのかが切り分け辛い
  • Groovyあたりで書いた方がJavaとの親和性も高くてやりやすいかも
    • Groovyで書いておけば、astah Scriptでちょろっと試して、それをプラグインまで持ってくのがラクかも