【CreateJS】Canvasのアニメーションを動的に切り替える

Canvasでアニメーションだけなら、JavaScript書かずにFlash CC(Animate CC)で書き出せばいいよね。Flashまだまだ使えるよ!なんですが、実際運用するとなると、ある時期でアニメーション切替、追加、削除等の変更が出てきます。AS3.0ならloadMovieでswf切り替えればよかったんですが、「CanvasにはloadMovieとかないし、どうするの?」と思ったら、意外とカンタンな話だったのでまとめておきます。

まずはアニメを作ります。
1つ目。Flash CC(今回はFlash CC 2015を使用)で、新規から「HTML5 Canvas」を選択してクラッシックトゥイーンでアニメーションして書き出しただけ。完成品はこちら

アニメその1

 

2つ目。作り方は同じ。完成品はこちら

anime2

 

で、2つ目のアニメを例に、Flash CCが書き出したHTMLとJavaScriptを見てみると・・・

・HTML抜粋(anime2.html)

<script>
var canvas, stage, exportRoot;

function init() {
	canvas = document.getElementById("canvas");
	exportRoot = new lib.anime2();

	stage = new createjs.Stage(canvas);
	stage.addChild(exportRoot);
	stage.update();

	createjs.Ticker.setFPS(lib.properties.fps);
	createjs.Ticker.addEventListener("tick", stage);
}
</script>

・JavaScript抜粋(anime2.js)

// stage content:
(lib.anime2 = function(mode,startPosition,loop) {
	this.initialize(mode,startPosition,loop,{});

	// timeline functions:
	this.frame_119 = function() {
		//this.stop();
	}

	// actions tween:
	this.timeline.addTween(cjs.Tween.get(this).wait(119).call(this.frame_119).wait(1));

	// レイヤー 2
	this.instance = new lib.mc_girl();
	this.instance.setTransform(698.1,205,3,3,0,0,0,41.1,143.8);

	this.timeline.addTween(cjs.Tween.get(this.instance).to({x:283.1,y:463},59).to({scaleX:4,scaleY:4,x:-154.8,y:479},60).wait(1));

	// レイヤー 3
	this.shape = new cjs.Shape();
	this.shape.graphics.f("#FF9900").s().p("Egq9AfPMAAAg+eMBV6AAAMAAAA+eg");
	this.shape.setTransform(275,200);

	this.timeline.addTween(cjs.Tween.get(this.shape).wait(120));

}).prototype = p = new cjs.MovieClip();

 

JSファイルでは、アニメーション全体がlib.anime2として定義されていて、それをHTML側に書いたJavaScript(init)でstageにaddChildしているという構造です。

なので、アニメーションの再生フレームを監視して、再生し終わったらremoveChildで削除して、次のアニメーションをaddChildすれば言いわけです。で、この2つのアニメーションを切替再生するためにJavaScript部分を書き直したHTMLがこちら。

・HTML(anime_switch.html)

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>anime_switch</title>

<script src="http://code.createjs.com/easeljs-0.8.1.min.js"></script>
<script src="http://code.createjs.com/tweenjs-0.6.1.min.js"></script>
<script src="http://code.createjs.com/movieclip-0.8.1.min.js"></script>
<script src="anime1.js"></script>
<script src="anime2.js"></script>

<script>
var canvas, stage, exportRoot;
var animeArray = ["anime1","anime2"];
var count_anime;

function init() {
	canvas = document.getElementById("canvas");
// 	exportRoot = new lib.anime2();

	count_anime = 0;
	exportRoot = new lib[animeArray[count_anime]]();

	stage = new createjs.Stage(canvas);
	stage.addChild(exportRoot);
	stage.update();

	createjs.Ticker.setFPS(lib.properties.fps);
	createjs.Ticker.addEventListener("tick", stage);
	createjs.Ticker.addEventListener("tick",onCheckAnimationEnd);
}

function onCheckAnimationEnd(event){
	if (exportRoot.timeline.position >= (exportRoot.timeline.duration-1)){

		count_anime++;
		count_anime = count_anime > (animeArray.length-1)  ? 0 : count_anime;

		stage.removeChild(exportRoot);

		exportRoot = new lib[animeArray[count_anime]]();
		stage.addChild(exportRoot);
	}
}

</script>
</head>

<body onload="init();" style="background-color:#D4D4D4">
	<canvas id="canvas" width="550" height="400" style="background-color:#FFFFFF"></canvas>
</body>
</html>

※完成サンプルはこちら

要点は以下の通り。

  • 両方のアニメーションのjsを読み込む(9-10行目)
  • アニメーションを切り替えるためのライブラリ名は配列化(15行目)
  • 再生順を管理するためのカウンタ変数を追加(16行目)
  • アニメーション再生監視用に関数を追加(31,34-45行目)

今回のCreateJSでのASとの相違部分は以下です。

処理 AS JavaScript
現在のフレーム数 mc.currentFrame mc.timeline.position
総フレーム数 mc.totalFrames mc.timeline.duration

 

【追記】
2つのアニメーションを1つのflaファイルに、それぞれMovieClipとして作成した場合は、JSファイル上は・・・

  • lib.anime1
  • lib.anime2

のように定義されるので、この名前でaddChildできます。よって、必ずしもアニメーションを別ファイルで作成する必要はありません。

※今回のようにアニメーション全体を切り替える場合、実際には別ファイルと管理する方が楽だと思います。

上記の説明は、私の環境のFlash CCで書き出される下記のバージョンのCreateJSを前提としています。

