どめ のすべての投稿

座標系変換 / CreateJS

CreateJSのチュートリアルにある座標系変換。
マウス座標をオブジェクトの座標に変換する場合、以下のようにします。

1
var pt = circle.globalToLocal(stage.mouseX, stage.mouseY);

stage.mouseX, stage.mouseYからマウス座標がとれるので、それを globalToLocal でオブジェクトの座標系に変換します。
この場合、pt.x, pt.y に変換後の座標がはいってます。
さらに hitTest を使用すれば、マウスがオブジェクトに乗っかってるか判定できます。

1
2
3
if (circle.hitTest(pt.x, pt.y)){
    // hit!
}

これで複雑な親子構造になっているオブジェクトでも簡単に座標計算できます。
逆の localToGlobal も、アニメーションするオブジェクト同士の localToLocal も用意されてます。

Tween 機能でアニメーションをつける / CreateJS

CreateJSのTween機能でアニメーションつけてみる。
これを使うとまとめて設定できます。

1
2
3
var start = 0;
var end = 400;
createjs.Tween.get(circle,{loop:true}).to({x:end}, 5000).to({x:start}, 0);

get で対象オブジェクトを指定します。
その際にオプション指定できます。
{ loop: true } はアニメーションのループを指定。
オプションは公式のドキュメント参照。
http://createjs.com/Docs/TweenJS/Tween.html

to で動きの指定と、完了までの時間をミリ秒で指定できます。
to は複数指定できるので、一連のアニメーションをまとめられます。
Tween には easing 機能も用意されてるので、いろんな動きも指定できるみたいで楽しそう。

アニメーション基礎 / CreateJS

CreateJSでアニメーションやってみる。
チュートリアルにある Animation and Ticker を参考にしつつ。

フレームごとに少しずつオブジェクトを動かします。まあ、基本的な考え方はどれも同じよね。

1
2
circle.x += 100; // 100pix移動
stage.update();

ループは setInterval や setTimeout でもよいけど、Ticker と言う機能が用意されてます。
すると tick という関数が毎度呼ばれるので、これに処理を記述します。
フレームレートの指定もできます。(デフォルトは20FPS)

1
2
3
4
5
6
7
8
9
10
11
12
var FPS = 30;
var speed = 100; // pix / sec
speed /= FPS;
function init(){
    // 初期化処理の中で指定
    createjs.Ticker.addListener(window);
    createjs.Ticker.setFPS(FPS);
}
function tick(){
    // Ticker から毎フレーム呼ばれる
    circle.x += speed;
}

ただ、これだとフレームレートが動的に変化するような場合に、移動スピードも変わってしまいます。
これに対応する機能が CreateJS では用意されています。
下記のように elapsedTime にミリ秒単位で時間差を取得できるので、これを元に移動量を決定します。

1
2
3
4
5
var speed = 100; // pix / sec
speed /= 1000; // pix / ms
function tick(elapsedTime){
    circle.x += elapsedTime * speed;
}

CreateJSさわってみる

ゲーム系のJavaScriptライブラリの中でCreateJSが気になってたのでちょっとさわってみることに。
とりあえず付属してるチュートリアル参考にしつつ。

まずはライブラリの読み込み。
最近はCDN用意されてるもの増えたね。

1
<script src="http://code.createjs.com/easeljs-0.5.0.min.js"></script>

あとは描画用の canvas と onload で呼ばれる関数の指定。
まずはチュートリアルにしたがって下記のように指定。

1
2
3
<body onLoad="init();">
    <canvas id="demoCanvas" width="640" height="480"></canvas>
</body>

ひとまず準備はこれだけ。
あとは init 関数に処理指定すればイイみたい。

描画する canvas は id 属性にて指定、最後にupdateします。
stage とかは Flash の ActionScript ライクになってる模様…ActionScript 知らんけど。

1
2
3
4
5
6
7
function init(){
    var stage = new createjs.Stage("demoCanvas");

    // 図形の処理とかここに描く

    stage.update();
}

