2012年8月20日月曜日

Javascript の オブジェクトの操作。

なんか別な事しようと思ってハマッたっつか、面白いから調べてみたよ。

var obj = {foo:"moge"};
var dat = obj;
obj.foo = "bar";

obj = "";
alert(dat.foo); // <- undefined とかを期待したのに、bar って出る。
alert(obj.foo); // <- こっちはundefined と出る。おいおい。


というわけで、こうしなきゃだめ。

var obj = {foo:"moge"};
var dat = obj;
obj.foo = "bar";

obj.foo = undefined;
alert(dat.foo); // <- undefined
alert(obj.foo); // <- undefined

なんか、当たり前のコードになった。
なんか、これ、腑に落ちないよねー。
それが出来るんなら、なんで最初のは undefined にならねーんだっつー話ですよ。
まぁいいか。つか、おかげでなんか今まで書いたコードでメモリ食う理由がわかった気もする。

あと、調べてわかったことは、 var obj ってしたら、 delete(obj) って出来ないということ。
グローバル変数じゃないと、delete 演算子は仕事をしないっつーことのようです。
基本らしいのだけど、基本を知りません。ワタクシ。Oh! No.
 http://nanto.asablo.jp/blog/2008/01/09/2552470#jsdel-target

ここを読むと良くわかりました。

【削除されない見本】
 var obj = {foo:"moge"};
 var dat = obj;
 obj.foo = "bar";

 delete(obj); // <- 削除されない
 alert(dat.foo); // <- bar
 alert(obj.foo); // <- bar

かーらーの、

【削除される見本】
 obj = {foo:"moge"};
 var dat = obj;
 obj.foo = "bar";

 delete(obj); // <- 削除される
 alert(dat.foo); // <- こっちは bar が出る。
 alert(obj.foo); // <-エラーになって alert が出ない。

Javascript の オブジェクトとかは参照渡し!とはいえ、
参照元のオブジェクト自体を削除しても、参照先のプロパティも削除されるわけではなく、
どっちかというと、ギリギリ前に参照していた内容がコピーされる、ということかなぁ?


2012年8月15日水曜日

BPMSync.js にレベルコントローラもつけましたの件。

これもつけないと不便だよなーと思ったので、
最小値、最高値、小節と音符範囲、コールバック関数を指定して、
レベルが変化していくような機能をBPMSync,jsにつけました。
なんか、メンバ変数があとで使いたくなるようなものにしてしまったので、
さらに機能を追加した時に困りそうでたまらないですねー。センスないわ。



デモではさっきのかえるの歌の文字をデカくしていってますが、
このレベルコントローラ単独でも使えますよ。

var hoge = BPMSync(150,16,[]);
   hoge.levelControl(0,127,[0,8],[1,15],function(val){/*do something*/});

みたいにすれば動くはずー。

最初は jQuery の animate と連動したら楽かなーとか、
animate をいじくりまわせばいいかなーとか思ったけど、
めんどくせーから書きました。
30分くらい?のお気楽コーディング。
でも、今回は怠けて、変な文字とか投げられたときの処理してなかったり、
数が減っていくような動きを要求された時にちゃんと動くか確かめなかったり、
まぁ、手抜きですけど、いいんですよ。そんなものは。
加算しか出来ないんだったら、コールバック関数の中でうまいことしてくださいよですよ。ええ。

あとなんかもう一個くらいないとこれ使い物にならねーなっつー機能があったので、
思い出したら追加します。
ここまで出掛かっているのに思い出せない感じ。

思いつきは、ちゃんとメモを取りましょう!

2012年8月14日火曜日

BPMと音符単位で同期させてなんかさせたい時にいい感じの BPMSync.js 作った。

というわけで、さっきの Movietime.js よりかは、
こっちのほうが使い道ありそうな感じがします。
似たようなのを前にどっかで見たんだけど、
失念してしまったので、さっきの勢いでバリバリと書いてみた。



なかなか表現が難しい?のだけど、
1フレームを8分音符と同じにするとか、16分音符と同じにするとかできると、
結構楽チンにかっこいいPV的なものが出来ますよ。

てか、書いたのは良いんだけど、
なんかこれ、 new BPMSync() で最後に渡す配列がイマイチだよね。
まぁ、これ、自分で改造してもらって、配列の中に Object 入れて、
そのオブジェクトによって内部的にさらに何かしらのメソッドゥーとか動かしていけば、
うまい事いくんじゃないかしら?

小節と音符を管理する都合上、配列で表現するとなると、二次元配列ぽくなるのは仕方ないかなぁ。
他になんかうまい方法ねーべかな。

これ、for文とかでぶん回したくなるんだけど、
なんかうまく動かない気がするので、for文じゃなくした。
なんか、this.measure とかせんでも、引数使いまわしてもよかったんだけど、
まぁ、そこら辺は、趣味?管理のしやすさ?クラスなのにメソッドに引数とか入れないのがベターなのかなー?とか、
なんか世間体とかいろいろ考えた結果こうしましたけど、
もっと綺麗にエレガントに素晴らしく出来る人は、Forkしてゴリゴリ修正してください。
むしろ全部作り直してくれてもOKです。

オホホホホ。

FPSとフレームを指定して、なんか動かす Movietime.js を作りました。

Timeline.js って名前にしようとしたら、同じような内容で、同じようなのがあったので笑った。

http://kjirou.net/main/public/js/lib/timeline/test/index.html

で、上記と何が違うかというと、
FPS(Frame Par Seconds) を指定して、
Flashみたいに、特定のフレームになったらなんかを表示するような事ができます。
ちなみに、ちゃんとFPSとか計ってないから、ずれたりしたらごめんね。

jsdoit にコードをアップしました。
なんか、前に作ったアカウントがどのOpenIDプロバイダで登録したかわからなくなったので、
仕方がないからpsychedesire1というアカウントを作ってやりました。

デモでは、指定したフレームが経過したら、
文字が太くなります。



test2 が二番目に来てるけど、500フレーム経過したら動いてねって指示をしているので、
一番最後に動きます。
そこら辺は、機能として、前回の経過フレームに加算する方法で動かすか、
それともそのままの経過フレームで動かすかを選べるようにしたほうが良いかなー。

そのままの経過フレームで動かすほうがよいメリットは、
コードを書き換えなくても、メソッドチェーンのケツにくっつければよいという点。

 hoge.next(0,func1).next(150,func2).next(200,func3);
 0フレーム目→150フレーム目→200フレーム目

となんか作ってて、100フレーム目にもアクション追加したいよ!
ってなった時に、普通にメソッドチェーンのケツに新しいアクションを追加すればよいだけ。

 hoge.next(0,func1).next(150,func2).next(200,func3).next(100,func4);
 0フレーム目→150フレーム目→200フレーム目→100フレーム目




前回の経過フレームに加算する方法だと、

 hoge.next(0,func1).next(150,func2).next(50,func3);
 0フレーム目→150フレーム目(150を指定)→200フレーム目(50を指定 200-150 = 50だから)

と作ってて、100フレーム目にもアクションを追加したいよ!
ってなった時に、

 hoge.next(0,func1).next(100,func4).next(50,func2).next(50,func3);
 0フレーム目→100フレーム目(100を指定)→150フレーム目(50を指定)→200フレーム目(50を指定)

って感じで、書き換えが頻繁になる気がする。
結構、動画を作る立場で考えるに、こういう計算作業は極力やりたくないものでござるので、
あまり経過フレーム加算のパターンを使うことは少ないかなーとか重いつつ。


でもまぁ、メインでフレーム数を管理する変数を用意すれば良いだけなので、
機能を追加するのは、たいした問題ではないのだけれども。
というわけで、早速直した。
Forkしたぜっ!イエイイエイ!



全部作っても一時間もかからなかったぜーい。
動画メインのFlasherもHTML5とかでなんかやる時に、使いやすいと思いますよ。
参考にしたブログ。

メソッドチェーンの作り方 - あと味
http://taiju.hatenablog.com/entry/20100307/1267962826

2012年8月8日水曜日

FizzBuzzってなんだよ。

FizzBuzzってなんぞやと思ったら、世界のナベアツみたいなやつだった。

http://ja.wikipedia.org/wiki/Fizz_Buzz

3で割り切れたら Fizz で、5で割り切れたら Buzz で、どっちでも割れたら FizzBuzz なんだとさ。
出来るだけ短くプログラムを書くのが楽しいらしい。

業務プログラマがFizzBuzz書いたらどうなるか
https://gist.github.com/3292173 

が面白かった。ガッチガチやぞっ!って感じ。

で、なんかとりあえず考えてみた。 Javascriptですけども。

var fizzbuzz = function(num){
    if(typeof(num) !== "number"){return "not a number";}
    if(num < 1){return "input 0 upper";}
    return (!(num % 15) ? "fizzbuzz" : (!(num % 3) ? "fizz" : (!(num % 5) ? "buzz" : num)));
};
 

for(var i = 0;i < 31;++ i){
    alert(fizzbuzz(i));
}