<script src="http://code.createjs.com/easeljs-0.8.1.min.js"></script>
<script src="http://code.createjs.com/tweenjs-0.6.1.min.js"></script>
<script src="http://code.createjs.com/movieclip-0.8.1.min.js"></script>

【参考】
今回はtwitterでのやりとりが元になりました。gyoh_kさん野中さんに感謝。

gyoh_kさんのツイート
野中 文雄さんのツイート1
野中 文雄さんのツイート2

【追記】2016.6.9
野中さんさんから、「MovieClip.currentFrameプロパティは前からあり、EaselJS 0.8.1 でMovieClip.totalFramesプロパティが加えられました。」とのご指摘を受けました。CreateJSとASの対応表を下記のように修正します。

処理 AS JavaScript
現在のフレーム数 mc.currentFrame mc.timeline.position,mc.currentFrame
総フレーム数 mc.totalFrames mc.timeline.duration,mc.totalFrames

 

currentFrame,totalFramesを使ったサンプルはこちら

参考
FN1506001 | EaselJS 0.8.1: MovieClipオブジェクトの再生の長さ・フレーム数を調べる | HTML5 : テクニカルノート
EaselJS v0.8.2 API Documentation : MovieClip – currentFrame
EaselJS v0.8.2 API Documentation : MovieClip – totalFrames

【数学】回転した正方形とそれを囲む正方形との辺の比

ちょっとタイトルが意味不明な感じですが・・・

square01

こんな感じで、正方形をθだけ回転したときの、回転した正方形を囲む正方形(c:c’)との辺の比を知りたい。ということで計算式を考えたのでメモ。

square02

直角三角形では、ピタゴラスの定理が成り立つ(斜辺を c、他の辺を a,b としたとき、a*a+b*b=c*c)ので 元の三角形を囲む 4 つの直角三角形(赤い部分)は合同。また c’ = a + b となる。

【参考】ピタゴラスの定理 – Wikipedia
※「正方形を用いた証明」の項を参照。

square03

この赤い部分の直角三角形1つ取りだしてを考えると、 tanθ= a / b なので・・・
a = b * tanθ
b = 1 / tanθ
a*a+b*b=c*c なので、仮に c=1 とすると・・・
a = b * tanθ
b = 1 / tanθ
a*a+b*b=c*c なので、仮に a=1 とすると・・・
1 *1 + (1 / tanθ)*(1 / tanθ) = c*c
c = sqrt(1*1 + (1 / tanθ)*(1 / tanθ))
ここで外側の正方形の辺を 1 とし、それに対する内側の正方形の辺の比を n とすると、 c : a + b=n : 1
n = c / (a+b) = c / (1 + b) = 1*1 + (1 / tanθ)*(1 / tanθ) / (1 / tanθ)

※「sqrt」はルートを求めるための関数です。念のため。
※ここで 仮に a=1 にしているのは、求めたいのは辺の長さではなくて、辺の比なので、たぶん問題ないはず。

とあるプログラムに組み込んで意図通り動いているので問題ないと思うけど、間違いがあればご指摘下さい。

【参考】直角三角形の1辺の長さと 角度はわかっています。90度 15度 75度、底辺の長さ... - Yahoo!知恵袋

【追記】2016.2.22
上の囲みの部分ですが、野中さんからご指摘を受けてもっとカンタンに考えられることがわかりましたので追記します。

この赤い部分の直角三角形1つ取りだしてを考えると、
sinθ= c / a
cosθ= c / b
tanθ= a / b
なので、仮に c=1 とすると・・・

a = sinθ / 1 = sinθ
b = cosθ / 1 = cosθ
1 = sinθ*sinθ + cosθ*cosθ

ここで外側の正方形の辺を 1 とし、それに対する内側の正方形の辺の比を n とすると、
c : a + b = n : 1
1 : (sinθ+ cosθ) = n : 1
n = 1 / (sinθ+ cosθ)

※c = 1 とするのは、三角関数で一般的な単位円(半径 = 1)の考え方ですね。
【参考】sinとcosは何する関数? | Creators MeetUp vol. 22

【Xcode】Cardboard for unityのデモをXcode7で書き出す際の注意点

【OSX 10.11.3+Xcode 7.2.1+Unity 5.3.2f1+iPhone5(iOS 9.2.1)】

VRも盛り上がりを見せつつある昨今、iPhoneでVRのテストをしてみようかとググっていて、こんな記事を見つけました。

Cardboard SDK for Unityを使ってVR対応アプリを作る & Live2Dのキャラを目の前に召喚する – Qiita

以前、「ぱのかの」(現「ルクルク」)のイベントでスマホ用ビューアをもらったことを思い出しました。

IMG_1196
ぱのかの(ルクルク)ビューア。 ここ で手に入ります。

とりあえず「Cardboard SDK for Unity」のデモをテストしてみてみました。手順は下記のリンクを参照。

iOS 用 Unity のスタート ガイド  |  Cardboard  |  Google Developers

で、この記事通りに進めてみたもののXcodeからの書き出しでエラーになります。Xcode7リリース前の記事であるため、2点ほどエラーになった箇所があり、その対処のための備忘録です。

Xcode7.2.1でbitcodeエラー

Unityからビルドすると、Xcodeのプロジェクト一式が書き出されるので、プロジェクトファイル(今回は”Unity-iPhone.xcodeproj”)をXcodeで開くことになります(今回初めて知りました)。

で、Xcodeからビルドすると下記のようなエラーになります。

