Adobe Capture CCで紙に描いた絵をパスに変換してみた

【Adobe Capture CC 2.0 + Illustrator CC 2015 + iPhone SE + MacOSX 10.11.5】
タイトル通りですが、ちょうどアドビサイトのチュートリアルを見つけたので、試してみました。

ロゴを手軽に! 紙に描いたイラストでロゴをつくろう! | Adobe Illustrator CC チュートリアル

細かい手順は上のリンクを見ていただくとして、ざっくりの流れと気づいた点などを書いておきます。

まず、Adobe Capture CCをダウンロードします。

今回は、先日某アイドルを描いた落書きがあったので、それを使用します。

某アイドルの落書き
某アイドルの落書き

Adobe Capture CCのキャプチャ画面の様子。きちんと線だけを認識してます。カメラを真上に置くことで発生する影には影響されないようです(この写真だと認識(緑の線)が弱いので、キャプチャ前にスライダーで調整)。

IMG_2249

シェイプ編集画面では、消しゴムを使って不要な線を削除。ピンチも出来るけど、線のないところなどを選んでやらないと、消しゴムとご認識されて意図しないところが消えてしまうことも。右下はandoではなくて戻すボタンのようで、押すと編集自体が初期化されました。

IMG_2250

で、Illustratorを立ち上げてみたものの、ライブラリには何も表示されず・・・。いろいろ見たところ、デスクトップのCreate Cloudアプリからファイル>同期を開始を押すことで、ライブラリに表示されるようになりました(表示されるまでタイムラグあり)。

※この辺は初めて使うので、別に方法があったりするのかしらん?

デスクトップのCreate Cloudアプリで、ファイルの同期を開始する。
デスクトップのCreate Cloudアプリで、ファイルの同期を開始する。
Illustratorのライブラリウィンドウに表示された様子(画面右下)
Illustratorのライブラリウィンドウに表示された様子(画面右下)

あとはIllustratorでの作業なので特に問題はありませんが、とりあえず参考ページに従ってテキストなど入れて余分なパスを多少調整したりしてできたのがこちら。

完成品
完成品

パスデータは「線ではなくシェイプ」で作成されるので、この元絵のように手描きでくっついている部分は1つのパスになってしまいます。なので、人物の塗りを分けるためにはさみ/ナイフツールでパスを分割しています。

結構サクッと使えていい感じですが、iPhoneとMac(PC)を往復するのが面倒かなという気も。Adobe Capture CC自体は、写真を撮るだけでなくライブラリの写真も使えるようなので、この機能自体をPhotoshopかIllustratorに組み込んでもらえる(または単機能のアプリ)とより便利かなと思います。

【参考】
[Illustrator]はさみツールの使い方 | バンフートレーニングスクール スタッフ ブログ
[Illustrator]ナイフの使い方 | バンフートレーニングスクール スタッフ ブログ

【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