長ぇな。
最初の方の例外処理みたいなの無ければ

var fizzbuzz = function(num){
    return (!(num % 15) ? "fizzbuzz" : (!(num % 3) ? "fizz" : (!(num % 5) ? "buzz" : num)));
};

 
だけでおっけーだけど、 なんか、メンテナンスし辛いよなこれでは。

var fizzbuzz = function(num){
    if(typeof(num) !== "number"){return "not a number";}
    if(num < 1){return "input 0 upper";}
    var fizz = 3,buzz = 5;
    return (!(num % (fizz * buzz)) ? "fizzbuzz" : (!(num % fizz) ? "fizz" : (!(num % buzz) ? "buzz" : num)));
};


これで fizz と buzz の条件が変わってもOKだよねっ!
いやいや、それだったら、

var fizzbuzz = function(num,fizz,buzz){
    if(typeof(num) !== "number"){return "not a number";}
    if(num < 1){return "input 0 upper";}
    return (!(num % (fizz * buzz)) ? "fizzbuzz" : (!(num % fizz) ? "fizz" : (!(num % buzz) ? "buzz" : num)));
};

var fizz = 3,buzz = 5;
for(var i = 0;i < 31;++ i){
    alert(fizzbuzz(i,fizz,buzz));
}


こっちのほうがいいよなぁ。うん。
FizzBuzzっていうゲームなんだから、ルールは関数の外で変わるんだから、こっちのほうが正しい。

グローバルが汚くても良いんなら、

i=0;while(i<31){alert(!(i%15)?"fizzbuzz":!(i%3)?"fizz":!(i%5)?"buzz":i);++i;}

こんな感じじゃね?使いまわせねーし読み辛いけど。78文字くらい。
もっと短くなるんだろうなぁ。凡人はこんなレベルです。

phpでFizzBuzz最短56Byte
http://d.hatena.ne.jp/milieu/20100204/1265305089

PHPだけど、こっちのが短い。
なるほど、割り切れたらベースじゃないほうが結果として短くなるのか。

i=0;while(i<31){alert(i%15?i%5?i%3?i:"fizz":"buzz":"fizzbuzz");++i;}

これで 69文字か。

2012年7月31日火曜日

思いつき

ちょっと面白いアプリを思いついたので、作ってみることにする。
できるかなぁ?

2012年7月22日日曜日

javascript の 配列とかオブジェクトをコピーする

Clone Anything with JavaScript
http://davidwalsh.name/javascript-clone

難しそうだなーと思ったんだけど、テキトーにやってみた。
リンク先にコメントを書いたんだけど、改行とかがグチャグチャになった。
ごめんなさい外人さん。謝る英語がわかりません。
あと、なんか見たらコメント消えてたから、書き直したら二重に投稿された。
どうしよう。あわわわわわあわわわわわわ。

var clone = function(o){
    var Clone = function(o){
        var self = this;
        if(o instanceof Array){
            for(var i = 0,l = o.length;i < l;++ i){
                self[i] = o[i];
            }
        }else{
            for(var n in o){
                self[n] = o[n];
            }
        }
    };
    if((!o)||(typeof(o) !== "object")){
        return o;
    }else{
        o = new Clone(o);
        return o;
    }
};

/* 以下動きを検証している感じ */

var myObject = {hoge:"hogehoge"};
var cloned = clone(myObject);
alert("1 hogehoge と出て欲しい -> " + cloned.hoge);

myObject.hoge = "ohohohoho";
alert("2 hogehoge と出て欲しい -> " + cloned.hoge);
cloned.hoge = "ababababa";
alert("3 ababababa と出て欲しい -> " + cloned.hoge);

var next_clone = clone(myObject);
alert("4 ohohohoho と出て欲しい -> " + next_clone.hoge);
alert("5 ababababa と出て欲しい -> " + cloned.hoge);


var myArray = ["mogemoge","mugamuga","morimori"];
var array_clone = clone(myArray);
alert("6 mugamuga と出て欲しい -> " + array_clone[1]);
myArray[1] = "uhiuhi";
alert("7 mugamuga と出て欲しい -> " + array_clone[1]);

var deep = {obj:{hoge:"huga",func:function(){alert("do something");}}};
var deep_clone = clone(deep);
alert("8 huga と出て欲しい -> " + deep_clone.obj.hoge);
alert("9 次に do something と出て欲しい");
deep_clone.obj.func();

var myStr = "ho---ge";
var str_clone = clone(myStr);
alert("10 ho---ge と出て欲しい -> " + str_clone);
alert("11 ababababa と出て欲しい -> " + cloned.hoge);

別に

var Clone = function(o){
    if((!o)||typeof(o) !== "object"){return;}
    var self = this;
    if(o instanceof Array){
        for(var i = 0,l = o.length;i < l;++ i){
            self[i] = o[i];
        }
    }else{
        for(var n in o){
            self[n] = o[n];
        }
    }
};

var myObj  = {test:"huga"};
var cloned = new Clone(myObj);

でも動くことには動くと思うんだけど、
引数の o が object 以外だった時に、複製できない。

if((!o)||typeof(o) !== "object"){this = o;return;} // <- エラーになる

とか

if((!o)||typeof(o) !== "object"){return o;} // <- 意味なし

とか出来ないので、clone()の中で object かどうか判断してからーって感じです。

きっと、俺でも思いつくので、外国の凄い人は思いついた上で採用していないのだろう。
つまり、なんかしらこの方法だと問題あるんだろうなぁ。
そこがわからないので、俺は未熟なんだろうなぁとおもいます。

でも、とりあえず動くから良いよね!

2012年6月29日金曜日

放置してました。

放置していたというわけではなく、
Googleのログインを二段階プロセスにしたのは良いのだけど、
ログインコードが発行されるメールアドレスを携帯のメアドにしていて、
その携帯が解約されてしまったので、ログインできなかっただけでした。
うぉ~ん。最近めっきりプログラムを組んでいません。
嘘です。そうでもないです。

会社で使うのに適した顧客管理DBみたいなものを作ったのだけど、
まぁ、そんなものくれてやるほどの価値もねぇ会社だよなってところが落としどころでした。
プププププ。

ていうか、思いのほか、アクセス数が落ちなかったので驚いた。
これからもポチポチブログ書くかなー。

2012年3月1日木曜日

NAVERまとめのブックマークレットが何をしているのか見てみる #NAVERまとめ

特に意味はないですけど、勉強がてらに見てみます。
『コードリーディングとか出来ないぜ!頭皮から汁が出てくるぜ!』
と思ってしまうのですが、
ブックマークレットくらいからやるのが、俺くらいの技量の人間には丁度良いでしょう。

取りあえず綺麗にしてみる。

javascript:(function(){
    var d=document 
        ,w=window
        ,e=w.getSelection
        ,k=d.getSelection
        ,x=d.selection;
    try{
        s=(e?e():(k)?k():(x?x.createRange().text:''))
    }catch(e){
        s=''
    }
    var l=d.location
        ,e=encodeURIComponent
        ,d=decodeURIComponent
        ,g=function(s){
            try{
                d(s);return s
            }catch(e){
                return g(s.substr(0,s.length-1))
            }
        }
        ,f='http://matome.naver.jp/bml'
        ,p='?u='+e(l.href)+'&s='+e(s)
        ,u=g((f+p).substr(0,2500))
        ,a=function(){
            if(!w.open(u,'njMTMBookmarklet','links=0,scrollbars=0,toolbar=0,status=1,width=520,height=653'))l.href=u
        };
    (/Firefox/.test(navigator.userAgent))?setTimeout(a,0):a();
    void(0)
})();

というわけで、綺麗になったところで、見ていきます。
前半

    var d=document 
        ,w=window
        ,e=w.getSelection
        ,k=d.getSelection
        ,x=d.selection;
    try{
        s=(e?e():(k)?k():(x?x.createRange().text:''))
    }catch(e){
        s=''
    }


getSelection は、文字列が選択されているかを見るやつなので、
変数 s に e k x つまり、なんかかんか選択された要素があればそれを入れて、
それがなければ s を空の文字列にするよとしています。

後半

    var l=d.location
        ,e=encodeURIComponent
        ,d=decodeURIComponent
        ,g=function(s){
            try{
                d(s);return s
            }catch(e){
                return g(s.substr(0,s.length-1))
            }
        }
        ,f='http://matome.naver.jp/bml'
        ,p='?u='+e(l.href)+'&s='+e(s)
        ,u=g((f+p).substr(0,2500))
        ,a=function(){
            if(!w.open(u,'njMTMBookmarklet','links=0,scrollbars=0,toolbar=0,status=1,width=520,height=653'))l.href=u
        };


ブックマークレットを起動したら、ウィンドウが開く(またはページ転移する)わけですが、
そのウィンドウが開く先のURLを作っているところ。