例えば半径50pxの赤い円を描きたければ次の感じで。
いったん Shape つくって、drawCircle や drawRect、lineTo など指定します。

1
2
3
4
5
var circle = new createjs.Shape();
circle.graphics.beginFill("red").drawCircle(0, 0, 50);
circle.x = 100;
circle.y = 100;
stage.addChild(circle);

それぞれ、ショートカットも用意されていて、beginFill = f, drawCircle = dc とか用意されてます。
ドキュメントは見当たらなかったけど、Graphics.js みると最後の方にまとめて指定あります。
そうすると、まとめて下記のようにもかけます。

1
stage.addChild(new createjs.Shape()).setTransform(100,100).graphics.f("red").dc(0, 0, 50);

HTTP Live Streaming

ちょっと調べる機会あったので、メモ。
ライブ配信ではなく、動画のオンデマンド配信についてが中心になります。

HLS(HTTP Live Streaming)はサーバの特別な設定なしでストリーミングが出来るようです。
ライブ配信する時はリアルタイムで変換する必要があるのでFFMPEGと組み合わせて使用します。
クライアント側でやりくりしている部分があるためAppleのデバイス限定となります。

Appleの公式ドキュメントや参考にしたサイトは下記。
https://developer.apple.com/jp/devcenter/ios/library/documentation/StreamingMediaGuide.pdf (PDF)
http://venture-blog.blogspot.jp/2012/05/http-live-streaming.html

オンデマンドで動画を配信する際もライブ配信も、MPEGのTSフォーマットで10秒区切りとか細切れでファイルを用意して、m3u8 のプレイリストで配信するのは共通です。

1
2
3
4
5
6
7
8
9
10
11
#EXTM3U
#EXT-X-TARGETDURATION:10
#EXT-X-MEDIA-SEQUENCE:0
#EXTINF:10, no desc
fileSequence0.ts
#EXTINF:10, no desc
fileSequence1.ts
#EXTINF:10, no desc
fileSequence2.ts
...
#EXT-X-ENDLIST

こんな感じでTSファイルの場所をリストにして指定していきます。
.htaccess や Apache のMIME Type設定も忘れずに。

1
2
AddType application/x-mpegURL .m3u8
AddType video/MP2T .ts

あとは、配信用のページを用意すればひとまず配信可能です。

1
<a href="playlist.m3u8"><video src="playlist.m3u8" autoplay="true" controls="false" width="320" height="180"></video></a>

ライブ配信の場合はリアルタイムでTSファイルを生成しつつ、こちらのプレイリストを更新します。
iPhoneやiPadから見るとこのm3u8ファイルに何度もリクエストがきます。
m3u8ファイル最後の #EXT-X-ENDLIST は配信が終わるまでは出力しないことになります。

で、ここからが今回調べた内容です。前置き長かったですが…
要求としては、なるべく動画を見てもらいたいので早送りできない方法はないものか?というものでした。

通常のオンデマンド配信だと動画のスキップ(早送り)が出来るのですが、擬似的にライブ配信ということにすれば早送りはしにくくなるのではないかと。
という訳で、PHPでサーバ側で動的にプレイリストを出力するというのを試してみました。
クライアント側からリクエストが何度も来るので、セッションで管理して最初のアクセスからの時間経過でプレイリストを更新するようにしました。

ただ、拡張子が .php のままだと、iPhone/iPad で見た時に再生してくれないようです。
なので、.m3u8 で PHP を実行するように .htaccess なり mod_rewrite で設定する必要があります。

今回調べてて思ったより<video>タグは使えるレベルになってる気がしました。
相変わらずデバイスやブラウザ間の調整は必要ですが、あんまり変わったことしなければ何とかなりそうですね。

擬似ライブ配信サンプル ※iPhone / iPad から見てください

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<?php
$video = array(
    'fileSequence0.ts',
    'fileSequence1.ts',
    'fileSequence2.ts',
    'fileSequence3.ts',
    'fileSequence4.ts',
);
$num = count($video);
$maxLength = 50; // sec, 動画の長さ
$length = 10; // sec, 分割動画の長さ
$now = time();

