2013-05-23

今更canvas使った描画やってみた


昔から画面に描画する系の事をやってみたかったので、ちょうど良かったからcanvas使って色々書いてみたよ。

hello world

その1

ハートのドット絵を根性で描いてみた。それを1コマ1コマ横と縦にずらしてアニメーションさせてる。
アニメーションさせるときは、setIntervalとか使うコードを良く見たけど、あとで出てくる最適化の話の通り、requestAnimationFrameと使ってみてる。




その2

それを画像として書きだして表示してみた。次に続く。




その3

画像をくるっと回してぴよんっと止めてみた。なんで画像かというと、Rectで矩形描いてきっちり並べたハートをそのまま回そうとしたら、斜めになった時隙間が空いちゃって、キレイなハートじゃなくなってしまったから。
後はプリレンダリング的な最適化処理にもなって良いらしい。




その4

回したり縮小〜拡大してみた!
回すのは画像座標の左上からぐるぐる回ってしまうので、座標を毎回中心で回るようにずらす必要がある。詳しくはソースコードを見てみてください!なるほどって感じ。




arcを使ったartっぽい描画やってみた

tumblrで似たようなGIFアニメ見つけて、試しに作ってみたら結構それっぽく動いた!jsdo.itのhot codeとかにもあがってちょっと嬉しかったよ(*´ω`*)



ただまぁすごく重かったわけです。描画中はしばらく見てるとPCのファンが回りだしてしまったり、iPhoneとかで見るとホッカイロとして活用できるようになります。

で、HTML5 canvas のパフォーマンスの改善という記事を見つけ、これを見ながら頑張ってパフォーマンス改善してみました…!!

改善その1

まぁつまりは動かない背景までアニメ書いてたら大変てのと同じで、動いてない背景まで毎回書き出してたわけです。
それをcanvasタグを2つおいて、position: absoluteで重ねる事でcanvasのレイヤー化をやってみました。



これだけでかなりパフォーマンスは改善したのですが、まだなんか出来そう。
そして次です。


改善その2

次は、描画する指定座標に浮動小数点を使うを重くなるっていうのを直してみました。
ぐるぐる回る点は、単純にMath.cos, Math.sinで指定した座標なのでお構いなしに浮動小数点を使いまくっています。
なので、座標指定するところを

(浮動小数点座標 + 0.5) | 0

というビット演算を使って丸めてみました。あとから仕組みを調べたら頭の良い人は世の中に沢山いるんだなぁという感じでした。恩恵に預かります。。

で、直したのがこれ。



小数点を丸めちゃったらなんかガクガクしちゃったりしないかなーと思ったのですが、人間はそんなに目が良くなかったみたいで見た目も問題ありませんでした。
そして全然ファンが唸らないww


まとめ

色々描画すんのめっちゃたのしい!
最適化とかも、このあとしばらくやってみていて、教えてもらったLUTみたいな前処理をいれてみたり(ブラウザ落ちたw)、var sin = Math.sinみたいに参照が軽くなるみたいな細かい事をやってみたりしていました。

今回、円弧を描くようなアニメーションをさせるときに、sin, cosとかθとか数学でやったわーっていうのを久々に思い出して、それを扱えてるのがなんだか楽しかったです。

最近おすすめされたBeyond InteractionっていうOpenFrameworksの本を読んでるんですが、canvasではないが、これには図形の描き方の初歩から書いてあるので結構勉強になる。

何を目指してるんじゃwwって感じですが、まぁ現状は趣味程度に色々作って遊んでみますね^^


2013-05-11

「UPを使い始めてから、女の子にモテ始めたし、宝くじもあたるしウハウハですよ」渋谷系Webエンジニア 27歳


UP by Jawboneを買って2週間くらい経ったので感想とかよく聞かれるのでブログに書いてみますね。タイトルは心無い友だちが考えてくれました。

UPってなんなの?

手首につけて日々の活動や睡眠時間を管理したりできるライフログガジェット。防水性なのでそのままシャワー浴びれます。
詳しい説明とかはappbankさんの記事見るといいかも。
Jawbone UP: 手首に装着するだけ! iPhoneアプリで健康管理できる注目のアクセサリー!!

なんで買ったの?


似たようなのにFuelbandfitbitがあります。
Fuelbandはカッコイイし、Nike+も使ってランニングしてるので良いなーと思ってましたが、時計を2つつけることになってしまったり、バッテリーの持ちがそんなに良くないぽい。あと睡眠状態が取れなかったり。
fitbitはあんまり周りに使ってる人がいないからわからないのだけど、ガジェットがクリップ式なので、付け替えたりめんどくさそう?よくわかりません^q^

それに比べれば(おしゃれかどうかはおいておいて)アクセサリーとして手首に付けられるし、風呂でも外すことなく使えるので、24時間、バッテリーも持つ10日間ずっとつけっぱなしでいられます。
UPはライフログ系のガジェットとしてつけっぱなしにできるってのが手間がなくて良いかなぁという印象。少しでもめんどくさいと途中でやめちゃいそう。

どんな使い方してるの?

1日の目標に向かって活動していく


UPの初期設定では、1日の活動目標が決められています。大体おすすめの6時間睡眠と10000歩を目標にしておけば十分ぽいのでそのまま使ってます。
真ん中の"Did you know?"には、過去の自分のログを元にUPのアプリが睡眠時間や活動についてアドバイスをくれたり、警告してくれたりします。(現在は英語のみ)

とある平日の日中の活動記録

一日の歩いた歩数や運動の記録を残してくれます。記録は結構正確で、下記URLのグラフでは朝の通勤、ランチタイム、帰ってからのランニングなどがグラフ化されています。
https://jawbone.com/up/activity/moves/BXM3Lg0tIY3HR3_W57NZAQ

・ストップウォッチモード

ランニングやジムでのウェイトトレーニングではストップウォッチモードを使って、正しく活動時間を区切って、後からアプリでどんな運動をしたか設定できたりします。ちゃんと運動したってログをつけると、ただ歩いた時より目標達成しやすいかも。

・アイドルアラート

普段デスクに座ってる時に1時間とか設定した時間動かないでいると「ご主人!動いたほうがいいですぜ!」っていうアラートで運動を促してくれます。
集中してる時に、だんだんパフォーマンスが下がるのを防げたりして、個人的には好きな機能。

とある平日の睡眠記録

寝る前にUPについてるボタンを長押しすると睡眠モードに代わり、それから寝れば記録が開始されます。(あとから手動でも入れられる)
下記リンクのグラフではちゃんと6時くらいに起きたのに2度寝に突入、UPに設定してあった目覚ましで起きて、モードを切り替えずに横になりながらアニメを見ていたことがわかります。
https://jawbone.com/up/activity/sleeps/BXM3Lg0tIY2OSx7HV78x9w

目覚まし機能が結構良くて、深い眠りと浅い眠りを記録してくれている中でも、ちゃんと浅い眠りの時にバイブレーションで起こしてくれるので心なしか気持よく起きれます。

・パワーナップモード

もう一つ、パワーナップ(昼寝)モードってのがあって、まだ会社で使ったことは無いんですが決まった時間内でほんとにちょうどよい時間まで寝かせてくれるので重宝しそうです。(最大睡眠時間の設定もできる)


API連動でもっとself-hack!


最近UPがAPIを公開したので、ランニング情報を記録できるRunKeeperやアプリ連動した体重計のWithingsなどと連携できるようになりました。

個人的に熱いのはWithingsとIFTTTで、Withingsは毎日の活動にプラスして、体重と体脂肪がUP上に記録されていくのは比較しやすくてすごく良いと思ってます。(もうすぐ届く)
IFTTTは10000歩歩いたらtwitterに投稿したり、Evernoteに記録してほげほげしたり、レストランにfoursquareでチェックインしたら食事した記録をとってくれたり…APIを直接使わずともいろいろできそうなワクワクサービスです。


まとめ

最近身体を鍛えるのが趣味なんですが、UPを使ってさらにそれが助長された感じです。
一日のふとした時にUPをアプリに同期させて(ここまで書いてないけどイヤホンジャックをiPhoneに刺すだけで同期できる!)、「やべ、今日あんまり動いてねーな。筋トレするか。」とか、睡眠時間を見れるので「最近ちゃんと寝れてないし、今日はもう寝ようかしら」とか思えるようになったのは実はすげーいいことだなと感じております。

買うときの注意点はサイズを間違えると悲しくなりそうなので、ちゃんと調べてから買うのをおすすめします。
この記事を参考にするといいかも。ただ、買ったばかりの時はちょっと締め付けられる感じがしますが、つけてると少しゆるくなっていくので少しくらいきつくても時期に慣れると思います。

買ったのはこちらです。
色は汚れると嫌だから黒で、手首めっちゃ細いのでSサイズ。Withingsは新しくなってWS-30て型番でbluetooth対応したらしいのでそっちを買ったお。

2013-05-08

JavaScript環境性能比較してみた - indexOf と RegExp の速度比較 (2013/05/08版) +α

















JavaScript初めたばかりで、やっと正規表現に出会ったので速度比較とかやってみたく色々調べてたら下記サイト様を見つけました。大変参考になりました!ありがとうございます。

indexOf と RegExp の速度比較

これが2010/03/30の記事でしたので、サクッと2013/05/08版をやってみた次第でございます。二番煎じ企画。乙!!

ベンチマーク

ベンチマーク用のhtmlベタ書きのJavaScriptソースはこんな感じで実装されています。ボタン押すだけ。

今回はChromeと同じV8で動いているNode.jsでも試してみたのでそちらのソースはこんな感じ。


結果

PCブラウザ+Node.js

グラフの番号は 
(1)indexOf : str.indexOf('item:9999')
(2)静的な正規表現 : /item:9999/.exec(str)
(3)動的生成の正規表現 : new RegExp('item:9999').exec(str)
(4)正規表現 : /item:9999$/.exec(str)
となっています。

Figure 1. PCブラウザとNode.jsの正規表現性能比較

Chromeェ…すげぇ…。4に関しては1msとかでした。
マジか…。

おまけ:iOSでの比較


Figure 2. iPhone標準ブラウザとアプリ内ブラウザの正規表現性能比較

こちらはちょっとおまけで調べたiPhoneでの性能比較。
アプリ内ブラウザにはChromeのiOS版を使ったんですが、Chromeって名前なだけなんですね。。というかAppleのネイティブにブラウザ埋め込んだアプリ締め出しの裏構図が見えてコワイ。。。


まとめ

Node.jsでの性能が知りたかっただけなんですが、色々やったら色々わかって面白かったです。
NodeはChromeと同じくらいのパフォーマンスがでるというのがわかったので、カリカリに作る必要がなければどんなやり方でも行けそうですね。
ただ、$つかった時みたいに明らかな正規表現をするときは速度に差が出るみたいなので、適時パフォーマンス見るのが良さそうです。

iPhoneの結果は面白いくらいアプリ内ブラウザ開発やる気見えなくてコワイですね。
ブラウザアプリラップしただけのネイティブアプリが、一時期締め出し食らったりしてるみたいですし、不便さが勝ってみんな撤退しろー…なんてことを考えてるんですかね?
くわばらくわばら。

Androidは貸してもらえなかったのでまた今度出来ればやります。

えっIE…?おや、誰か来たみたいなのでこの辺で。

2013-05-07

Node.js (express)で使うConnectみたいに使えるミドルウェアをつくる (UserAgent編)



express使ってて、Connectに代表されるbodyParser, session, cookiePerser, compress, errorHandlerみたいな、全ルート処理に対するfilterみたいな実装がしたくてメモ。
具体的に言うとuserAgent判別とか。

※あくまでやり方のメモ!実際の実装ではもっとちゃんとuseragent判定等を書く必要があります。

Connectって?


connect
https://github.com/senchalabs/connect

上記に書いたようなhttpServerの機能をexpressに提供してくれてるライブラリという認識。ひと通りnode.js入門してからgithub読めば大体分かる。readmeにMiddlewareに各種機能とその説明、ソースがある。

※参考
http://d.hatena.ne.jp/hokaccha/20110719/1311053590
hokaccha氏の読んでみた記事



何したいの?

express入門でおまじないのように書いてるapp.configure()内のapp.use()で使えるミドルウェアを自作します。



実装

使い方と作り方。使う方は適当です。

使う方


ミドルウェア(userAgent.js)


実際の処理はreturn function(req, res, next)辺りから始まって、next()を実行することで次のapp.use()のルート処理にexpressが引き継いでくれてる。

適当すぎて申し訳ないのだけど、ここではiPhone以外のUserAgentが来た時は302にstatusを変えてヘッダ変更後、next()しないでres.end()することでredirectしました。