encodeURIComponent とか decodeURIComponent とか名前が長いので、e とか d とか変数に置き換えて、
省略して書けるようになってますね。
d は 前半部分で document だったけど、ここにきたら上書きされてしまいます。
g っていうのが関数で、これは何をやってるのかというと、
放り込まれた文字列をデコードすることを試みます。
デコードできなければ文字列の長さを1個減らして(substring のところ)、もう一回自分自身にその文字列を放り込み、
デコードが出来るまでそれを繰り返しています。
で、その関数 g が出てくるのが次あたり。
変数 f はブックマークレット用のエンドポイントURL(っていうの?)、
変数 p は f のあとにくっつく文字列、つまり、ブックマークレットが開くURL (f + p) は、

 http://matome.nave.jp/bml?u= encodeURIComponent( 開いているページのURL ) &s= encodeURIComponent(前半で作った選択された文字列) 

になります。で、
変数 u で g が登場します。
ブラウザというのは、開けるURLの文字数が決まっているので、

 http://support.microsoft.com/kb/208427/ja
 http://www.connect-i.co.jp/tipsblog/?p=6

さっきの

 http://matome.nave.jp/bml?u= encodeURIComponent( 開いているページのURL ) &s= encodeURIComponent(前半で作った選択された文字列) 


こいつが、ブラウザの開けるURL文字数を超えているとマズいので、
g に 『 f + p して一端 2500 字でぶった切ったもの』 を投げて、
それが decodeURIComponent できるかどうか、URLとして成立するかをチェックし、
成立しなければ成立するまで文字数を減らしてから、変数 u に返します。

で、関数 a は、そんな変数 u を小窓で開ければ開いて、
ポップアップ禁止されてたりすれば、今開いてるページを、変数 u のアドレスに移動させます。

最後

    (/Firefox/.test(navigator.userAgent))?setTimeout(a,0):a();
    void(0)

ここがわからん。
ユーザエージェント、つまり今見ているブラウザが Firefox っぽかったら(ユーザエージェントを偽装することも出来るからね)、
何故かsetTimeoutで0秒待ってから、関数 a を実行してて、それ以外のブラウザは普通に関数 a を実行している。
この違いが良く分からないなぁ。なんざんしょ。Firefoxには特別な何かがあるのであろう。
調べるのめんどくさい。非同期ぽくしなきゃだめつーことですか?
ブックマークレットを書き換えてどうなるか実験君してみればいいんだけどねぇ。やらない。めんどいから。

そんな感じでした。嘘書いてたらごめんなさい。

開いたブックマークレットのウィンドウの中の

 http://static.naver.jp/matome_ver4/js/nj.matome.bookmarklet_xxxxxxxxxxxxxxx.js

これとかは、そのうち読んでみたいなーと思います。

久しぶりにブログ書いた。5000HIT超えました。
『上手くはないんだけどせっかくもらったしヘタとは言えないし飾らないわけにもいかない5000HITおめでとうトップ画像』
ネット友達から貰う感じだね。これは。

2012年2月24日金曜日

NAVERまとめ疲れ #NAVERまとめ

ないだろ?まだないだろ?
NAVERまとめ疲れって書いた人居ないだろ!
俺一番!俺いちばーーーん!いえーい!
あんまり疲れてません。
疲れたといえば、無駄に色んなGmailのアカウントの予備のメール扱いになってたので、
それらを整理整頓してました。それに疲れました。
プライバシーポリシーも変わるからさっ!エヘ!テヘペロ!
ついでに『NAVERまとめとはなんだったのか』 とか言ってやる!
ざまぁ!ざまぁ!アルファギーク()ざまぁ!

別にNAVERまとめに疲れてはいないけど、要望はありますね。
あ、NAVERまとめへの要望まとめを作ればいいのか。

NAVERのご意見ご要望の掲示板はあって、

http://uservoices.naver.jp/

ちゃんとスタッフの人が(同じような返事が多いが)返事してたりして、
amebaに比べたら100億倍マシだなぁとおもってみたりしています。でも、この公式の掲示板、どのサービス向けなのか、
ユーザが一目見てわからないから、そこらへん何とかして欲しいと思います。
その点、はてなのはてなアイデアってある種画期的ですよね。

http://i.hatena.ne.jp/

というわけで、NAVERまとめへの要望まとめを作ってみた。

http://matome.naver.jp/odai/2133004169489844101

既に同様のまとめがあったら、そっちを使うべきだと思う。
検索してない。エヘ!テヘペロ!
うちの4歳の娘までテヘペロテヘペロ言い出してます。流行ってますね。
そんな感じでした。

2012年2月17日金曜日

期待のJSゲームエンジン enchant.js でキーボードの入力だけ処理させる。

enchant.js 触ってみました。
参考にしたのがこちら。enchant.js でプログラム組む方法が良くわかる。

「enchant.js」でゲームを作ろう! HTML5とJavaScriptによるアクションゲーム制作入門


別に熊とかを動かしたいわけではなく、キーボードの入力だけを処理させたかったので、
そういうことをやってみます。
『キーボードの入力のためだけにenchant.js 使う必要なくない?』と言われそうですが、
まぁ、ものは試し。男は度胸。何でもためしてみるのさ。

最初に書いたのがこんな感じ。
なんとなく jQuery も使っています。

enchant();
$(document).ready(function(){
    var game = new Game(320,320);
        game.onload = function(){
            this.addEventListener("enterframe",function(){
                if(this.input.left) {alert("left") ;}
                if(this.input.right){alert("right");}
                if(this.input.up)   {alert("up")   ;}
                if(this.input.down) {alert("down") ;}
            });
        };
        game.start();
});

MACやスマホはわかりませんが、Windowsでキーボードの矢印キーを押すと、
アラートが出ました。
そこまではよかったものの、
アラートが出続ける…あらら。こまったので、F5キーを連打しました(笑)
で、書き直したのがこんな感じ。

enchant();
$(document).ready(function(){
    var game = new Game(320,320);
        game.onload = function(){
            this.addEventListener("enterframe",function(){
                if(this.input.left) {alert("left") ;this.input.left  = false;}
                if(this.input.right){alert("right");this.input.right = false;}
                if(this.input.up)   {alert("up")   ;this.input.up    = false;}
                if(this.input.down) {alert("down") ;this.input.down  = false;}
            });
        };
        game.start();
});

いちいち それぞれのフラグを false にしてやるわけですね。
これでアラート連発が無くなりました。

まぁ、ただそれだけです。

2012年2月16日木曜日

node.js + jsdom + jQuery で Gumroadで売った商品をブログに貼るブログパーツ作った

完璧に惰性。デザインのセンスなし。
うわーんうわーん。
このページのしたの方にはっつけてあります。
なーんか、iframeってどうなのよ?知らんがな。

なんか、NAVER まとめのブログパーツを no.de で動かしていたんだけど、
サーバが変ぽいので、herokuに変えた。
ついでに、それをイジって Gumroad のブログパーツもつくったった。

導入方法とかは、
Gumroadで売った商品をブログに貼るブログパーツ作った。
http://matome.naver.jp/odai/2132940047075673701

ここに書きました。
適当にやってください。

ソースとか、書かなきゃ駄目か?大したことしてないからいいだろー。てへぺろ。

2012年2月15日水曜日

Gumroadについて

Gumroad っていう、自分の作ったものを Twitter とかで手軽に売れるサービスが話題になってます。 

大体の流れとか、問題点とかは、
 
 個人コンテンツ販売の新時代を開くか 「Gumroad」で同人誌を売ってみる (1/3) - ITmedia ニュース 

ここを読んだらよくわかります。
NAVERまとめ も結構あります。

日本製の派生サービスの Ameroad っていうのもテストで始まってます。
ITメディアの紹介記事ね。
 
Gumroad は 海賊版とか売られたりしたらやばいよ!という記事が多いですね。 



 
 Gumroad の危険性について早めに警鐘を鳴らします 物語を語ろう&#12290;物語を創ろう&#12290;
 Gumroad の問題点についてもう少し掘り下げてみました&#12290; 物語を語ろう&#12290;物語を創ろう&#12290; 
 RMB: もしあなたの著作物が知らぬ間にGumroadで売られていたら

実際に Gumroad で曲を売ったけど、100%自作曲じゃなくて、
東方(?シューティングゲームだっけ?)の曲のアレンジだったからテンパッた人の話。
 
 話題のGumroadを使って楽曲を販売してみたAnitaSunの記録 - Togetter

昔iTunesで再生している曲タイトルを2ちゃんねるブラウザに送るアプリを作ってくれた fladdict さんが
なんか絡まれている様子のドキュメンタリ。
 
 なんでGumroadに苦言まとめエントリ書く人は『黒いことしてバレると人生ゲームオーバーヤバい』ってことを、誰も書かないの?イデオロギー的な理由とかなの? - Togetter
 
海賊版うんぬんについては、概ね、どうとも思わないというか、fladdictさんの言ってるとおりだなと思う。
お金にする為に Gumroad を使うという前提がある以上、お金にならないことはやらないだろうし。
『お金がかかるものをタダで皆で使おうぜ!』という行動とは違うからなぁ。 
ていうか、fladdict さんに至っては、自分の作ったiPhoneアプリが散々割られているような人なのに、
よく冷静に分析できるなーと思います。
 