ld: '/Users/c_geru/work/unity/testProject/xcode/Libraries/Plugins/iOS/libvrunity.a(vraudio_unity.o)' does not contain bitcode. You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)

これは、プロジェクト設定の Build Settings > Enable BitcodeをNOにすればいいらしい。詳しくは下記参照。

Xcode7でbitcodeのエラーが出た – Qiita

Xcode7.2.1で”_SecTrustEvaluate”エラー

で、もう一回ビルドしてみると、今度は別のエラーが2件。

Undefined symbols for architecture armv7:
  "_SecTrustEvaluate", referenced from:
      ___75-[GTMSessionFetcher URLSession:task:didReceiveChallenge:completionHandler:]_block_invoke651 in libvrunity.a(GTMSessionFetcher.o)
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Undefined symbols for architecture armv7:
  "_SecTrustEvaluate", referenced from:
      ___75-[GTMSessionFetcher URLSession:task:didReceiveChallenge:completionHandler:]_block_invoke651 in libvrunity.a(GTMSessionFetcher.o)
ld: symbol(s) not found for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)

これらは、Security.frameworkが足りないことによるエラーのようです。プロジェクト設定の General > Linked Frameworks and Libraries で Security.framework を追加してやればOK。詳しくは下記参照。

[Unity] Xcodeで”_SecTrustEvaluate”, referenced from: エラーが出る – Qiita

これで無事、実機にビルドできました。

iPhone5にビルドした様子。
iPhone5に「Cardboard SDK for Unity」のデモをビルドした様子。

【Cordova】Cordova を使ってみよう(2)Androidでスプラッシュスクリーンを表示する

【OSX 10.11.3 + Node.js v4.2.6 + nam 3.5.3 + Cordova 6.0.0 + Xcode 7.2 + Android Stuido 1.3】

※ターミナルのコマンドについては、$を省略しています。理由はコピペの時に必要ないからです。

Cordovaの続きです。前回に引き続き、下記サイトを参考にAndroidでスプラッシュスクリーン表示をテストしてみました。

Cordova: アプリの設定 – Build Insider

これが意外にハマりました。原因は、参考サイトではCordovaのバージョンが3.0.0なのに対して、現在は6.0.0なので仕様が変わっているようです。以下、手順です。

1.Splashscreen プラグインのインストール

Cordovaのバージョン4.0.0以降、スプラッシュ・スクリーンの機能がプラグイン化されたようです。ターミナルから以下のコマンドでインストールします。

cordova plugin add cordova-plugin-splashscreen

【参考】Apache Cordova のスプラッシュ・スクリーン表示がややこしい | まさくらのブログ
※本サイトでエラーが出ているので、暫定的にキャッシュをリンクしました。

2.config.xmlの設定

config.xmlに設定を書き込みますが、これはプロジェクトディレクトリの直下(今回の場合は、hello/config.xml)にあるファイルです。hello/platforms/android/res/xml/にも同名のファイルがあるので注意。

基本的に設定は、プロジェクトディレクトリ直下のconfig.xmlを変更して、プラットフォーム別のプロジェクトに反映するようです。

Androidのスプラッシュスクリーンは、以下の2つを設定します。
・タグの中に解像度別の画像リンク。
・widgetタグの中にスプラッシュスクリーンの表示時間を指定したタグ(preference name=”SplashScreenDelay” value=”10000″)。

<?xml version='1.0' encoding='utf-8'?>
<widget id="com.example.hello" version="1.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
    <name>HelloWorld</name>
    <description>
        A sample Apache Cordova application that responds to the deviceready event.
    </description>
    <author email="dev@cordova.apache.org" href="http://cordova.io">
        Apache Cordova Team
    </author>
    <content src="index.html" />
    <plugin name="cordova-plugin-whitelist" spec="1" />
    <access origin="*" />
    <allow-intent href="http://*/*" />
    <allow-intent href="https://*/*" />
    <allow-intent href="tel:*" />
    <allow-intent href="sms:*" />
    <allow-intent href="mailto:*" />
    <allow-intent href="geo:*" />
    <platform name="android">
        <allow-intent href="market:*" />
        <splash src="platforms/android/res/drawable-port-ldpi/splash.9.png" density="port-ldpi" /><!--200x320-->
        <splash src="platforms/android/res/drawable-port-mdpi/splash.9.png" density="port-mdpi"/><!--320x480-->
        <splash src="platforms/android/res/drawable-port-hdpi/splash.9.png" density="port-hdpi"/><!--480x800-->
        <splash src="platforms/android/res/drawable-port-xhdpi/splash.9.png" density="port-xhdpi"/><!--720x1280-->
        <splash src="platforms/android/res/drawable-land-ldpi/splash.9.png" density="land-ldpi" />><!--320x200-->
        <splash src="platforms/android/res/drawable-land-mdpi/splash.9.png" density="land-mdpi"/><!--480x320-->
        <splash src="platforms/android/res/drawable-land-hdpi/splash.9.png" density="land-hdpi"/><!--800x480-->
        <splash src="platforms/android/res/drawable-land-xhdpi/splash.9.png" density="land-xhdpi"/><!--1280x720-->
    </platform>
    <platform name="ios">
        <allow-intent href="itms:*" />
        <allow-intent href="itms-apps:*" />
    </platform>
    <preference name="SplashScreenDelay" value="10000" />
</widget>
3.config.xmlの設定を各プラットフォームに反映する

・ターミナルから以下のコマンドを入力します。

cordova prepare -d

