近況0714

今しがた映像のやつの作業が一周した。安堵。と言ってもプールのやつもあったりで依然としてやばいけど。

この年になってようやく全体に手を回しながら進めるようになってきた。やっぱり作業が収束するのが早い。予備校時代(5, 6年前)、手のデッサンで他の部分を放置して延々爪描いてた頃からちょっとは進歩したかも。

作業のスピードが上がる→詰めの作業に注げる時間ができる→クオリティが上がるっていう構図を体感したのが社会人一年目の記憶。

この前昼飯食べてる時に、ケイタさんに頭いい人ってどういう人ですか?って聞いたら「仕事早い人」ってすごい早さで返ってきた。ナルホドーと。

自分としてはコード仕事は書く時間を減らして、考える時間を増やしたい。デザイン仕事は考える時間を減らして、手を動かす時間を増やしたい。

そろそろ家につくので公開ボタンを

ポチッと。

近況0710

なんてめんどくさいんだ。毎週書くことさえできない。

先々週あたり、仕事中(※営業時間外)にコンビニがてらフラッと観に行ったアフターアースがクソつまんなかったけど、いい息抜きになって良かった。

昨日は初めて一からやる映像仕事で、構成と選曲とエフェクトの提案。構成はやり直し、選曲とエフェクトはOKとのこと。時間なくてやばい。

なんか他にもいろいろあったけどそんな感じ。

Require.jsを試してみた

Require.jsはActionScriptのimportのようにjsファイル同士の依存関係を崩さないよう非同期で読み込みつつ、多重読み込みなども防止してくれるライブラリ。
Require.jsを使えば細かくjsファイルを分割してもBackboneやjQuery等のライブラリを依存関係を保ちつつ読み込んでみる。