mixi の日記でも書いたけど、
オンザクラウドでパーソナルなタレントがマネタイズされるのは素晴らしいよねぇ。手軽だし。
海外法人だからどうだこうだっつったってさー、Twitterだって日本法人できるまで使わなかったの?とか思うし。
Googleは?Yahooは?実際Googleは日本に法人あるけど、安全なの?って思う。

新しい手段が生まれることは素晴らしいと思うし、Gumroad を装うフィッシングサイトが怖いねーと思います。
機能やシステムより、その枠組みの外にある『人間の行動』が怖いわけだから。 
うまく言えないな。例えば、Gumroadの中に居れば安全、
Gumroad だと思って別なサイトに入った人のことはGumroadは守れない、
Gumroad は Gumroad に行きたい人を全て Gumroad に誘導出来ない、
Gumroad は Gumroad に似せたサイトへのアクセスを Gumroad に強制リダイレクト出来ない、という事か。
いずれにせよ、良くないサービスは廃れるだろうし、良くないサービスにならないようにサービスを運営する人は努力するだろうし、って思う。

あー。マネタイズってところで思い出したけど、
うちの嫁から聞いたんだけど、
アメブロを使っている奥様の間で、ヤフオクとかを使わないで、
アメブロの中だけで物の売り買いをしてるらしいよ。中古の子供服とか。
他のブログサービスだとそういうのは禁止されているらしいけど、
アメブロは禁止されていない(?)らしく、そういう売買の行動があるらしい。
当然物品のやりとりに必要な個人情報とか、口座番号は、
相手に開示したりするんだろうけど、そういうことに抵抗がないのはなんなんだろうな?と思う。


で、俺もGumroadで何か売ろうかなーという感じになってきたので、
カリフォルニア州の法律的に問題が無ければ、
アート作品として、ようじょのパンツ姿の写真を $10 で売ろうと思います。
この記事のはてなブックマークのコメントにうp!と書いた人が10人以上居たら通報販売します。

2012年2月14日火曜日

NAVERまとめのブログパーツを作った。

※2012/02/15 なんかサーバに繋がらなくなってるなぁ。なんでだろ。

公式を見ても、人気のまとめのブログパーツしかないみたいな感じだったので、
よく確認もしないで作った。
全然反省とかはしていない。
公式のものがあるなら、それを使ったほうがいいし、
公式のものがないなら、それが出来るまでの箸休めです。

動作は、このページの右側にあるやつを見て確認してください。
使い方やなんやらは、
http://matome.naver.jp/odai/2132921992271736701
からどうぞ。

最初は php でやろうかなーとか思ったんですが、
勉強をかねて、node.js でやりました。
node.js で jsdom + jQuery でスクレイピングしているので、
blogparts.no.de からのアクセスとかを 403  されたら使えなくなります。

jsdom + jQuery でのスクレイピングは、
過去に思いっきり自分用というか、当時の会社用で、
×××の○○○○○をごっそり抜き出すようなものを作ったことがあるのですが、
他の人がアクセスするようなものを作ったことが無かったので、
http で サーバを立てるところからお勉強でした。

NAVERのサーバにあるCSSを link rel したり png ファイル読み込もうとしたんですが、
うまくいかない感じだったので、
ソースに直で 長ったらしい CSS 書いたり、

こちら
[JavaScript] dataスキームURI生成(画像データのBase64変換)
で base64に画像変換してみたりしました。

取り合えず、動いたので良かったです。

あ、ソースコードはこんな感じです。インチキくさい。
修正すべき点とかご指摘いただけたらと思います。不慣れなもんで。フヒヒヒヒ。てへぺろ。

var http   = require("http"),
    url    = require("url"),
    qs     = require("querystring"),
    XHR    = require("xmlhttprequest").XMLHttpRequest;
    jsdom  = require("jsdom"),
    jq     = "http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js";