ここでAndroidディレクトリにあるconfig.xml(hello/platforms/android/res/xml/config.xml)を開いてみると、スプラッシュスクリーンの情報が追加されています。

<?xml version='1.0' encoding='utf-8'?>
<widget id="com.example.hello" version="1.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
    <preference name="loglevel" value="DEBUG" />
    <feature name="Whitelist">
        <param name="android-package" value="org.apache.cordova.whitelist.WhitelistPlugin" />
        <param name="onload" value="true" />
    </feature>
    <feature name="SplashScreen">
        <param name="android-package" value="org.apache.cordova.splashscreen.SplashScreen" />
        <param name="onload" value="true" />
    </feature>
    <allow-intent href="market:*" />
    <splash density="port-ldpi" src="platforms/android/res/drawable-port-ldpi/splash.9.png" />
    <splash density="port-mdpi" src="platforms/android/res/drawable-port-mdpi/splash.9.png" />
    <splash density="port-hdpi" src="platforms/android/res/drawable-port-hdpi/splash.9.png" />
    <splash density="port-xhdpi" src="platforms/android/res/drawable-port-xhdpi/splash.9.png" />
    <splash density="land-ldpi" src="platforms/android/res/drawable-land-ldpi/splash.9.png" />
    <splash density="land-mdpi" src="platforms/android/res/drawable-land-mdpi/splash.9.png" />
    <splash density="land-hdpi" src="platforms/android/res/drawable-land-hdpi/splash.9.png" />
    <splash density="land-xhdpi" src="platforms/android/res/drawable-land-xhdpi/splash.9.png" />
    <name>HelloWorld</name>
    <description>
        A sample Apache Cordova application that responds to the deviceready event.
    </description>
    <author email="dev@cordova.apache.org" href="http://cordova.io">
        Apache Cordova Team
    </author>
    <content src="index.html" />
    <access origin="*" />
    <allow-intent href="http://*/*" />
    <allow-intent href="https://*/*" />
    <allow-intent href="tel:*" />
    <allow-intent href="sms:*" />
    <allow-intent href="mailto:*" />
    <allow-intent href="geo:*" />
    <preference name="SplashScreenDelay" value="10000" />
</widget>
4.Android実機又はエミュレータでアプリを起動する

。ターミナルから以下のコマンドを入力します(ココでは実機で起動します)。

cordova run android

これでスプラッシュスクリーンが表示されました。Cordovaの情報は多いですが、バージョンによる違いもあるので、必ず公式のドキュメントに当たった方がよさそうです。

Cordovaサイトの右上にどのバージョンの情報かが表示されているのでチェック。
Cordovaサイトの右上にどのバージョンの情報かが表示されているのでチェック。

【参考】
アイコンとスプラッシュ画面 – Apache Cordova(6.0.0)
Cordovaめも: スプラッシュスクリーン表示

【Automator】SafariからURLをaタグ付きでコピーする

【OSX 10.11.3】
ここのところブログ書いていて「リンク貼るの面倒だなー」と思ってました。

具体的には例えばこの記事のページを開いていたら・・・

<a href="https://c-geru.com/as_blind_side/2016/02/cordova01.html" target="_blank">【Cordova】Cordova を使ってみよう(1)環境設定編 | AS blind side</a>

・・・といった感じで、カンタンにURLをタイトル付きのaタグに変換してくれないものかと。

で、そんなことをtwitterでつぶやいていたら「AppleScript使えばいいじゃん」とアドバイスをいただいたので、メモしておきます。

【参考】鳶嶋工房 / AppleScript / 入門 / AppleScriptの使い方

どうやって登録しようかなと探していたら、Automatorだとサービスとして登録できるらしいので、Automatorを使ってみることにしました。

【参考】Automatorを使ってみよう – entacl Lab.

以下、実際の手順です。

1.アプリケーション>Automator.appを起動
2.ファイル>新規を選択
3.サービスを選択

スクリーンショット 2016-02-03 1.16.55

4.左側からライブラリ>AppleScriptを実行 を右側へドラッグ&ドロップ
5.AppleScriptを実行 の中にスクリプトを記述。

実はAppleScript使ったことないので(笑)、スクリプト自体はほぼ教えてもらったままです。リンクは別ウィンドウで開きたかったので、そこだけ変更しました。

on run {input, parameters}
	tell document of front window of application "Safari" to set the clipboard to "<a href=\"" & URL & "\" target=\"_blank\"" & ">" & name & "</a>"
end run
6.”サービス”は、次の項目を受け取ります を「入力なし」、検索対象:「Safari.app」に設定。
スクリーンショット 2016-02-03 1.17.16
7.名前をつけて保存(ここでは「URLをaタグ付きでコピー」としました)

これでSafari>サービス から「URLをaタグ付きでコピー」が使えるようになりました。

ここではサービス環境設定でショートカットを割り当てています(option+C)
ここではサービス環境設定でショートカットを割り当てています(option+C)

使う上での注意点をひとつ。サービスの実行中はメニューバーにギアアイコンが表示されています。これが消えて初めてサービスが終わったことになるので、途中でブラウザのタブを切り替えてしまうと、別のURLがコピーされてしまいます。最新のマシンなら気にすることはないかもしれないですが、ウチの環境では何度か「アレ?何で違うページがコピーされてるの?」ということがあったので、念のため。

サービス実行中を示すギアアイコン(左端)
サービス実行中を示すギアアイコン(左端)

もっとAppleScript覚えれば、いろいろ自動化できそうです。