最小限のコードで挙動を確認してみる。(以降すべてCoffeeScript
これを実行するとMyModelのmessageに定義された「Hello, World!」が出力される。
Backboneに必要なUnderscoreとjQueryはBackboneより先に読み込まれている。

require([
	"libs/jquery-1.10.1.min"
	"libs/underscore.min"
	"libs/backbone.min"
],
($, _, Backbone) ->
	MyModel = Backbone.Model.extend({
		message: "Hello, World!"
	})

	MyView = Backbone.View.extend({
		initialize: (options) ->
			console.log @model.message
	})

	view = new MyView({
		model: new MyModel()
	})
	@
)

今度はRequire.jsの機能のdefineを使ってモジュールを作ってみる。
こちらも同じく「Hello, World!」が出力される。

define("myModule",
[
	"libs/jquery-1.10.1.min"
	"libs/underscore.min"
	"libs/backbone.min"
],
($, _, Backbone) ->
	MyModel = Backbone.Model.extend({
		message: "Hello, World!"
	})

	MyView = Backbone.View.extend({
		initialize: (options) ->
			console.log @model.message
	})

	return {
		modelClass: MyModel
		viewClass: MyView
	}
)

require([
	"myModule"
],
(module) ->
	model = new module.modelClass()
	view = new module.viewClass({
		"model": model
	})
	@
)

require.configのshimでライブラリの依存関係をあらかじめ設定してみる。
実行結果は同様。

require.config(
	shim:
		"libs/backbone.min":
			deps: [
				"libs/jquery-1.10.1.min"
				"libs/underscore.min"
			]
			exports:
				"Backbone"
)

define("myModule",
[
	"libs/backbone.min"
],
(Backbone) ->
	MyModel = Backbone.Model.extend({
		message: "Hello, World!"
	})

	MyView = Backbone.View.extend({
		initialize: (options) ->
			console.log @model.message
	})

	return {
		modelClass: MyModel
		viewClass: MyView
	}
)

require([
	"myModule"
],
(module) ->
	model = new module.modelClass()
	view = new module.viewClass({
		"model": model
	})
	@
)

今度はrequire.configのpathsを使ってライブラリのパスをあらかじめ定義しておく。
こちらも実行結果は同様。

require.config(
	paths:
		"jquery": "libs/jquery-1.10.1.min"
		"underscore": "libs/underscore.min"
		"backbone": "libs/backbone.min"
)

define("myModule",
[
	"jquery"
	"underscore"
	"backbone"
],
() ->
	MyModel = Backbone.Model.extend({
		message: "Hello, World!"
	})

	MyView = Backbone.View.extend({
		initialize: (options) ->
			console.log @model.message
	})

	return {
		modelClass: MyModel
		viewClass: MyView
	}
)

require([
	"myModule"
],
(module) ->
	model = new module.modelClass()
	view = new module.viewClass({
		"model": model
	})
	@
)

今度はshimにもpathsで定義したパスを使ってみる。

require.config(
	paths:
		"jquery": "libs/jquery-1.10.1.min"
		"underscore": "libs/underscore.min"
		"backbone": "libs/backbone.min"

	shim:
		"backbone":
			deps: [
				"jquery"
				"underscore"
			]
			exports:
				"Backbone"
)

define("myModule",
[
	"backbone"
],
() ->
	MyModel = Backbone.Model.extend({
		message: "Hello, World!"
	})

	MyView = Backbone.View.extend({
		initialize: (options) ->
			console.log @model.message
	})

	return {
		modelClass: MyModel
		viewClass: MyView
	}
)

require([
	"myModule"
],
(module) ->
	model = new module.modelClass()
	view = new module.viewClass({
		"model": model
	})
	@
)

require.configでの設定は一度きりなのでこれを無視すると、メインのコードはだいぶスッキリした。

参考:
RequireJS moduleについて – 文殊堂
java-ja.js #2 RequireJS実践編 – 文殊堂
[JS] JavaScriptをモジュール分割して開発できるRequireJSに入門 – YoheiM .NET

Grunt導入してみた

MacにはCodeKitっていうCoffeeScriptとかSassとかLessとかをコンパイルしてくれる便利なツールがあって最近までお世話になってた。でも自分はWindowsユーザーで、これだけのためにMacを起動するのも面倒くさいので、CodeKitでやってたことをWindowsでもできるようにとGruntをはじめてみた。

Gruntそのものはコンパイラではなく、いろんなタスクを実行してくれるだけのツールなんだけど、プラグインを追加することでCoffeeScriptのコンパイルや、Sass/Lessのコンパイル、Uglifyを使ってjsのminifyなどができるようになる。

これを使ってCodeKitでやってたことを再現してみた。

1. インストール

まずGruntを実行するのに必要なnode.jsをインストール。同時にnpm(node.js用のパッケージ管理ツール)もインストールされる。

環境変数PATHに「C:\Users\{ユーザー名}\AppData\Roaming\npm;C:\Program Files\nodejs\」を追加しておく。

gruntをインストール

npm install -g grunt-cli

※「npm install -g grunt」ではない

環境変数PATHに「grunt」を追加しておく。

参考:
Windows 環境変数 Path の設定方法 – コンピュータ/ソフトウェア関連Tips
はじめに | Grunt 日本語リファレンス | js STUDIO

2. プロジェクトの準備

プロジェクトのルートフォルダにGruntfile.js(もしくはGruntfile.coffee)と、package.jsonというファイルを作る。
Gruntfile.js(Gruntfile.coffee)はGruntに実行させるタスクを定義しておくファイル。package.jsonはプロジェクトに必要なGruntのプラグインのリスト。

3. package.json

package.jsonはこのように記述して、devDependenciesに必要なプラグイン(パッケージ)の名前とバージョンを羅列しておく。

{
  "name": "{プロジェクト名}",
  "version": "{パッケージのバージョン}",
  "author": "{作者}",
  "devDependencies": {
    "grunt": "~0.4.1",
    "grunt-contrib-livereload": ">=0.0.0",
    "grunt-contrib-watch": ">=0.0.0",
    "grunt-contrib-coffee": ">=0.0.0",
    "grunt-contrib-uglify": ">=0.0.0",
    "grunt-contrib-jshint": ">=0.0.0",
    "grunt-contrib-jst": ">=0.0.0",
    "grunt-contrib-sass": ">=0.0.0",
    "grunt-contrib-compass": ">=0.0.0",
    "grunt-contrib-cssmin": ">=0.0.0"
  }
}

package.jsonを用意した状態で「npm install」をコマンドプロンプト上で実行すると、devDependenciesに書かれたプラグインを順番にプロジェクトフォルダ直下のnode_modulesフォルダにダウンロードしてきてくれる。

npm install

と書かれた.batファイルを作っておくと良い。

参考:
npm-json(1) — Specifics of npm’s package.json handling
npm と package.json でパッケージ管理 | FIRN.JP
npmとpackage.json使い方 – Kokudoriing

4. Gruntfile.js

下記のようなラッパー関数を用意し、その中にタスクを書いていく。Gruntfile.jsの内容はGruntを通してnode.js上で実行されるので、js(もしくはCoffee Script)で記述していく。

module.exports = function(grunt)
{
  //ここにGruntに実行させたいタスクを書いていく
};

coffeeファイルが入ったフォルダを監視してcoffeeファイルが更新されたらCoffeeScriptをコンパイルして、uglifyでminifyするGruntfile.coffee。

module.exports = (grunt) ->

    # load tasks
    grunt.loadNpmTasks "grunt-contrib-coffee"
    grunt.loadNpmTasks "grunt-contrib-uglify"
    grunt.loadNpmTasks "grunt-contrib-watch"

    grunt.initConfig(

        coffee:
            files:
                expand: true
                cwd: "assets/coffee/"
                src: ["**/**/*.coffee"]
                dest: "assets/js/"
                ext: ".js"

        uglify:
            files:
                expand: true
                cwd: "assets/js/"
                src: ["*.js"]
                dest: "assets/js/"
                ext: ".min.js"
            options: ""

        watch:
            coffee:
                files: ["assets/coffee/**/*.coffee"]
                tasks: [
                    "coffee"
                    "uglify"
                ]
	)

    grunt.registerTask "default", ["watch"]

sassファイルが入ったフォルダを監視してsassファイルが更新されたらSassをコンパイルして、sprite画像も生成する。

module.exports = (grunt) ->

    # load tasks
    grunt.loadNpmTasks "grunt-contrib-compass"
    grunt.loadNpmTasks "grunt-contrib-cssmin"
    grunt.loadNpmTasks "grunt-contrib-watch"

    grunt.initConfig(

        compass:
            dist:
                options:
                    environment: "development"
                    outputStyle: "compressed"
                    debugInfo: true
                    relativeAssets: true
                    basePath: "assets"
                    sassDir: "sass"
                    cssDir: "css"
                    generatedImagesDir: "images"

        cssmin:
            files:
                expand: true
                cwd: "assets/css"
                src: ["*.css", "!*.min.css"]
                dest: "assets/css/"
                ext: ".min.css"

        watch:
            sass:
                files: ["assets/sass/**/*.sass"]
                tasks: [
                    "compass"
                    "cssmin"
                ]
	)

    grunt.registerTask "default", ["watch"]

これらをまとめつつ、JavaScriptテンプレートのコンパイル、htmlの更新監視にコンパイル後にLiveReloadを使ってブラウザをリロードするタスクを加えるとこうなる。

module.exports = (grunt) ->

    # load tasks
    grunt.loadNpmTasks "grunt-contrib-compass"
    grunt.loadNpmTasks "grunt-contrib-cssmin"
    grunt.loadNpmTasks "grunt-contrib-coffee"
    grunt.loadNpmTasks "grunt-contrib-uglify"
    grunt.loadNpmTasks "grunt-contrib-jst"
    grunt.loadNpmTasks "grunt-contrib-watch"

    grunt.initConfig(
        compass:
            dist:
                options:
                    environment: "development"
                    outputStyle: "compressed"
                    debugInfo: true
                    relativeAssets: true
                    basePath: "assets"
                    sassDir: "sass"
                    cssDir: "css"
                    generatedImagesDir: "images"
        cssmin:
            files:
                expand: true
                cwd: "assets/css"
                src: ["*.css", "!*.min.css"]
                dest: "assets/css/"
                ext: ".min.css"
        coffee:
            files:
                expand: true
                cwd: "assets/coffee/"
                src: ["**/**/*.coffee"]
                dest: "assets/js/"
                ext: ".js"
            options:
                sourceMap: true
        jst:
            compile:
                options:
                    processName: (filename) ->
                        return filename.match(/assets\/jst\/(.*).js$/)[1]
                files:
                    "assets/js/templates.js": ["assets/jst/**/**/*.js"]
        uglify:
            files:
                expand: true
                cwd: "assets/js/"
                src: ["*.js"]
                dest: "assets/js/"
                ext: ".min.js"
            options: ""
        watch:
            html:
                files: ["**/*.html"]
                options:
                    livereload: true
            coffee:
                files: ["assets/coffee/**/*.coffee"]
                tasks: [
                    "start"
                    "coffee"
                    "uglify"
                ]
                options:
                    livereload: true
            jst:
                files: ["assets/jst/**/*.js"]
                tasks: [
                    "jst"
                    "uglify"
                ]
                options:
                    livereload: true
            sass:
                files: ["assets/sass/**/*.sass"]
                tasks: [
                    "start"
                    "compass"
                    "cssmin"
                ]
                options:
                    livereload: true
    )

    # register tasks
    grunt.registerTask "start", "start task", ->
        grunt.log.writeln "--------------------------------------------------------"
        grunt.log.writeln "    start task"
        grunt.log.writeln "--------------------------------------------------------"

    grunt.registerTask "default", ["watch"]

それぞれのタスクの設定はそれぞれのプラグインのページを参照のこと。

参考:
grunt-contrib-coffee
grunt-contrib-jst
grunt-contrib-uglify
grunt-contrib-compass
grunt-contrib-cssmin
grunt-contrib-watch

ExternalInterface.callが重い

Flashから毎フレームExternalInterface.callでJSの関数を呼び出したりしている時に、そのJSの関数内でなにかしらのObjectをreturnしてるとその処理に手間がかかるのか、Flashのフレームレートがすごい落ちる。

CoffeeScriptで関数の最後に@を入れてるとこの現象が起こりやすいので、ExternalInterface.callで直接呼び出される関数の最後はreturn falseして回避しておく。

さらにそのJSの関数内でDOMの操作みたいなちょっと重めの処理(width, height変えたり、left, top変えたり)をしてたりしても同様の現象が起こる。この場合はJSの関数内でやっている処理をsetTimeout(Function, 0)でくるんで非同期で処理してあげると回避できた。

なんだろこれ?ExternalInterface.callで呼び出した処理が終わるのをFlashが待っちゃうからかな?

追記1:
こういうことらしい

追記2:
CoffeeScriptで行末returnしないようにするには「return」だけ書いとけばいいっぽい。

近況0604

書き終わった瞬間の風景
前回から毎週日記書こうと思ったのにいきなり頓挫してしまった。今回は日常の隙をついて、会社帰りに歩きながらiPhoneで書いてみる。アプリで書いてるのでリンク貼るとかハイパーテキストっぽいことはめんどくさいので割愛。

先週末、先々週末は撮影のサポート。一日中撮影ポイントを探しつつ都内をウロウロ。座り仕事で体が錆びついてるせいか毎夜毎夜全身筋肉痛。

両親が結婚30周年で来京。宿泊先の帝国ホテルのスウィートがすごかった。

torne+nasneがいい感じ。torneは全ユーザーの視聴データや、録画予約のデータをもとに、各番組にミルネとトルネという独自のスコアをつけている。試しにこのスコアの高い番組をいろいろ録画してみた。このIT化を機にまたテレビを見る気が湧いてきた。

去年の年末ぐらいに、社長から引き継いだコードを読んでて、モーションプログラムのコツみたいなのに気づいた瞬間があった。それを意識しだしてからなんとなく自分がイメージしたようにオブジェクトが動いてくれるようになってきた。コツと言ってもただ単にモノを動かす時に、x、yじゃなくて距離と角度を操作するってだけの話なんだけど。

そんな感じ。

近況0519

月曜は先週シコシコやってたサイトのデザインの提案。すんなり通ってよかった。安堵。

火曜~金曜はFlash仕事。

あと金曜は先々週までやってたEspace Louis Vuittonの新しいやつ公開。今回はわりと時間があったのでこれでもかってぐらいFlashの最適化に勤しめてよかった。途中で試したStarlingがさほど高速じゃなかったのは意外だった。

そのあと仕事終わりで大輪さんと勅使河原さんと新宿で飲んだ。
お金の話とか勅使河原さんの近況とか。例のプロフィールがまだまだ長くなりそうな話とか息子さんの話とかいろいろ聞けて楽しかった。お店も不思議な空間でいて飯もおいしくてよかった。

あと最近は移動中にナニワ金融道を読んでる。結構古い作品だけど今までスルーしてたのを後悔。超面白い。それと進撃の巨人のこのまとめ見てたらいろいろ気になってきたので復習のためにアニメ見てる。

そんな感じ。

AfterEffects ショートカットメモ

今年の1、2月あたりにガンガン編集してたのにさっきAfterEffects立ち上げたらまったく手が動かなくて泣いた。すぐ取り戻せるようによく使うやつをメモ。

タイムラインの移動

1フレーム進む:Ctrl+→
1フレーム戻る:Ctrl+←
10フレーム進む:Ctrl+Shift+→
10フレーム戻る:Ctrl+Shift+←
タイムラインの先頭に移動: Ctlr+Alt+←
タイムラインの終端に移動: Ctlr+Alt+→
特定の時間に移動: Alt+Shift+J

次のキーフレームに移動:K
前のキーフレームに移動:J

レイヤーのインポイントに移動:i
レイヤーのアウトポイントに移動:O
選択したレイヤーのインポイントを現在の時間に移動:[
選択したレイヤーのアウトポイントを現在の時間に移動:]

中央、端にスナップ:Ctrl+Shift+ドラッグ

レイヤーの順序

選択したレイヤーの順序を上に移動: Ctrl+Alt+↑
選択したレイヤーの順序を下に移動: Ctrl+Alt+↓
選択したレイヤーの順序を最前面に移動: Ctrl+Alt+]
選択したレイヤーの順序を最背面に移動: Ctrl+Alt+[

トリミング

レイヤーのインポイントをトリム: Alt+[
レイヤーのアウトポイントをトリム: Alt+]
レイヤーの分割: Ctrl+Shift+D

ワークエリアの始端を現在時間にセット:B
ワークエリアの終端を現在時間にセット:N

タイムラインを拡大:^
タイムラインを縮小:-
タイムライン最大拡大/最小縮小の切り替え:;

特定プロパティのみを表示

アニメーションを含むプロパティのみを表示:U
位置プロパティのみを表示:P
スケールプロパティのみを表示:S
アンカーポイントプロパティのみを表示:A
角度プロパティのみを表示:R
不透明度プロパティのみを表示:T
マスクプロパティのみを表示:M
エクスプレッションのみを表示: EE

レンダリング & プレビュー

レンダーキューに入れる:Ctrl+Shift+/
音つきでプレビュー: Ctrl+ドラッグ
音だけ再生: .(テンキー)

その他

コンポジション設定: Ctrl+K
アクティブなパネルを全画面化:@
エクスプレッションの適用: Alt+タイムウォッチをクリック
新規平面:Ctrl+Y

2012年よかったランキング – ムービー編

すでに2013年も1/4が終わろうというさなか、超主観で2012年に出会ったものをランキングで振り返ってみるテスト3本目、ムービー編。

#10 16mm Phantasmagoria (2001-2010) on Vimeo

個人的に、表現における表面的な質感というものを懐疑的に捉えているところがあるんだけど、この作品のフィルムの質感を見て少し許せるようになった。あと、ちょうど夏ごろに行ったカンボジアの思い出ともあいまって少しノスタルジックな気分にもなったり。

#9 Krizovatka – Love – YouTube

人の善意がひたすら連鎖していくという映像の構造もさることながら、その善意の総体が織りなす「人間っていいよね」的な幸福感にも似た気持ちよさがある。

#8 Isaac's Live Lip-Dub Proposal – YouTube

ありがちな素人が撮ったプロポーズ動画と思いきや、いろいろと手が込んでいて感心した。
大きなところでは、鑑賞者を車で運ぶことで背景が動かし続け、パフォーマンスの単調さをうまく解消してる。こういうことをやろうとすると、まずは背景側をなんとか動かそうと考えそうなものだけど、逆転の発想的に鑑賞者を動かしてしまえってところが新しい。
細かいところで言うと、ダンスのウマいお姉ちゃんに目立つ色の赤い服を着させてフォーカスを奪うことで、素人の中途半端なクオリティのダンスをなんとなくゴマかしてるあたり結構手が込んでるなぁと思いました。

#7 TextureWorld – YouTube

「動き」のみで「形」を表現する方法。目から鱗が落ちた。

#6 完成版 ニュ~東京音頭 NEW TOKYO ONDO – YouTube

手描きアニメーションでは手間のかかる空間的なカメラワークや、高フレームレートによって密度のあるスピード感を感じる。作品解説にもある通り、デジタルツールのみでストイックにモーションを作るこんでいるらしく、察するにデビッド・オライリーにインスパイアされていそう。
(デビッド・オライリーのThe External Worldと、Please Say Somethingも名作なのでぜひ)

#5 MOVE on Vimeo

表現方法としてはわりとありがちながら、構成とテーマが素晴らしく、この手の作品の代表格的なポジションを築いた感がある。

#4 Robot readable world on Vimeo

画像解析によってコンピューターが見ている世界をビジュアライズした映像を集めた作品。なによりも映像にオーバーラップされる、コンピューターが知覚した情報の無機質な痕跡がグラフィカルでカッコイイ。

#3 Japan tron dance – YouTube

擬似的に姿を消したり、現したりする事で空間を自由に移動しているように見せている。またその応用によってマンガの様な時間軸を無視したアニメーションを作っている。
昨今の技術の進歩によりコンパクトな装置で電飾をリモートで操作できるようになったことで可能になった表現手法かと。

#2 High Five FAIL Compilation 2011 – YouTube

ハイタッチをしようと構えた人がスルーされてしまう様子をひたすら集めた作品。ひとつひとつのシチュエーションから漂ってくるほんのりとした哀愁が徐々に増幅して笑いのしきい値を超えてくる。

#1 「HAPPY BOGEYS」クリハラタカシ – YouTube

ひたすら奇怪な形状の生物が画面を横切っていくだけのアニメーションなのだけれども、その形状に最適化された動きがとても気持ちいい。

算数メモ

毎度公式をググるのはいい加減めんどいのでここにまとめてく。
(これらを覚えられるほどの知能はない)

距離と角度からx、y方向の距離を求める

var dx:Number = Math.cos(degree * Math.PI / 180 ) * distance;
var dy:Number = Math.sin(degree * Math.PI / 180 ) * distance;

03bc502b-41cb-426a-8cea-d28c2a500107

2点間の角度

var radian:Number = Math.atan2(targetY - currentY, targetX - currentX);
var degree:Number = radian * 180 / Math.PI;

8fc882bd-ba74-4651-b7c0-2edf61e9d023

2点間の距離

var dx:Number = targetX - currentX;
var dy:Number = targetY - currentY;
var distance:Number = Math.sqrt(dx * dx + dy * dy);

bcaf9577-e04f-46bd-ae87-3b5cb82087c1

角度からラジアン

var radian:Number =  degree * Math.PI / 180;

ラジアンから角度

var degree:Number = radian * 180 / Math.PI;

バネ運動

var vx:Number = ( currentX + ((targetX - currentX) * spring) * friction;
var vy:Number = ( currentY + ((targetY - currentY) * spring) * friction;
currentX += vx;
currentY += vy;