session_name('videoCount');
session_cache_limiter('nocache');
session_cache_expire(60);
session_start();
session_regenerate_id();

if (isset($_SESSION['count'])) {
    if ($now - $_SESSION['count'] > $maxLength) {
        $_SESSION['count'] = $now - 1;
    }
} else {
    $_SESSION['count'] = $now - 1;
}

$page = ceil(($now - $_SESSION['count']) / $length);
if ($page > $num) {
    $page = $num;
}

header("Content-type: application/x-mpegURL");
echo '#EXTM3U';
echo "n";
echo '#EXT-X-TARGETDURATION:10';
echo "n";
echo '#EXT-X-MEDIA-SEQUENCE:0';
echo "n";
echo '#EXT-X-ALLOW-CACHE:NO';
echo "n";

for ($i = 0; $i < $page; $i++) {
    echo '#EXTINF:10, no desc';
    echo "n";
    echo $video[$i];
    echo "n";
}
if ($page == $num) {
    echo '#EXT-X-ENDLIST';
}

iPadで加速度センサー / jQueryゼロから

iPad/iPhoneでiOS4.2以降はブラウザでも加速度センサーの値がとれるのでちょっとテストした時のをまとめます。
javascriptではdevicemotionイベントで取れます。

1
2
3
4
5
6
7
8
$(window).bind('devicemotion', function(e){
    // 加速度
    var a = e.originalEvent.acceleration;
    // 重力加速度
    var g = e.originalEvent.accelerationIncludingGravity;
    // 回転加速度
    var r = e.originalEvent.rotationRate;
}

重力加速度で画面を傾けるとコリント的な動きさせる場合は、下記の感じ。

1
2
3
4
5
6
$(window).bind('devicemotion', function(e){
    // left, top が対象の左上の x, y 座標
    var g = e.originalEvent.accelerationIncludingGravity;
    left += g.x;
    top -= g.y;
}

これだけだとよくあるので、画面を傾けると回転しちゃう場合も考慮に入れてみます。
※画面ロックしなかった時にぐるっと回っちゃうので…
画面の回転はwindow.orientationから0, 90, 180, -90で取れます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$(window).bind('devicemotion', function(e){
    var g = e.originalEvent.accelerationIncludingGravity;
    var dx, dy = 0;
    if (window.orientation == 0) {
        dx = g.x;
        dy = -g.y;
    } else if (window.orientation == 90) {
        dx = -g.y;
        dy = -g.x;
    } else if (window.orientation == 180) {
        dx = -g.x;
        dy = g.y;
    } else {
        dx = g.y;
        dy = g.x;
    }
    left += dx;
    top += dy;
}

あとは画面からはみ出ないようにとかする場合は orientationchange イベントで調整できます。
例えば canvas を画面いっぱいにした場合は、canvasサイズも変更しつつ画面の右下の最大値を調整します。

1
2
3
4
5
6
7
$(window).bind('orientationchange', function(e){
// size は描画するオブジェクトの大きさ
    canvas.width = window.innerWidth;
    canvas.height = window.innerHeight;
    maxX = canvas.width - size;
    maxY = canvas.height - size;
});

まあ、回転に対応するケースはなさそうだけど…

サンプル ※iPadでみてね

iPadでスワイプ / jQueryゼロから

ちょっと特殊だけど、iPadでスワイプ処理を自分で書くことがあったので。
たぶんGalaxyでもあんまり変わらないはず。

タッチイベントは touchstart, touchend, touchmove で拾えます。
touchmove の際に event.touches に座標が入ってます。
配列なのは5つまでデータが入っているから。
今回は、ただのスワイプなので touches[0] だけ使います。

とりあえず座標を拾ってみます。

1
2
3
// touchmove で座標を拾う
X = event.touches[0].pageX;
Y = event.touches[0].pageY;

サンプル ※iPadで見てください

touches には pageX, pageY, screenX, screenY, clientX, clientY があり、ページやスクリーンの相対座標として取得できます。
画面を固定する場合は特に変わりはないですが、スクロールする場合は使い分けが必要です。
※pageX, pageYはスクロールする場合は指に追従してページも移動するので

とりあえず、touchstart と touchend の時の座標の差でスワイプを判定してみます。
X方向に100px動いたらスワイプします。※値は適当です

1
2
3
4
5
6
// touchendで判定
if (startX - endX > 100) {
// prev
} else if (endX - startX > 100) {
// next
}

サンプル

これでもスワイプは出来るのですが、いくつか問題があるのでもう少し調整してみます。
・縦(斜め)にスワイプしても横移動が100px以上ならスワイプするのをやめる
→ touchstart と touchend の確度を小さくする(2点を結ぶ直線の傾きが0.5以下としてみる)
・速度が遅くてもスワイプするのをやめる
→ 0.7秒以内のみスワイプとする
・iPadだと画面がズレる(指に追従する)のをやめる
→ よく使われている方法を参考に preventDefault でブラウザの挙動を無視する

サンプル

LLCの作り方

とりあえず作るだけなら簡単なので手続系からまとめておきます。
まずは前提としてウチはこんな感じの企業です。

  • Web制作企業
  • メンバーは3人(デザイナ、マークアップエンジニア、プログラマ)
  • 全員フリーランスあがり

フリーランスから法人にしたのはよく一緒に仕事してるからというのと、有限責任かな。
株式会社じゃなく合同会社なのは、株主総会がいらないとか手続が安いからというのもあるけど、新しい会社法から追加されたので単に興味というのが大きかったりします。制作の悪いクセで試しにやっちゃおうと。

以下、手続きする際にやったことです。(やった順)

会社名を決める
法務局で似たような社名がないか検索できる端末があります。最近は登記する住所や業種が違えば同じ名前でも良いみたいです。
ただ、社名で検索上位に表示させたいなら競合は避けたいところです。
サーバ、ドメイン契約
業種柄、すぐ出来るので登記前に取って準備しました。co.jpは登記必要なので後から取りました。
会社ロゴ、コーポレートカラー決定
こういう場合、メンバーにデザイナいると早いです
名刺作成
早めに配れるに越したことはないので。登記前からフリーランス時代のお客さんに名刺持って営業行きました。
設立までのスケジュールを立てる
半年計画くらいで、割りとゆっくり計画立てました。フリーランスの仕事しながらだったので。
起業経験者に話し聞いたりアドバイスもらったりしました。やむを得ず会社たたんだ人の方が参考になるかも。
定款作成
何事も経験!ということで、ネット見ながら自分たちで定款作りました。(登記は行政書士さんに頼んだので定款もやってもらうのが早いです)
ついでに契約書などの書類もつくりました。
Webサイト作成
同時にWebサイトもつくりました。
シェアオフィスを借りる
登記に住所必要なので、まずは代表個人で手続きします。シェアオフィス co-lab でフレックス(席はフリーアクセスで会議室が使用可能)に登録しました。Web制作なので基本自宅作業で会議の時に使用してますが、いろんな人達がいるのでもっと活用したいです。
行政書士さんに依頼
知人に行政書士さんを紹介してもらい、指示に従って進めていきます。
資本金の準備
行政書士さんに指示されてから代表の口座に振り込みます。(日付も関連するので、うっかり前もって振り込んでやり直したりしましたw)
社印をつくる
ネットで3点セットとかで作れます。あとゴム印つくったけど、あんまり使ってないです…
陰影はデジタルでもらえたりするのでPDFで請求書とか出す時に使えます。(クライアントによるけど書面でなくて済むので)
各種登記書類の用意
行政書士さんの指示に従いました。 

  • 合同会社設立登記申請書
  • 代表の就任承諾書
  • 代表者印決定書
  • 資本金の額の計上に関する証明書
創業計画書作成
行政書士さんに進めてもらいつつ、同時進行で創業計画書作成。そんなしっかりしたものではないけど、会社としてどんな仕事をしていくか日付つきで計画立てたり、家賃やサーバ代など月々の経費と自分たちの給与から月いくら稼がなきゃなのか試算しました。フリーランスも兼業なので無難な目標にしたけど、最初で攻めた方が良いです。どうせ思い通りになんて行かないので。
払込証明書作成
代表の口座に振り込んだ資本金の通帳コピーに法人代表者印を押します。あとは行政書士さんに手続きしてもらい、審査の通過待ち。
一発ですんなり通ったので、後からもっとイロイロ試せば良かったかなと思ったり。
法人口座の用意
Web制作だしネット銀行にしてみようかと思い楽天銀行で口座作成。念のためゆうちょ銀行もつくりました。
結果から言えば、社保の引き落としができないので、作れそうならメガバンク、東京都民銀行とかの自銀が良いです。(社保は日銀の代理店でないと取り扱えないので楽天銀行は出来ないそうな)
融資を受けるつもりなら貸してくれそうな銀行で。メガバンクはそもそも作れなかったりすることも…
登記申請
法務局に登記申請、印鑑登録して印鑑カードをもらいます。ここも行政書士さんに手続きしてもらいました。
税務署、都税事務所に申請
ここで国税の納付とかで使う整理番号とかもらいます。毎月の給与源泉を半年に1回(1/10, 7/10)に出来る、納期の特例があるので申請しとくと楽。外注さんの報酬源泉は払った月の翌10日までなので、こちらは毎回払いに行きます。普通の銀行窓口で出来るので、会社の口座関係なく最寄りの銀行に行けば良いです。

あとは毎月の経理も自分でやろうとするとなかなかに大変なんですが、それはまたの機会に。

画像をプリロード / jQueryゼロから

画像のプリロードは前にもやったんだけど少し小技をはさんでみた。
プリロードしたって間に合わん時は間に合わんので、せめて見栄えが悪くないようにしようかってはなしです。

下記の感じで画像のプリロード時に読み込み完了後の処理を指定しちゃいます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var imagePath = '/images/';
var preloadImages = [
    'ooo.jpg',
    'xxx.jpg',
    '***.jpg'
];
var images = [];

(function($){
    for (var i = 0; i < preloadImages.length; i++) {
        var image = new Image;
        image.src = imagePath + preloadImages[i];
        images.push($(image).hide());
        (function(i){
            image.onload = function(){
                images[i].fadeIn();
            };
        })(i);
    }
})(jQuery);

読み込みが間に合わなかった時のために画像は hide() で非表示にして、image.onload で読み込み完了時の動作を指定しました。
※今回だとfadeInさせてます

サンプル

カスタムフィールド使ってみる / よくあるWordPress

カスタムフィールドでやりくりした時のメモ。

お客さんに使ってもらう時は管理画面ライクなインターフェイスにしたいのでプラグインのカスタムフィールド・テンプレートを使ってます。
使い方はこちらが詳しいです。
http://39kn.com/2011/05/30/5486/

ということでPHPでテンプレ側の処理を。
カスタムフィールド・テンプレート使った場合はショートコードがあるんだけど、普通の人に使ってもらうにはわかりにくいのでテンプレ側で処理します。

カスタムフィールドのデータはget_post_customで連想配列で取得できます。

1
2
3
4
5
6
7
8
9
10
$custom = get_post_custom();

foreach ($custom as $key => $value) {
    if (substr($key, 0, 1) == '_') {
        continue;
    }
    switch ($key) {
        case ...
    }
}

同じ名前で複数登録できるので一旦取り出したほうがイイかも。
ただ、foreachだと余計な変数入ってるので、「_」で始まるものは除外しとく。
カスタムフィールド・テンプレート使っててもデータは同様に取得できます。