【Cordova】Cordova を使ってみよう(1)環境設定編

先日のCreateJS勉強会で話題に上ったCordova。とりあえず使ってみようということで、環境設定して、コンパイルできるとことまでやってみたので、その作業メモです。ターミナルを使い慣れていないので、主にその周辺についてです。

Cordovaとは何か?

Adobeの Phone Gap という、HTML5+CSS3で作ったコンテンツをパッケージ化してiOS/Android用アプリにするという技術が、オープンソース化されて Cordova と呼ばれています。詳しくは下記で。

【参考】HTML5ハイブリッドアプリ開発を支えるOSS「Cordova」はなぜアツいのか?PhoneGapとの違いは何か? – ふろしき.js

作業環境

・OSX 10.11.3
・Node.js v4.2.6
・nam 3.5.3
・Cordova 6.0.0
・Xcode 7.2
・Android Stuido 1.3

環境設定

下記のサイトを参考にしました。
【参考】Cordovaを用いた開発環境を構築する – Build Insider

以下、環境構築する際に引っかかった点などをまとめておきます。

【Node.jsのインストール】

私の場合は導入済みでした。その時の手順などはこちらを参照。

【cordovaのコマンドラインツールをインストール】

このインストールがなかなか終わらなくて、npmのバージョンが古いのかとアップデートかけたら、npm自体が消えてしまいました。原因はよくわからず・・・。調べてみたら同じ現象について書いてある記事を見つけて、この通りにnpmの再インストールをして復活しました。
【参考】[node.js]npm自体のアップデートしようとしたらなぜかコマンドが消えた… – もじれつとがめん

その後、cordovaのインストールは無事終了。

【Android SDKに含まれているディレクトリにパスを通す】

「以下のように環境に応じてパスを設定してください」と書いてあるけど、どうすればいいかわからず(笑)。
で、次の手順で設定します。

1.Android Stuidoを起動し、「Android Stuido」>「Preferences…」を選択。
2.Preferencesウィンドウの右側で「Appearance & Behavior」>「System Settings」>「Android SDK」を選択すると、「Android SDK Location」蘭にパスが表示されます。

ココでのパスは「」
この環境でのパスは「/Users/c_geru/Library/Android/sdk」

Android SDKのパスをFinderで確認すると、SDKの中に「tools」「platform-tools」のディレクトリが確認出来ます。

ああ
選択されているのが「tools」「platform-tools」ライブラリは不可視ファイルなので、Finderで確認するには不可視ファイルの可視化が必要。

3.パスがわかったので、2つのディレクトリにパスを通します。ターミナルから下記のコマンドを1つずつ入力してreturnキーを押します。「echo 」以降がコマンドです。正しく受け付けられると、入力可能(c-gerus-MBP2011:/ c_geru$ が表示され、カーソルが点滅している)な状態になります。

※「c-gerus-MBP2011:/ c_geru$」の部分は、当然ながら環境によって異なります。

c-gerus-MBP2011:/ c_geru$ echo "export PATH=\$PATH:/Users/c_geru/Library/Android/sdk/tools" >> ~/.bash_profile
c-gerus-MBP2011:/ c_geru$ echo "export PATH=\$PATH:/Users/c_geru/Library/Android/sdk/platform-tools" >> ~/.bash_profile

パスの設定について詳しくは下記を参照。今回行ったのは.bash_profileというファイルにコマンドライン上からファイルにテキストを挿入する方法です。
【参考】[Mac, Linux] PATHを通す方法 | Memo on the Web

【プロジェクトを作成する】

参考サイト通りにコマンド打ったら、次のようなエラーが出ました。

c-gerus-MBP2011:/ c_geru$ cordova create hello com.example.hello HelloWorld -d
Creating a new cordova project.
Copying assets."
Error: EACCES: permission denied, mkdir '/hello'
    at Error (native)
    at Object.fs.mkdirSync (fs.js:794:18)
    at /usr/local/lib/node_modules/cordova/node_modules/cordova-lib/src/cordova/create.js:284:16
    at _fulfilled (/usr/local/lib/node_modules/cordova/node_modules/q/q.js:787:54)
    at self.promiseDispatch.done (/usr/local/lib/node_modules/cordova/node_modules/q/q.js:816:30)
    at Promise.promise.promiseDispatch (/usr/local/lib/node_modules/cordova/node_modules/q/q.js:749:13)
    at /usr/local/lib/node_modules/cordova/node_modules/q/q.js:557:44
    at flush (/usr/local/lib/node_modules/cordova/node_modules/q/q.js:108:17)
    at nextTickCallbackWith0Args (node.js:419:9)
    at process._tickCallback (node.js:348:13)

ターミナルがデフォルトの状態では、ルート(通常なら Macintosh HD 直下)に位置しているため、ディレクトリを作成する権限がないためです。この場合は、スーパーユーザーを示す「sudo」を冒頭につけて、下記のように実行します。

c-gerus-MBP2011:/ c_geru$ sudo cordova create hello com.example.hello HelloWorld -d

※この際パスワード入力を求められます。ログイン時のパスワードを使用します。
【参考】必ず使える!Macのターミナルで使う基本UNIXコマンド15選 | NEZU.log

大体は作業用にディレクトリを作って、そこにまとめることが多いと思うので、今回はユーザディレクトリ配下の特定のディレクトリを指定して(/Users/c_geru/works/_2tone_dev/_cordova/hello)そこにプロジェクトを作成することにしました。