var style = function(){
    var str  = "";
        str += "*{font-size:10px;}";
        str += ".MdMTMTtlList01{margin-left:0;padding-left:0;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01Item,.MdMTMTtlList02 .mdMTMTtlList02Item,.MdMTMTtlList03 .mdMTMTtlList03Item{display:table;*display:inline;width:100%;}";
        str += ".MdMTMTtlList01{overflow:hidden;*zoom:1;margin-bottom:-15px;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01Item{margin:16px 0 0 0;padding:0 0 15px 0;border-bottom:1px solid #f2f2f2;margin-bottom:-1px;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01Item:first-child{margin-top:0;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01Thumb,.MdMTMTtlList02 .mdMTMTtlList02Thumb,.MdMTMTtlList03 .mdMTMTtlList03Thumb{display:table-cell;*display:inline;*zoom:1;width:60px;height:60px;padding:0 13px 0 0;vertical-align:middle;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01Thumb a,.MdMTMTtlList02 .mdMTMTtlList02Thumb a,.MdMTMTtlList03 .mdMTMTtlList03Thumb a{display:block;width:60px;height:60px;overflow:hidden;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01Txt,.MdMTMTtlList02 .mdMTMTtlList02Txt,.MdMTMTtlList03 .mdMTMTtlList03Txt{display:table-cell;*display:inline;*zoom:1;vertical-align:middle;word-wrap:break-word;table-layout:fixed;width:100%;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01Ttl,.MdMTMTtlList02 .mdMTMTtlList02Ttl,.MdMTMTtlList03 .mdMTMTtlList03Ttl{display:inline;font-size:10px;font-weight:bold;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01Ttl a:link,.MdMTMTtlList01 .mdMTMTtlList01Ttl a:visited,.MdMTMTtlList02 .mdMTMTtlList02Ttl a:link,.MdMTMTtlList02 .mdMTMTtlList02Ttl a:visited,.MdMTMTtlList03 .mdMTMTtlList03Ttl a:link,.MdMTMTtlList03 .mdMTMTtlList03Ttl a:visited{text-decoration:none;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01Ttl a:hover,.MdMTMTtlList01 .mdMTMTtlList01Ttl a:active,.MdMTMTtlList01 .mdMTMTtlList01Ttl a:focus,.MdMTMTtlList02 .mdMTMTtlList02Ttl a:hover,.MdMTMTtlList02 .mdMTMTtlList02Ttl a:active,.MdMTMTtlList02 .mdMTMTtlList02Ttl a:focus,.MdMTMTtlList03 .mdMTMTtlList03Ttl a:hover,.MdMTMTtlList03 .mdMTMTtlList03Ttl a:active,.MdMTMTtlList03 .mdMTMTtlList03Ttl a:focus{text-decoration:underline;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01Thumb+.mdMTMTtlList01Txt{width:593px;max-width:593px;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01Draft{color:#959595;font-size:10px;font-weight:bold;}";
        str += ".MdMTMTtlList01 .mdMTMTtlList01TimeStamp{color:#afafaf;font-size:10px;}";
        str += ".MdMTMTtlList01 .MdSocialCountList01{margin-top:2px;}";
        str += ".MdMTMTtlList01 .MdMsgDisp01{display:table-caption;margin-bottom:4px;}";
        str += ".MdSocialCountList01{margin-left:0;padding-left:0;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Li{display:inline-block;*display:inline;*zoom:1;margin-left:7px;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Li:first-child{margin-left:0;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Ico{display:inline-block;*display:inline;*zoom:1;overflow:hidden;margin:0;padding:0;border:none;background:url('data:image/png;base64,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') no-repeat 0 0;text-align:left;vertical-align:middle;text-indent:-9999px;*text-indent:0;*line-height:9999px;*word-wrap:normal;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Hatena .mdSocialCountList01Ico{width:12px;height:12px;margin-top:-4px;*margin-top:0;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Twitter .mdSocialCountList01Ico{width:12px;height:12px;margin-top:-4px;*margin-top:0;background-position:-15px 0;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Facebook .mdSocialCountList01Ico{width:12px;height:12px;margin-top:-4px;*margin-top:0;background-position:-30px 0;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Comment .mdSocialCountList01Ico{width:14px;height:13px;margin-top:-2px;*margin-top:0;background-position:-50px 0;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Good .mdSocialCountList01Ico{width:13px;height:14px;margin-top:-4px;*margin-top:0;background-position:-70px 0;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Comment,.MdSocialCountList01 .mdSocialCountList01Good,.MdSocialCountList01 .mdSocialCountList01View{margin:0 -2px 0 0;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Label{margin:0 5px 0 0;color:#7b7b7b;font-family:Tahoma,Arial,Helvetica,sans-serif;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Num{font-weight:bold;color:#7b7b7b;font-family:Tahoma,Arial,Helvetica,sans-serif;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Hatena .mdSocialCountList01Num,.MdSocialCountList01 .mdSocialCountList01Twitter .mdSocialCountList01Num,.MdSocialCountList01 .mdSocialCountList01Facebook .mdSocialCountList01Num{margin-left:4px;}";
        str += ".MdSocialCountList01 .mdSocialCountList01Comment .mdSocialCountList01Num,.MdSocialCountList01 .mdSocialCountList01Good .mdSocialCountList01Num{margin-left:5px;}";
    return str;
}
var app = http.createServer(function(req,res){
    res.writeHead(200,{"Content-Type":"text/html"});
    var prm = url.parse(req.url,true);
    if(req.method == "GET" && prm.query && prm.query.mode){
        var mode  = prm.query.mode;
        if(mode != "matome.naver"){res.statusCode=403;res.write("403 Forbidden");res.end();return;}
        var usr   = prm.query.usr.replace(/script|\"|\'|\(|\)|\{|\}|\:|\;|\,|function/gi,"");
        if(!usr || usr == ""){res.statusCode=403;res.write("403 Forbidden");res.end();return;}
        var naver = "http://matome.naver.jp/mymatome/" + usr;
        var xhr = new XHR();
            xhr.onreadystatechange = function(){
                if(this.readyState == 4){
                    var con  = this.responseText;
                    var doc  = jsdom.jsdom(con);
                    var win  = doc.createWindow();
                    var body = "";
                    jsdom.jQueryify(win,jq,function(win,$){
                        body = $(".mdMypageMTMList01Item").html();
                        res.write("<!DOCTYPE html><html lang='ja'><head><meta charset='UTF-8'>");
                        res.write("<style>" + style() + "</style>");
                        res.write("</head><body>");
                        res.write(body);
                        res.write("</body></html>");
                        res.end();
                    });
                }
            };
            xhr.open("GET",naver);
        xhr.send();
    }else{
        res.end();
    }
});
app.listen(80);

javascript で 出来る色んな事をまとめた。

NAVERまとめでまとめました。

JavaScript でこんなことも出来るのか!なまとめ
http://matome.naver.jp/odai/2132918730570646901


まぁ、Twitterで既に見た人も居ると思うけども。
個人的に、『おっ!こんなこともできるのかー!』みたいのを纏めた。
見た目的に凄いのもあれば、
『こういうのはウィンドウズのアプリケーションじゃないと出来ないと思ってたよー』
みたいなのもあります。


javascript っていうと、範囲が広いんだよなぁ。
『こりゃ凄い』みたいなのを、素直な気持ちで纏めて行きたいと思います。
他の人にとっては大したことなくても、
俺にとって凄ければそれでいいじゃないの。人間だもの。みつを。

『一昔前というか、俺がインターネットを始めた時は、
javascript って嫌われてたなー』

というのを、ついつい、何度も書いてしまう。

例えば、ゲームに関して言えば、
その頃のブラウザゲームというと、
CGIで都度ページをリロードして遊ぶようなゲームだった気がする。
FLASHも3が出たかどうかみたいな感じで。
ブラウザで遊べるJAVAのゲームもあったけど、凄く重くて、みたいな気がした。
その頃とは、凄く変わったんだなーと思う。

ブラウザにプラグインを入れなくてもゲームが出来るってところは、
凄い事だと思う。
Java、Flashみたいに、なんか、コンパイルされたファイル(.jar とか .swf)じゃなくても、
.js で誰でも作れる、中を覗ける、改造できるっつーのも、魅力ではあるよねぇ。

でも、html に <embed> って書くか、 <canvas> って書くかに変わっただけな気もする。
それが、凄いことなんだけど、不思議だよねぇ。


javascript で pdf が作れる、 zip が作れる、 psd を開ける、 lzh を開ける、
サーバが立てられちゃう、iPhone アプリが作れちゃうつーのは、
とっても楽しいことだなーと思う。

そういえば、
javascript と同じようにあの頃嫌われていた ActiveX はどうなったんだろう。


2012年2月13日月曜日

Google Street View 上に Three.js の 3D グラフィックを表示

実行結果は

http://psychedesire.webcrow.jp/stmon/

キャラクタがボヨンボヨンします。
WebGL対応のブラウザで開いてください。Chromeとかなら大丈夫だと思うよ。



コチラより。
今のところGoogleに怒られていません。
まぁ、アクセス自体が無いからねぇ。

3D オブジェクトは、メタセコイアで作り、それを Blender にインポートして、Blender から .js に変換しました。
mesh.rotation.x とかが動かない?よくわからないので、
camera.rotaion.x とかで無理矢理キャラクタをボヨンボヨン動かしています。

殆どのやり方は、


空が狭い: Three.jsでMQOデータを表示するまで

こちらを参考にしましたが、違うやり方をしたのが2点あって、
1点が、
Blender に メタセコイアのデータ .mqp をインポートする場合は、
 
 Blender2.5~2.6 - とあるPGの研究記録Ⅱ(レコーダー)

このインポータを使いました。Blender の最新 2.6.1 にも対応しています。

2点目が、
Blender から Three.js への エクスポータが、現状 2.6.0 にしか対応していないので、
 \Blender\2.61\scripts\addons\io_mesh_threejs\__init__.py
の28行目の 2.6.0 を 2.6.1 に書き換えました。

苦労した点、というわけじゃないけど、
ブラウザで3Dオブジェクトを表示したときに、どこにオブジェクトがあるのか、わからなかったので、
カメラの位置とかを色々動かして、なんとか最適なカメラポジションとか設定しました。
なんせ、3Dがわからないので。
コツとしては(?)オブジェクトを、ステージに対して、凄く巨大にすればいいみたいです。
あと、何故か、上下逆転する?ので、Blender上でY軸に180度回転させたりしています。

画像的に言うと、メタセコで






こうやって作って、
Blenderで

こうしてから、Three.js にエクスポートしてる感じです。。。
よくわからないけど、 これでうまくいった。
取り合えず、素材を6個作るので限界だった~。
3Dで凄い造型を作る人って、凄いよね。

マウスのイヴェント処理に応じて、3Dオブジェクトのカメラ位置を変えたり、
連動してストリートビューの表示を変えたり出来たら、見た目部分はOKかなーと思います。
あとは、部品だよね。これは。あまりにショボすぎるけど、
フリーのやつ使うのもねー。せっかくだから自作したいもんねー。

Googleに怒られるまで、チョコチョコイジって遊びたいですね。

2012年2月11日土曜日

各種3D製作ソフトのファイルを Three.js 用JSONに変換する方法まとめ

英語が多くて、なんか嘘が多そうな予感。

色々見てみたのですが、
それぞれのソフトで、.obj にしてから、convert_obj_three.py というのを使って、
JSON にコンバートするみたいです。
python のコンバータ convert_obj_three.py は

https://github.com/alteredq/three.js/tree/master/utils/exporters



https://github.com/mrdoob/three.js/tree/master/utils/exporters

ここにあります。
AutodeskFBX・Blender・3DS MAXは専用のエクスポートモジュールやプラグインがあるみたいですね。
mrdoob さんのほうが最新みたいですが、
blender の古いバージョンのプラグインとかは alterdq さんのほうにしかなかったり?するみたい。
動作デモは、

http://alteredqualia.com/tmp/three/examples/obj_convert_test.html

ここにあります。


3DS MAX
専用のエクスポータもあるようなのですが、
.obj に出力してからのほうが綺麗みたい?です。
.obj への出力の仕方が書いてありました。
http://bkcore.com/blog/3d/webgl-three-js-workflow-tips.html

MAYA こちらも .obj にしてから、みたいですね。。
http://blog.stickmanventures.com/2011/11/17/convert-a-model-from-maya-to-webgl-for-use-with-three-js/

md2
やりかたはこちら(日本語)。
http://d.hatena.ne.jp/nakamura001/20120206/1328542607

デモはこちら
http://oos.moxiecode.com/js_webgl/md2/index.html

なんでこんなのまとめたかというと、.x ファイルという 3D のファイルがあって、
それを Three.js で使えるようにするJSONコンバータを作りかけていたんですが、
ものすごくワケが判らなくなってやめましたw

俺が使ってるメタセコイアでも、

http://homepage1.nifty.com/garbagesoft/tools.html

ここにあるプラグイン使えば(?) obj に出来るぽいんだけど、
プラグインを使えるのはシェアウェア版のみなのだよ。なのだよ…

Google Street View にモンスターが出現するWebアプリ作った。



超適当です。アハハハハ。
 ストモンと言います。ここで見れますよ。
http://psychedesire.webcrow.jp/stmon/

Google Map API の v3 というのが出ていて、
それだと、 Flash ではなく、 html5 で Street Viewが見れるようなので、
思い切ってやっちゃいました!エヘヘヘヘ。
知らなかったわぁ~。

Googleストリートビュー内で銃を撃てる『Google Shoot View』が閉鎖

まぁ、こういう前例があるので、直ぐに使えなくなると思いますけども。

GoogleChromeでしか動かないかも知れません。
他のブラウザは試してないです。

郵便番号を入れると、
その郵便番号近辺の地域で卵が孵ります。
で、勝手にモンスターの種類が決まります。

その内容でよければ、名前をつけて保存してください。
保存したモンスターは、ストモンって書いたアイコンを押せば見れます。
他は何も出来ません。

ほんとは、Three.js で作った3Dオブジェクトを表示させたかったけど、
心の中の悪魔が、
『どうせGoogleに消せって言われるんでしょ?』
と言ったので、凄く適当になりました。


製作時間10時間ほどです。
データストレージは WebStorage(localStorage) なので、
サーバ側に何か残したりしていません。
郵便番号投げると住所のJSONを返してくれるAPIがあったので、
使わせていただきました。

郵便番号検索API by グルーブテクノロジー株式会社

スマホと連動すれば楽しいのになぁとか、
夢が広がるんですけどね。残念だなぁ。

2012年2月8日水曜日

Three.js と Google Street View で 街にモンスター出現

なんて出来たら楽しいんじゃないかと思ったので、やってみた。

みんなが使っている、インターネットを見るためのソフト(ブラウザ)に、
Javascriptでプログラムを組んだりするだけで、
3Dの画像なんかを表示する技術が出来つつあります。

Three.js というJavascriptフレームワークを使うと、3Dグラフィックをブラウザに楽に描画できます。

でも、3Dグラフィックをコードだけでプログラミングするのはめんどうくさい。
巷には、 ShadeやPoser、3DSMAX、メタセコイア、六角大王、Blenderなど、
3Dグラフィックを出来るだけ簡単に作れるようなソフトがあって、
そんなソフトと同じように、Three.js用のデータを作れるものが、ThreeFabという名前で公開されています。

Moongift さんの紹介記事
Three.js対応。Webブラウザ上で3Dモデルを作成「ThreeFab」

で、これを使いながら、GoogleStreetView上に、自分の作った3Dグラフィックを描画できないかという実験です。
あ、結果から言うと、失敗です。

まずは、ThreeFab の準備。
ThreeFab はGit 上にありますので、
Git が既に使えるという状態であれば、
Windowsのコマンドプロンプトを開いて、
cd c:\
git clone git://github.com/blackjk3/threefab
とすれば、
Cドライブ直下の threefab というディレクトリ に ファイルがダウンロードされ展開されます。
C:\threefab\index.html を GoogleChrome にドラッグアンドドロップすれば、
ThreeFab が使えます。(この使い方であってるのか?取り合えず動いた)
で、実際に3Dオブジェクトを作ってみた。





なんだこのタコチュウ。
で、出来たので(多分10分くらいで作った)、右上のエクスポートを押すと、
なんかいっぱいJavascriptコードが表示されるので、どっかにコピーしておきます。

次は Google Street View。
まずは、

http://code.google.com/intl/ja/apis/maps/documentation/javascript/v2/services.html

ここの左上の登録してAPIキーを取得をクリックして、
APIキーを取得します。
使うウェブサイトのアドレスを入れたら、APIキーが取得できると思うので、
Javascript のところに書いてあるものをまるっとコピーします。

で、どうやって使うかというと、

ストリートビューを表示する

ここに書いてあるのを改造しちゃいましょう。でへ。てへぺろ。
ていうか、openspc2.org って、色々なサンプルがあって凄いよねぇ。

で、なんかうまいことやろうと思ったけど、ThreeFab から export した Javascript のコードが動かない。
よく見ると、ところどころ、必要ないっぽい }); が存在している…
そこの部分をコメントアウトしても、なんか何にも表示されないし。
まぁ、仕方ない。こういう時は、あきらめよう。検索しても何も出てこない。
つか、そもそも Three.js の使い方が判らないからなー。