c-gerus-MBP2011:/ c_geru$ cordova create /Users/c_geru/works/_2tone_dev/_cordova/hello com.example.hello HelloWorld -d
プロジェクトの対象プラットフォームを確認する

参考サイトとは若干表示が違いました。この辺はバージョンによる差違かも。

c-gerus-MBP2011:hello c_geru$ cordova platform ls
Installed platforms: android 5.1.0, ios 4.0.1
Available platforms: amazon-fireos, blackberry10, browser, firefoxos, osx, webos
プロジェクトにAndroidとiOS用のファイルを追加する

cordovaコマンドは作ったプロジェクトのルートで行う必要があるので、追加する前にディレクトリを変更します。

c-gerus-MBP2011:/ c_geru$ cd /Users/c_geru/works/_2tone_dev/_cordova/hello
Androidエミュレータを利用する

問題なく起動しましたが、すごく時間かかりました。この辺はマシンスペックの問題かも。
(MacBook Pro (15-inch, Early 2011) 2GHz intel Core i7 メモリ 8GB)

iOSシミュレータを利用する

参考サイトでは、ios-simをインストールするように指示されていますが、直接エミュレータを起動して問題なかったです。Xcodeがインストール済であれば必要ないのかな?

ブラウザで確認する

「パソコンのブラウザで表示されたアドレスにアクセスすると、指定したプラットフォーム向けのWebアプリを見ることができます。」と書かれているけど、実際に「http://localhost:8000/」にアクセスするとメニュー画面が表示され、そこから各プラットフォームを選択することになるようです。

http://localhost:8000/ にアクセスした様子。対応しているプラットフォームのみリンクがついている。
http://localhost:8000/ にアクセスした様子。対応しているプラットフォームのみリンクがついている。
プラットフォームのリンクをクリックするとコンテンツが表示される。
プラットフォームのリンクをクリックするとコンテンツが表示される。iOSのリンクをクリックした様子。

これで環境設定と、エミュレータ、実機、ブラウザでの確認ができました。次は具体的な中身を作ってみてから。

【CreateJS】CreateJS勉強会(第7回)私的まとめ

2016/1/22(金)CreateJS勉強会(第7回)に行ってきました。その個人的まとめです。

※以下、敬称略です。

セッション内容

【セッション1】Single Page ApplicationにおけるPreloadJSの活用事例

(リクルートマーケティングパートナーズ 山田 直樹

・「キャッシュ済のファイルは読み込まないようにする」について、「ブラウザのメモリ上限に対するキャッシュの扱い(古いものから消す等)」について質問。「現状ではコンテンツ数が少ないので考慮していない」とのこと。
・PreloadJS は 0.6.1 を使用。最新版(0.6.2)だと、queue.getResult().srcから抜き出したBlobオブジェクトのパスが使えない(画像が読み込めない)ため。
【セッション2】事例から見るCreateJSの使いみち

(世路庵 沖 良矢
※レジュメなし(クライアント情報を含むため非公表)

・CreateJSのメリット
 各要素(動画除く)を1つの APIで制御できる。
 ブラウザ間の挙動を吸収してくれる
・CreateJSのデメリット
 画面描画は、Flashは部分更新なのに対し、CreateJSは全画面更新になる為、負荷が高い。
【セッション3】EaselJS 0.8.2の改訂項目とgskinner labの作例「Arc Rainbow」

野中文雄

※「Arc Rainbow」についての、野中さんによる更なる解説記事
 ・ FN1512002 | Graphicsコマンドでトゥイーンアニメーションを描く | HTML5 : テクニカルノートFN1512001 | 設定のオン・オフを切り替える - トグルボタンの論理組み立て | HTML5 : テクニカルノートFN1601001 | 条件分岐を考える | HTML5 : テクニカルノート
【セッション4】CreateJSで開発するクロスプラットフォームなアプリ開発〜ElectronとPhoneGapで広がる可能性〜

(ICS 鹿野 壮野原 のぞみ
・レジュメ(前編後編

・Webコンテンツアプリ化のメリット
 開発リソースの軽減
 アプリ化はカンタン(デスクトップ >> Electron, モバイル >> Cordova
・Webコンテンツアプリ化のデメリット
ネイティブ機能はプラグインで実装。プラグインが公開されているか、または自作。この辺は AIR for iOS/Androidに 対する ANE(Adobe Native Extension)と同じ印象。

関連リンク

CreateJS勉強会 (第7回) まとめ – Togetterまとめ

【Node.js】Node.jsを試してみた(基礎編)

【OSX 10.11.2 + Node.js v.4.2.4】
今更ながらですが、Node.js使ってみました。ターミナルやサーバ周りはあんまり得意ではないので、使ってみて「あれ?」となったところをまとめてみます。

参考にしたのはコチラのサイト。
Tech Blog | リクルートライフスタイル開発者ブログ Tag : ‘Node.js’

このサイトの記事を参考にテストしてみて、つまずいた点をメモとして以下に記します。

Node.jsで5行Webサーバを書いてみよう〈Node.jsシリーズ vol.1〉

手順通り公式サイトからパッケージをダウンロードしてインストールします。今回ダウンロードした時点でのバージョンは、v.4.2.4でした。で、インストールが終了すると、この画面が表示されます。

インストール完了時の画面。ここにインストール先のパスが書かれています。
インストール完了時の画面。ここにNode.js,namのインストール先とパスが書かれています。

記事には説明がないのですが、/usr/local/bin があんたのパスだよと書いてあるので、ここにファイルを作っていくことにします。つまり「たった5行でWebサーバーが書ける」にあるサンプルスクリプトは、 webserver.js という名前で、/usr/local/bin/ に保存するということです。

※ルートパスで書かれているので、実際は Macintosh HD/usr/local/bin にあります。それからディレクトリ「usr」は不可視なので、この辺を参考に不可視ファイルを表示するように設定します。

で、「nodeコマンドでサーバーを起動してみましょう」って書いてあるんだけど、ターミナル使ったことないとココでハマります(笑)。

通常、ターミナルを起動すると、こんな感じになってるはずです。

c-gerus-MBP2011:/ c_geru$

※「c_geru」はユーザ名

つまり、起動時点ではユーザ直下にいるので、そのままnodeコマンドを叩くと・・・

c-gerus-MBP2011:/ c_geru$ $ node webserver.js
-bash: $: command not found

とコマンド(webserver.js)ないといわれてしまいます。

c-gerus-MBP2011:/ c_geru$ node /usr/local/bin/webserver.js

とルートパス指定で起動するか、

c-gerus-MBP2011:/ c_geru$ cd /usr/local/bin/
c-gerus-MBP2011:bin c_geru$ node webserver.js

と、ディレクトリを /usr/local/bin/ に切り替えた上で(1行目)、起動することになります。

ちなみにnodeコマンドのあとに1行空行で改行された状態が、サーバが起動している(nodeコマンドが受け付けられた)状態です。

さて、この最初に起動した webserver.js をどうやって終わらせるのか?「Control+C」で停止します(ブレークを送信/中止・キャンセル)。

c-gerus-MBP2011:bin c_geru$ node webserver.js
^C
c-gerus-MBP2011:bin c_geru$

ターミナルが起動前の状態になってカーソル点滅になり、入力可能状態に戻ります。

この辺りのターミナル用コマンドは、いくつも解説サイトがありますが、例えばこの辺を参考に。
[ Mac ] ターミナルコマンドのまとめ ( 多分 Linux でも使えるはず )

この辺りはターミナルに馴れていれば自明のことなんでしょうが、知らないと結構ハマります。

npm実践! モジュールをインストールしQRコードを生成しよう〈Node.jsシリーズ vol.2〉

「npmコマンドでのモジュールインストール」で、qrcode-console モジュールをローカルインストール/グローバルインストールのどちらでインストールするか書いてないので、ちょっとハマりました。

・ローカルインストール
コマンドを実行するパス直下のnode_modulesディレクトリにインストールします。つまりインストール先は「/usr/local/bin/node_modules」になります。

・グローバルインストール
同一環境内にあるすべてのコードからモジュールを使えるようにインストールします。この場合のインストール先は「/usr/local/lib/node_modules」になります。

私はグローバルインストールしたので、qrcode_sample.jsのサンプルコードがそのままでは動きません。グローバルにあるモジュールを参照するので、1行目のrequire文のパスを書き換えます。

var qrcode = require( '../lib/node_modules/qrcode-console' );

この記事の冒頭に「node_modulesというディレクトリ配下におかれたモジュールは、コアモジュールと同じようにパス記号を付けず呼び出すことができます。」と書いてあったので、グローバルインストールすればパスなしで使えるのかと思ったんですが、「ローカルインストールでnode_modulesというディレクトリ配下におかれたモジュールは、コアモジュールと同じようにパス記号を付けず呼び出すことができます。」ということのようです。

チャットを作りながら学ぶSocket.IO〈Node.jsシリーズ vol.4〉

「Socket.IOを使ってWebサーバーを立ち上げると、/socket.io/socket.io.jsというパスに、そのライブラリが自動的に生成されます。」と書かれていますが、起動してみてもファイルができません。バージョン変わって仕様が変更になったのかも?とファイルを探してみると、下記にありました。

・ローカルインストール
/usr/local/bin/node_modules/socket.io/node_modules/socket.io-client/socket.io.js

・グローバルインストール
/usr/local/lib/node_modules/socket.io/node_modules/socket.io-client/socket.io.js

で、このファイルをindex.htmlに指定してみたのですが、socket.io.js自体がエラー(Uncaught SyntaxError: Unexpected token “<“…)で動きません。。。

Socket.IOのダウンロードページをみたらサーバ上の参照パスが書かれていたので、これを使うことにして無事起動しました。

<script src="https://cdn.socket.io/socket.io-1.4.3.js"></script>

この時期では同一PC上で複数ブラウザを立ち上げているのですが、同一ローカルネットワーク上の別端末からアクセスする場合は、index.htmlに書かれているjsの「localhost」の部分を

var ioSocket = io.connect( "http://192.168.11.6:3000" );

のように、サーバを起動しているPCのIPアドレスを指定することでアクセス可能になります。

ちょっとした小技で効率UP——アプリケーションをデーモン化〈Node.jsシリーズ vol.7〉

foreverを試そうとしてインストールするも、何度やってもエラーでインストールできず。。。

いろいろ試したところ、npm configを下記のように書き換えることでやっとインストールができました。

npm config set registry="http://registry.npmjs.org/"

【参考】【NODE.JS】NPMでFOREVERのインストールに失敗してしまう。。。

これでざっとNode.jsのテストが出来ました。今ひとつわかってない気がするので、間違い等ありましたら、ご指摘下さい。

【その他参考サイト】
・第1回 Node.jsとは:基礎から学ぶNode.js|gihyo.jp … 技術評論社
・node.jsのrequire相対パスうざい問題 – Quita
・SwiftでSocket.io (nodes利用) – Quita
・Socket.IO入門 (全10回) – プログラミングならドットインストール
・How do I check the version of socket.io and update it – Stack Overflow
・Node.jsとSocket.IOによるPCとスマホブラウザのペアリングデモ – ICS MEDIA
・5分くらいで出来るnode.js(0.6) + socket.io(0.8x)のサンプルプログラム – 大人になったら肺呼吸
・Mac OS X から Node.js をアンインストールする方法
・【Node.js】足りないモジュールをたったの一行でインストールするコマンド – Quita

【IoT】Wi-Fiモジュール ESP8266 を使ってみた

最近、いろんなところで話題になっているWi-Fiモジュール ESP8266。技適も取得していて、しかも数百円で入手可能。ということで、放置しっぱなしの電子工作のリハビリも兼ねてやってみました。

いくつかある記事の中で、機材的に一番ハードルが低そうなこちらを参考にしました。

プログラミング不要でiPhoneからLEDをオン・オフするIoTを作る(ESP8266使用) – stocker.jp

【テスト環境】
・Arduino IDE 1.6.7
・OSX 10.11.2

基本的な方法は、上の記事を参考にしてもらうとして、異なる点や補足をメモしておきます。

1.FTDI USBシリアル変換アダプター は同じものが手に入らなかったので、同じく5V/3.3Vで使用できるこちらを使いました。
FT232HL ハイスピードUSBシリアル変換モジュール

2. FTDIのチップをPCで使うにはドライバが必要だそうで、こちらを参考にOSX用のドライバを入手、インストールしました。
VCPドライバのインストール(mac編) | スイッチサイエンス マガジン

3.使っているUSBシリアル変換モジュールが違うので、USBシリアル変換アダプターと ESP-WROOM-02接続の仕方がちょっと違います。

・(USBシリアル)GND >> (ESP-WROOM-02)GND
・(USBシリアル)VIO >> (ESP-WROOM-02)3V3
・(USBシリアル)AD1 >> (ESP-WROOM-02)TXD
・(USBシリアル)AD0 >> (ESP-WROOM-02)RXD

USBシリアル変換アダプターと ESP-WROOM-02 を繋いだ様子
USBシリアル変換アダプターと ESP-WROOM-02 を繋いだ様子

4.上記2.でFTDIのドライバをインストールした後、上記1.のUSBシリアル変換モジュールを単体でつなぐと、Arduino IDEにシリアルポートが表示されるのだけれど、ESP8266を繋いだ状態でUSBに繋ぐとシリアルポートが表示されませんでした。

原因はよくわからず・・・。とりあえず上記1.のUSBシリアル変換モジュール側の電源部分(VIOとGND)のジャンパーコードを外すとシリアルポートが認識されるので、その状態で認識後にジャンパーコードを差し込んで、ソースコードを書き込むことで動作しました。

※下記ブログにOSX 10.9 の場合は、apple製のFIDIチップ用ドライバがよくないようなことが書かれていますが、OSX 10.11だし・・。
Arduinoトラブルシューティング アップロード編: 構想100年

またYosemite(Mavericks)だと、AppleFTDIドライバを無効にする方法もあるようです。
MacOSX – Yosemite(Mavericks)でFTDIが動かない件 – Qiita

同じ現象が出た方、解決法などあれば教えてください。

【Xcode】Apple Watch用アプリのテスト(2)- 親子間(iPhone、Apple Watch)の通信

【Xcode7.2 + MacOX10.11.2 + watchOS 2】
前回に引き続き、Apple Watch用アプリを試してみました。今回は親子間(iPhone、Apple Watch)の通信について。実機がないのでSimulatorで確認。

同じ方の書いたこの記事を参考にしました。

Apple Watch アプリから親アプリの情報を更新する。 – Apple Watch アプリプログラミング

ただこのままだとエラーが出て、コンパイルが通りません。watchOS 2では、ここで通信に使っている WKInterfaceController.openParentApplication() というメソッドが使えないようです。

ios – ‘openParentApplication(_:reply:)’ has been explicitly marked unavailable here – Xcode 7 Beta – Stack Overflow

そこで調べてみたら、この記事で解説されていました。

[Apple Watch] Watch Connectivity: sendMessage 即座にメッセージを送るには

準備は、こんな感じになります。

・WatchConnectivity を import する。
・WCSessionDelegate を設定する。
・WCSession のサポートの有無をチェックする(WCSession.isSupported())。
・WCSession がサポートされているときには WCSession を初期化(WCSession.defaultSession())して、delegateを設定し、activeにする(activateSession())。

後は、送信・受信用のメソッドをWCSession 用に書き換えてやればOKです。

・送信:– sendMessage:replyHandler:errorHandler:
・受信:– session:didReceiveMessage:replyHandler:

ちょっと気になったのは、Simulatorでのテストでは、iPhone >> Watch への送信は即時に受け取れるんですが、Watch >> iPhone への送信は、10秒ほどのタイムラグが出ました。これがSimulator のみの問題なのか、Apple Watch の仕様なのかは、実機がないので確認出来ていません。

【その他参考リンク】
WCSession Class Reference – iOS Developer Library
WCSessionDelegate Protocol Reference – iOS Developer Library
iOS – watchOS 2 の Watch Connectivity を使ってみた – Qiita
[watchOS 2][iOS 9] Watch Connectivity で情報をやりとりする様々な方法 | Developers.IO

AS,Objective-C,Javascript,その他諸々の備忘録