Three.js のサンプルコードを表示することにします。
Three.js もGit にあります。
いちいち clone とかしなくても、 Git のページをちょっと下にスクロールすると、
Minified Library って書いたリンクがあるので、それをダウンロードして使うと良いです。
その下にサンプルコードがある(赤い線の立方体がアニメーションするやつ)ので、
それをまんまコピペした。

で、ぽこぽこ書いてみた。
[CSS]
        <style>
*{margin:0;padding:0;vertical-align:middle;}
#streetview{
    position:absolute;
    top     :0;
    left    :0;
    width   :640px;
    height  :480px;
}
#three{
    position:absolute;
    top     :0;
    left    :0;
    width   :640px;
    height  :480px;
}
        </style>

[Javascript]
// Three.js のサンプルコード
    var camera, scene, renderer,geometry, material, mesh;
    function init() {
        scene = new THREE.Scene();
        // camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 1, 10000 );
        camera = new THREE.PerspectiveCamera( 75, 640 / 480, 1, 10000 );
        camera.position.z = 500;
        scene.add( camera );
        geometry = new THREE.CubeGeometry( 200, 200, 200 );
        material = new THREE.MeshBasicMaterial( { color: 0xff0000, wireframe: true } );
        mesh = new THREE.Mesh( geometry, material );
        scene.add( mesh );
        renderer = new THREE.CanvasRenderer();
        // renderer.setSize( window.innerWidth, window.innerHeight );
        renderer.setSize("640","480");
        // document.body.appendChild( renderer.domElement );
        $("#three").append(renderer.domElement);
    }

    function animate() {
        // note: three.js includes requestAnimationFrame shim
        requestAnimationFrame( animate );
        render();
    }

    function render() {
        mesh.rotation.x += 0.01;
        mesh.rotation.y += 0.02;
        renderer.render( scene, camera );
    }

// StreetView の 描画
var makeStreetView = function(callback){
    var streetObj = new GStreetviewPanorama(document.getElementById("streetview"));
    var sibuya = new GLatLng(35.660748,139.701762);
    streetObj.setLocationAndPOV(sibuya);
    if(callback && typeof(callback) == "function){callback();}
};

$(document).ready(function(){
    makeStreetView(function(){
        init();
        animate();
    });
});

[html]
    <body>
        <div id='three'></div>
        <div id='streetview'></div>
    </body>

みたいにしたけど、残念。Google Street View はFlashで動くので、z-index が効きません。
なので、Google Street View の上に、3Dオブジェクトを描画することが出来ませんでした。
Google Street View の下のレイヤに、赤い立方体が回っている感じになった。

Flash コンテンツが z-index を無視して覆い被さってしまう件
[flash][javascript] Flash の z-index を Javascript から有効にする
z-indexを無視してFlashが上に重なってしまうのに対処

色々調べたけど、まぁ、無理だなぁ。
あとからパラメタ書き換えたけど、うまくいかなかった。

つか、そもそも、Google Street View のAPI利用規約とかにひっかかりそうなので、
だめだろうな。うむ。


『地図上のロゴや属性を改変したり、見えにくくしないでください。』

って書いてあるしね。
でもまぁ、ブラウザで Three.js を使ったりすることを体験できたから良かった。
サンプルをみてるだけで満足することが多いので、
何かしら自分で作ってみることって大事ですよね。
結局サンプルはっつけただけの記事書いておいて、ですけど、そう思います。

html5 の pushState が 動かなかったのと、jQuery と html5 data と pushState。

原因:ローカルにおいてあるファイル(file://~/index.html) を開いていたから。
Windows環境ではダメでした。
<script>
 var url = "http://localhost/hoge";
 history.pushState(null,null,url);
</script> 
とかやってもダメでした。

単純に『pushState file://』で検索しても出てこない。
俗に言う、凡ミス(てへぺろ)の領域なんだろうけど、
そんな事で5分間とか時間を無駄にする人が二度と現れない事を祈ります。
適当なサーバに置けば、ちゃんと動きました。

html5 では、data-hoge-moge みたいな、オレオレアトリビュートで、
ほーむぺーじに情報を付け加えられるそうです。
jQueryMobile とかで使われているやつですね。Microdata とかと繋がっていくとかどうとか。
Microdata については、

HTML5の新要素「data要素」に繋がる Microdataのプロパティについて

この記事が詳しいです。
RSSとかXMLとかhtmlって、データベースの行とか、データベースのテーブルとしても使えたらいいよね?
みたいなのを、ずっと色々やってて、うまくいかなかったけど、
なんかやっとうまくいくんじゃね?みたいな感じなのかなーと、
勝手に見てましたけど、違ったらごめんなさい。
検索エンジンに対してのページ解析とかにも関っていったり、
SocialGraph っつか、まぁ、SNS とか、そういうのにも関ってくるよーみたいなものだそうですよ。
この辺について変なことを書くと、森ボーイという人からツッコミが入るので、さらっとふわっとしか書きません。

で、この data要素data属性使って pushState いじくりゃいいんじゃね?みたいなのを書きました。
まぁ、きっと、色んな人が既に書いてるものですけど。多分。めげずに Fight!

<script>
    $(document).ready(function(){
        $("nav").on("click","li",functioni(){
            var data = $(this).data("hogeHuga"); *
            var url  = "";
            for(var i in data){
                url += "/" + encodeURIComponent(data[i].replace(/\"|\'|\(|\)/gi,""));
            }
            history.pushState(null,null,url); // "/hirama/hokkaido"になるとおもう
        });
    });
</script>

<nav>
    <ul>
        <li data-hoge-huga='{"name":"hirama","state":"hokkaido"}'>おれっちひらまっち</li>
    </ul>
</nav>
こんな感じになりました。
jQuery の on を使ってみましたよ!うほ。
jQueryの on off は、この記事がわかりやすかったです。
赤で * 書いてあるところが大事みたいです。

html 上は、 data-hoge-huga って書いてあるんだけど、
この中身を取り出すときは、 hogeHuga って、キャメルクラッチ キャメルケースになるそうです。
キャメルクラッチについては、ここが詳しいです。
jQuery でデータを呼び出す時は、この例のような書き方をすると、object 型になります。

[追記:
 <data hoge='1234'>ほげー</data> ← data要素
 <span data-hoge='1234'>ほげー</span> ←data属性
 というそうです。森ボーイこと forestk さんご指摘ありがとうございます!
 そうだよね。要素っつったら、<a></a> だもんね。エレメント。
 属性つったら、 href='' だもんね。アトリビュート。
 jQuery で要素を取るんだったら、普通に $("data").attr("hoge") で取るのか?おう?あれ?
]

この辺の挙動については、

意外と要注意 HTML5データ属性とjQuery Data APIの関係まとめ

ここに詳しく載っています。

で、for in でデータを基にURLつくって、pushState にホイと渡す感じですね。
渡すだけだと、ただブラウザのURLが変わるだけなので、
このデータに基づいて、ajax かなんかでデータのやり取りをして、なんかする感じ。
そこらへんは、

AjaxでもURLを更新して履歴を作れるHTML5のpushState試してみた

この記事が良くわかります。
応用というか、canvas ていう線を書いたりするやつも交えて使っているのが、

history.pushState、history.replaceState

この記事です。
うむ。うむうむ。

ええと、こんな感じでした。これで何をするのかは、わかりません。

2012年2月7日火曜日

Google Adwords の人から電話が来た





 最近、PV数も増えたし、広告を載せようということで、
GoogleとAmazonの広告を載せ始めました。

で、←の画像の広告が出てきたので、
なんだろーこれと思ってクリックしたら、
Googleに広告が出せるよ!ていう、GoogleAdwordsが3000円分タダで使えるよーって案内だった。

『Androidアプリの宣伝して貰えばいいずwwwwww』と思って、
名前と電話番号と、会社のHPなんてないから、AndroidマーケットのURLを入れて送ったら、
GoogleAdwordsの人から電話が来た。

なんか、企業情報にあたる情報(名前とか電話番号とか住所とか)と、
プライバシーポリシーが無いとダメですってことだったらしい。
まぁ、マーケットのページには、俺の住所も電話番号も載ってないよなーと思ったので、
『じゃあ、ブログがあるんで、そこに書いてもいいすか?』って言ったら、
OKっぽいので、このブログに電話番号とかプライバシーポリシーとかを載せることにしてみる。

なんか、電話で打ち合わせをしながら、広告掲載とかするみたい。
へぇ~。前居た会社とかで、求人広告の打ち合わせとかした事があるんだけど、
そんな感じなのだろうか。面白そう。

あーいう電話営業は、Googleの人じゃなくて、代理店の人とかが電話してるのかなー?
アウトソーシングってやつ?どんな風になってるんだろーなぁ。
もうコールセンタ業とか足を踏み入れたくないな、と思いつつ、
やっぱり興味出てきちゃうよねぇ。

LivedoorBlog にエロブログを作るまでをNAVERまとめした。


僕が LivedoorBlog にエロブログを作るまでにやった事

なんのこっちゃないスクリプトですねぇ。

1・エロイ画像を投稿しがちなTumblrを集めてくる。
2・APIでJSON取って来て、type=photo の画像のアドレスを集める。
3・新しい画像を全部ダウンロードする
4・ダウンロードした画像のサムネイル版を作る
5・AmazonS3にアップロード
6・画像とかのURLをLivedoorBlogに記事としてメールで投稿する。

みたいな感じ。
全然、Blogへの愛がないからかわからないけど、収入にはなりませんね。
PV数も全然上がらないしなー。
逆に、AmazonS3にお金払っている分赤字ですね(笑)
ちゃんと記事を書いているエロブログって、
なんていうの?『魅惑の黒タイツ画像で抜こうずwwwww』とか『この素人エロ杉wwww』 とか、
ブログエントリ毎に画像を選んでいるから、みんな見るんだろうなーと思います。
俺のはあからさまに機械的だもんなー。

でも、結局みんな、エロ画像が見れれば、それでいい!って話じゃないの?とも思うけど、
ん~。でもまぁ、やっぱ、入り口が大事というか、
『よぉし!このブログタイトルならば、さぞかしエロイ画像に違いない!』
と思い、期待に胸膨らませながら、ブログエントリを開いて見る、というところに、
男の浪漫?あるんじゃない?うん。俺はわかってる。

2012年2月6日月曜日

Titanium Mobile で参考にしたものをNAVERまとめしてみた。

作ったまとめはコチラにあります。

最近流行ってますよね。お金もらえるらしいし。へぇ~。
エロイ画像を見るためにしか、殆ど使ってなかったNAVERまとめですが、
Firefoxのお気に入りがエラい事沢山溜まってしまい、
今 Blogger でまとめ始めていたので、Blogger でまとめるのをやめて、NAVERまとめにしてみました。
まぁ、べんりっちゃあ、便利かなぁ。

はてなブックマークとか、SBMサービスって、
エントリに対して何かしらタグをつけていって、
それが蓄積されたときに、付けられたタグ側から見て、まとめになってる感じ。
NAVERまとめみたいなのは、その逆なだけなんだよねぇ。

その、見る人側的に、見たい、探したいものが決まっている時は、
NAVERまとめがいいんだろうなと思います。
SBMサービスは個人の関心事を緩く誰かの関心事と繋げるものっぽい?ので、
用途がNAVERまとめとはそもそも違うけども。
SBMのが、Twitter的で、
NAVERまとめのが、Blog的だなーと思った。

NAVERまとめの欠点?というか、そんなのがあるとすれば、
例えば、SBMのトップページで [これはひどい] ってタグを選べば、
全てのユーザが [これはひどい] とタグをつけたエントリがズラズラ出てくると思うんだけど、
NAVERまとめは、同じようなまとめが乱立しないのかな?って思う。
そういう秩序みたいなのは、どうなってるんだろう。

GitみたいにForkして、そこから先は俺はこう纏めるぜ!みたいに、
枝分かれして、集束いけば、きっとある程度、
情報の美しく纏まって行く様みたいなのが、あると思うけど。
纏めに対してタグ(トピック)をつけたり、複数人で編集出来たりするみたいだけど、
お金が絡むと、人間は難しいからなぁ。とか、色々、気を揉むよね。おっさんだから。

トピックが重複するまとめ達の中に含まれるアイテム(URLとか画像)で登場回数の多いものとかが、
見る側にとって大事だと思うんだけど、
そういったものを表示するものってあるのかなー?
javascript css html5 というトピックのついた A というまとめ上のURL X,Y,Z
javascript node.js html5 express というトピックのついた B というまとめ上のURL V,W,X

があったら、 javascript html5 というトピックにおいて、 X というURLは、大事だよね。ていう、意味ね。

なんせ、エロ画像しか見てないからわからない。
画像をZIPでダウンロードできる麿ボタンとかつけたらいいと思うよ本当に。

JSON かどうか評価する関数 isJson を作った。

結構、JSONをパースする度に、try catch して、
タブが深くなるので、
簡易的にJSONか評価する関数を作った。
ColdFusion ってやつだと、そういう関数があるみたいだけど、
Javascript ではないっぽい?
jQuery でもないっぽい?
まぁ、大して難しいものでもないので、良ければ使ってください。

var isJson = function(arg){
    arg = (typeof(arg) == "function") ? arg() : arg;
    if(typeof(arg) != "string"){return false;}
    try{arg = (!JSON) ? eval("(" + arg + ")") : JSON.parse(arg);return true;}catch(e){return false;}
}

alert(isJson(1));                 // false
alert(isJson({data:"hoge"}));     // false
alert(isJson('{"data":"hoge"}')); // true
alert(isJson("{'data':'hoge'}")); // false
alert(isJson(function(){return '{"data":"hoge"}';})); // true

ちゃんと、
'{"data":"hoge"}'

"{'data':'hoge'}"
を区別して評価してくれて良かった。

つか、JSON.parse() が出来るかどうかって、
(!JSON) で判別していいのかしら?
eval() は、昔どっかのブログでグローバルをなんちゃらとか書いてあった気がしたので、
できるだけ、JSON.parse() 使えたら使えるようにしたいんだけどもねぇ。
でも、JSON.parse() より eval() のほうが速いよ!っていうのも見た気がした。

Chrome16 と Firefox3.6.x で動作確認済みですー。

2012年2月5日日曜日

Cloud 9 で Git と連携する。 heroku に node.js のコードを deploy する。

 
Blogger、画像付記事が書き辛いな…勝手に回り込む…

まぁいいか。
Cloud9からGitと連携できるっぽいことに気づいたので、
画像付で親切に書いてみます。

なんで画像付で親切に書くかというと、
あとで自分でやり方がわからなくなるからです。

まず、ログインして、ダッシュボードで、
Githubの横の activate って書いた緑の字を押します。










そしたら、Githubのウィンドウが開くので、
IDとパスワードを入れてログインを押します。
















OAuth認証みたいな感じで、
Allow か Denyか聞いてきます。
レッチリの Dani California はかっこいい曲ですが、
ここでは Allow を選びます。 







すると、ダッシュボード左にGithubで使ってるプロジェクトが表示されました。
やったね!
まぁ、別に今はこれをどうこうする気はないので、放置。
あとでどうこうする時に、記事にしますね。

ちなみに、givmero っていうのは、
俺が作ったエロブログです。

今のところ、
Tumblrのエロ画像を良く貼っているところから画像をダウンロードして、
画像をAmazonS2にアップロードしたのち、
Livedoorブログに記事を投稿するようなPHPスクリプトですが、
Gitにコードを置いていません。残念。
ブログ自体は givmero ここらへんです。18歳以上の人だけ開いてね!












はい。画像転載バラ撒きクソエロブログはどうでもいいので、
次はCloud9で書いたコードを heroku にdeploy するやりかたです。

まず、プロジェクトから、rssgetter を開きます。
開いたら、左の deploy って書いた気球?をクリックして、
Create a Deploy Server をクリックします。





















deploy 先を選べます。
Heroku Joyent(no.de) Windows Azure が選べます。

























今はFreeのMacheneが作れないからか、
Joyentは有料のものしか表示されません…
























というわけで、heroku.com、君に決めた!という感じで、
heroku にサインインします。
heroku にアカウント持っている前提で話し進めます。
それくらいググれ。

常に優しい男はダメ。
たまに突き放す。そして、大事なときに、包み込む。
これが、本当の、男の愛情表現。わかる?
俺は自分で言ってて何がなんだか全然わかりません。


















でー、ボタン押したらメアドとパスワード入れろって言われるから、
入れてサインインを押します。押しめんします。

俺のオシメンは市井由理だね。
東京パフォーマンスドールの話だけど。






















穴井夕子はどうでもいいので、
サインインが完了すると、今 heroku.com 上にある
自分のアプリ名が表示されます。
今回は今あるのとは別なのを使いたいので、
create new を押します。オシメンします。
俺のオシメn(ry




















hatenaone という名前をつけてAddを押してみます。























完了すると、
hatenaone.herokuapp.com が作られます。

早速なので、Deployを押してみましょう!





package.json がねーぞと言われました。
あら。Cloud9上で書くのを忘れてました。
書いてもう一回やってみる。







今度はProcfileがねーよと言われました。
heroku で使うもの一式を
Cloud9上で準備しなきゃだめなんですねー。
web:node server.js って書くだけだから別にいいけど。

詳細は
http://devcenter.heroku.com/articles/node-js
この辺を見てください。





で、全部準備してDeployして、うまく動いたら
こんな風にActiveになります。

さっき作ったserver.js は、
その名前とは裏腹にサーバ機能をつけてないので、
hatenaone.herokuapp.com にアクセスしても意味はないのですが、
そこらへんちゃんとやれば、
ちゃんとできるはずです。

こんな感じでした。


Cloud 9 で node.js 開発 & オレオレ はてなOne 作った。

Cloud9 という IDE 統合開発環境?が人気みたいです。
Web上で開発が出来るっていうスグレモノみたいです。
node.js をいじることが増えたので、ちょっと使ってみることにします。

http://c9.io/#home

ココにアクセスすると、すぐ左に、表示名とメアドを入れる所があるので、
そこを埋めると、入れたメアド宛にアクティベートコードつきURLみたいなのが届きます。

























 ほんで、そのURLをクリックすると、パスワードを設定しろとか言われるので、
パスワードを入れると、ダッシュボードの画面になります。























で、早速適当にプロジェクトなんて作ってみます。
RSSをJSONにするようなやつを造ろうと思うので、
RSSGetterとか名前をつけて、CREATEします。
Git とか FTP とか色々やりかたを選べるみたいですが、
取りあえず Git でやってみる。



















CREATEを押すと、プロジェクトができるので、
START EDITINGを押してみます。


















しばらーくまっていると、こんな画面になります。
Show this quick start on startup のチェックをはずして、
Just the Editor Please を押してみます















NewFileしてみたり、OpenFileしてみたりするけど、
なんか、タブは増えても、書いたり出来ない…




















これはブラウザが悪いな。多分。
ということで、ブラウザをFirefox 3.6.x から Chrome 16 に変えます。























動いた動いた。

node.js で RSS をパースするには、node-feedparser というのを使えばいいみたいです。

node-feedparser

http://stackoverflow.com/questions/5722638/node-js-rss-module


ほうほう。
RSSの更新日付とかのことも考えて、日付のフォーマットを簡単に変えられるやつも使いたい。

node-datetime

var dt = dateformat((new Date),"yyyymmddHHMMSS");
こんな感じなのかなー?まぁ、やってみよう。
























とりあえず、こんな感じになりました。

オレオレ はてなOne ですね。

var XHR        = require("xmlhttprequest").XMLHttpRequest;
var FeedParser = require('feedparser');
var dateFormat = require('dateformat');

var HatenaOne  = function(usr,callback){this.usr = usr;this.callback = callback;this.init();};
    HatenaOne.prototype = {
        hatena     :["b","d","h"],
        myFav      :[],
        getFavList : function(callback){
        // お気に入りに入れているユーザ一覧を取ってくる
            var self = this;
            var url  = "http://www.hatena.ne.jp/" + this.usr + "/favorites.json";
            var xhr  = new XHR();
            try{
                xhr.onreadystatechange = function(){
                    if(this.readyState == 4){
                        var json = this.responseText;
                            json = JSON.parse(json);
                        self.myFav = json.favorites;
                    }
                };
                xhr.open("GET",url);
                xhr.send();
            }catch(e){
            }finally{
                if(typeof(callback) == "function"){callback();}
            }
        },
        getFeed    : function(){
        // お気に入りのユーザのはてダRSSとかはてブRSSとかフォトライフのRSSとか取ってくる
            var name = "";
            var url  = "";
            for(var i = 0,l = this.myFav.length;i < l;i ++){
                name = this.myFav[i].name;
                for(var j = 0,m = this.hatena.length;j < m;j ++){
                    url  = "http://" + this.hatena[i] + ".hatena.ne.jp/" + name + "/rss";
                    (function(self,url,cnt,parser){
                        parser.on("article",function(json){
                            self.myFav[cnt].time = dateFormat(json.pubDate,"yyyymmddHHMMSS");
                            if(typeof(self.callback) == "function"){self.callback(json);}
                        });
                        parser.parseFile(url);
                    })(this,url,i,(new FeedParser()));
                }
            }
        },
        init       : function(){
            var self = this;
            this.getFavList(function(){self.getFeed();});
        }
    };
   
var hoge = new HatenaOne("psychedesire",function(json){console.log(JSON.stringify(json));});

self.myFav[cnt].time = dateFormat()~のあたりが自信ない。書式これでいいのか?つか、
parser.on した json が一個ずつなのか、配列で返されてるのかちゃんとみてないので、
json.length とかやったりとかして、うまく書き換えて、
前回取得日より新しい更新だけを取得する、とか、
そういう処理を書いてください。そんくらい書けよって話しなんだけどね(笑

var dt = dateFormat(json.pubDate,"yyyymmddHHMMSS");
dt -= 0;
if(self.myFav[i].time &&self.myFav[i].time > dt && typeof(self.callback) == "function"){
 self.callback(json);
 self.myFav[i].time = dt;
}

こうですね。IF文長いね。まぁいいか。
てか、これこのままだと1回しか取得しないので、
init のところで setInterval() とかしなきゃだめだね。

ポイントは、(function(){})() してるところです。ああしないと、非同期?にならないはず。
此間、

timeline.js という非同期処理連携用ライブラリを作成

こういうのを見つけたので、こういうのを使えば調子良いのかも知れないですけど。

ご指摘とか、変だよとか、死ねとか、そういうのあったら言って下さい。死にませんけど。

あ、あと、package.json は

    "dependencies" : {
        "xmlhttprequest"  : "1.2.2"
      , "dateformat"      : "1.0.2-1.2.3"
      , "feedparser"      : "0.9.1"
    },

これみたいです。dateformat のヴァージョンがちょっと変わってるねーと思った。

あ、で、cloud9 の使い勝手ですけど、一応!とか×とか出てきたりしてくれるので、
勉強になりました。
for文の中で function 使うなとか言われました。テヘペロ。むしろテヘベロ。