読者です 読者をやめる 読者になる 読者になる

大人のYAPC登壇の告知

yapcasia 大人のYAPC

YAPC::Asia Tokyo 2013が来場予定数1000人突破したなか、非モテの僕にもやっとチャンスが回ってきました。

大人のYAPC - YAPC for Grown-upsにて、一般発表枠にお誘いいただきましたので登壇させていただきます!!

大人のYAPC?

YAPC本編とは一線を画した非公式イベント、YAPCを一通り遊び終わったあとの大人たちが夜な夜な集まり濃密なアダルトテクニックを語り合う場です。アダルトテクニック。

と、適当なことを言うと怒られそうなので一応告知サイトもご覧ください。

要するに、エロい話が大好きな大人の子供が真面目にエンジニアリングでエロを考える会です。(適当)

とまぁ、注意点ですが公式でもあるとおり

  • 一部(性的な内容を含め)過激な内容が含まれる可能性があります。十八歳以下の入場は堅くお断りします
  • Twitter等を含むインターネット上での発表内容に関連する情報の開示を行う場合は必ず登壇者の同意のもと行うようにしてください。もし登壇者が発表内容を公にしないよう求めた場合はそれに従ってください

です。大人の男の子たちなら問題ないですね。

ナニを話すの

昨年、某社AdventCalendarでちょっとした事故を起こしましたが

前回はあくまでスマートフォン向けの軽量かつ実用的なプロダクトとしたところを、今回は今注目のセンサーデバイスを用いるように改修し、ご紹介させていただきます。

当社比2倍以上のぷるんぷるんをお約束します。


イベントへの参加募集は9月から公式サイトにて行われます。

5分のLT枠はまだまだ募集中のようなので、変態エンジニア紳士各位はぜひぜひ@yusukebeさんまでReplyを。

また、YAPC::Asia Tokyo 2013のチケット販売は11日(日)までです。お買い逃した方、少しでも興味のある方はお早めに

僕は社内でチケットが配られてるのを知らず、自費で参加となりました!本当にありがとうございました!!

イベントを企画していただいた、@lestrrat氏・@yusukebe氏、また参加へのキッカケとなった@mackee_wに感謝します。ありがとうございます。

Gitアプリの決定版!SourceTree for windowsがやってきた! ヤァ!ヤァ!ヤァ!

git SourceTree

街頭アンケート「非エンジニアのWindows環境でgitが運用出来ましたか

  • 40%: Github for Windowsを入れたが、日々何らかのトラブルが発生した
  • 30%: TortoiseGitを入れようとしたが、面倒くさすぎてやめた
  • 20%: 上記の情報を知っていたので、他のアプリを探したがどれもクソ完成度がイマイチだった
  • 9%: 非エンジニアはsvnもしくは共有フォルダでファイルを管理してもらい、自分でpushするようになった
  • 1%: 全員Macで開発するようになった

2013.3僕調べ

そんなすべての環境設定おじさんに朗報です!

Macで人気を博したgitアプリ、某法人利用率99%(僕調べ)の"Atlassian SourceTree"がついにWindowsへ登場!!

これで環境設定おじさんの手間も省けるし、誰にも殺意を向けずにすみますね!!やったね!!!

SourceTree for Windowsことはじめ

ダウンロードはこちらから

インストール

ダウンロードしたインストーラーを起動してインストールを進めて行きましょう。

過去に Git for Windows や msysGit をインストール指定なければ、途中で下記のような確認画面が表示されると思います。

f:id:dameleon:20130321184036j:plain

要するに、Git本体(Gitコマンドの実行ファイル)をどうするの?ということなのですが

多くの場合は特に気にせず一番上の選択肢"Download an embedded version of Git for SourceTree alone to use"を選択して大丈夫です。

(過去、または現在TortoiseGitなどでGitを使用しており、現在の環境を引き継ぎたい場合には"Browse to the location of Git on your system"のほうがいいかもしれません。[自動で選択されるかも])

Git本体のインストールを行う(or 既にインストール済みである)と、下記のような画面が表示されます。

f:id:dameleon:20130321184043j:plain

Full Name, Email addressを入力します。

その下のチェックボックスは、通常入れたままで問題ありませんが、気になる場合はプロジェクトの管理者やプログラマに確認するといいでしょう。

"I agree to the SourceTree license agreement"は、規約に同意出来ればチェックを入れ、"Next"をクリックして進みます。

f:id:dameleon:20130321184054j:plain

AtlassianのBitbucket, Stashを使用している場合は、アカウントのサインアップができます。使用してなければ"Finish"でインストール終了です。

f:id:dameleon:20130321184059j:plain

鍵を作る

インストール完了!よし使うぞ!と思いきや、Gitは優しくありません。優しいわけがありません。

まずは、Gitとサーバが通信を行う際の認証情報として必要な「鍵」を作っていきます。

  • Tools > Create or Import SSH Keysを選択
  • PuTTY Key Generatorが起動するので、"Generate"をクリック

f:id:dameleon:20130321184103j:plain

  • 画面上の案内に従って、"Key"の部分でマウスを動かすことにより鍵を生成していきます

f:id:dameleon:20130321184106j:plain

  • 鍵の生成が完了しました。

      "Key Comment"にPCや自分の名前など分かりやすいものを入力します
      "Key passphrase", "Confirm passphrase"に好きなパスワードを入力します
    

(一応ボカしとこう)

f:id:dameleon:20130321184109j:plain

  • "Save private key"をクリックして、「秘密鍵」と呼ばれるものを保存します

      これは誰に見せてはダメな鍵です。見られたら死にます。
      また、無くしてもダメです。死にます。
      特に決まりはありませんが、"id_rsa.ppk"や"名前_PC名.ppk"というファイル名にしておくといいでしょう。
      別に決まりはないので好きでいいです。
    
  • "Public key for pasting into OpenSSH authorized_keys file:"の下のテキストボックスに表示されている文字列の「公開鍵」を保存します

      一旦、メモ帳などに貼り付けて保存すると良いです。
      こちらも特に決まりはないですが、"id_rsa.pub"や"名前_PC名.pub"などがオススメです。好きにしてください。
    
  • 続いて鍵を登録します。PuTTY Key Generatorを閉じて、SourceTreeに戻ったらTools > Launch SSH Agent(pageant)を選択します

  • 先ほど保存した.ppkファイルを選択すると、passphraseを入力するように言われるので入力します

  • これで鍵の登録は完了です


以上で、GitとSourceTreeの環境設定は完了です。

Gitを使ったプロジェクトに参加する際は、「公開鍵」をサーバへ登録する必要があるので、その際はプロジェクト管理者やプログラマに.pubのファイルを渡せば作業をしてくれるでしょう。

簡単な使い方は、また後日。

gruntみたいなコマンド実行できるnodeのmoduleをpackage.jsonに書いた時のメモ

grunt

前回の記事でpackage.jsonのdevDependenciesに依存関係は書いたんだけど そういえばgruntとかコマンド打って動かす系のnode moduleって普通は-gつけてglobal installするよなーとか思って

案の定、別の環境で前回のpackage.jsonからnpm installしたらコマンドは打てないし、なんかイイ方法ないのかなーとか思ってたらそんな感じのがstackoverflowにあった

// package.json
"scripts": {
    "preinstall": "npm i -g themodule"
}

(via. Install dependencies globally and locally using package.json)

npmにも書いてあった

要するに"preinstall"にベタでコマンドを書いておけばmoduleはインストールされる

gruntでいうと

// package.json@tt.js
"scripts": {
    "preinstall": "npm i -g grunt-cli"
}

みたいな感じかな

grunt-cliをinstallすれば、gruntコマンドを打つことでlocalのnode_modules/gruntを見に行ってくれる

そのlocalのnode_modules/gruntはdevDependenciesでパッケージ管理されているという寸法

あと前回は npm install -g grunt しちゃったんだけど、0.4.0からはgrunt-cliをinstallすべきなのを見落としてた

getting-started#installing-the-cli

Grunt for javascript libs

javascript tt.js

ナウでもヤングでもないけどGruntを使ったJS(ライブラリ|プラグイン)配布環境の構築メモ

scaffold的なテンプレを用意したほうが便利なんだけど、その前に基本的な構築とか

忙しい人はあとがきから読むことをおすすめする

やること

おおまかにはJSライブラリのテスト&ビルド用タスクの構築

  1. test
  2. jshint
  3. concat
  4. minify
  5. document生成(今回はやめました)

これらを拙作のgithub.com/dameleon/tt.jsで整えてみる

ファイル構造などが分からなければ、上記リポジトリをcloneして、git checkout developされたし(masterに反映していないので)

package.json

package.jsonってなんぞや

ビルド環境や依存関係、バージョンなどのパッケージ情報を管理するファイル

用意しておけば、どこでも差異なく開発環境が作れる(はず)

気になる方はCommon.jsとかnpmのアレとか見てください。

see

package.jsonを作る

良いサンプルが見つからなかったのでとりあえずjQueryからパクる影響を受けましょう。

// package.json from jQuery
// https://github.com/jquery/jquery/blob/master/package.json
{
    "name": "jquery",
    "title": "jQuery",
    "description": "JavaScript library for DOM operations",
    "version": "2.0.0pre",
    "homepage": "http://jquery.com",
    "author": {
        "name": "jQuery Foundation and other contributors",
        "url": "https://github.com/jquery/jquery/blob/master/AUTHORS.txt"
    },
    "repository": {
        "type": "git",
        "url": "https://github.com/jquery/jquery.git"
    },
    "bugs": {
        "url": "http://bugs.jquery.com"
    },
    "licenses": [
        {
            "type": "MIT",
            "url": "https://github.com/jquery/jquery/blob/master/MIT-LICENSE.txt"
        }
    ],
    "dependencies": {},
    "devDependencies": {
        "grunt-compare-size": "0.3.1",
        "grunt-git-authors": "1.0.0",
        "grunt-update-submodules": "0.2.0",
        "grunt-contrib-watch": "0.1.4",
        "grunt-contrib-jshint": "0.1.1rc6",
        "grunt-contrib-uglify": "0.1.1rc6",
        "grunt": "0.4.0rc5",
        "testswarm": "0.2.2"
    },
    "keywords": 
}


// package.json for tt.js
{
    "name": "tt.js",
    "title": "jQuery",
    "description": "JavaScript Library for fast DOM operations",
    "version": "0.2.0",
    "homepage": "",
    "author": {
        "name": "dameleon",
        "url": "https://twitter.com/damele0n"
    },
    "repository": {
        "type": "git",
        "url": "https://github.com/dameleon/tt.js"
    },
    "bugs": {
        "url": "https://github.com/dameleon/tt.js/issues"
    },
    "licenses": [
        {
            "type": "MIT",
        }
    ],
    "dependencies": {},
    "devDependencies": {},
    "keywords": 
}

インスコ

Grunt本体のインスコ

// 本体をグローバルインストール(直接でもいいです)
$ npm install -g grunt

// projectのディレクトリで作業
$ cd path_to_project

// node_modulesをignore
$ echo node_modules >> .gitignore

// --save-dev付けておけば、package.json の devDependencies へ依存したパッケージとして書き込まれる
$ npm link grunt --save-dev

Gruntプラグインのインストール

今回の構成はこんな感じ

  • linter : jshint > grunt-contrib-jshint
  • test : buster.js > grunt-buster
  • concat : grunt-contrib-concat
  • minify : uglify > grunt-contrib-uglify
  • document : YUIDoc > grunt-contrib-yuidoc

この辺りは好みによって変更のこと。

Gruntプラグイン検索は本家で。

// 全部入れる
$ npm install grunt-contrib-jshint grunt-contrib-uglify grunt-contrib-concat grunt-contrib-yuidoc grunt-buster --save-dev

// buster.jsを使う場合、phantomjsのインストールが必要
$ brew install phantomjs

ここまでやると、package.json に以下の依存関係が書き込まれてるはず。

// @package.json
"devDependencies": {
    "grunt": "~0.4.0",
    "grunt-contrib-jshint": "~0.2.0",
    "grunt-contrib-uglify": "~0.1.2",
    "grunt-contrib-concat": "~0.1.3",
    "grunt-contrib-yuidoc": "~0.4.0"
    "grunt-buster": "~0.1.2",
}

setup grunt.js

環境は整ったので、grunt.jsの動作を設定していく

基本的な書き方はthe-gruntfileらへん

プラグインを入れた際の設定は各プラグインのnpmページ(ex.grunt-contrib-concat)を参考に

// projectのrootで(じゃなくてもいいけど)、gruntfile.jsを作って編集
// coffee scriptでも書けるので、お好きな方でどうぞ
$ vim gruntfile.js

// gruntfile.js
module.exports = function(grunt) {

    grunt.initConfig({

        // package.jsonを読み込む
        // 以後の設定値で pkg.name のようにプロパティをテンプレート内で展開できる
        pkg: grunt.file.readJSON('package.json'),

        buster: {
            test: {
                // buster.jsのconfigファイルを指定
                config: 'test/buster.js',
            },
            server: {
                // port を指定(いらない?)
                port: 1111
            }
        },

        concat: {
            options: {
                // 既存の(既に書かれている)バナーを削除
                stripBanners: true,
                // 結合後のバナーのスタイルを指定
                banner: '/** <%= pkg.title %> version:<%= pkg.version %> author:<%= pkg.author.name %> at:<%= grunt.template.today("yyyy-mm-dd") %> */\n'
            },
            dist: {
                // ソースファイルの指定。ワイルドカードを用いず、1つずつでもOK
                src: 'src/*.js',
                // 結合後のファイル名を指定
                dest: '<%= pkg.name %>.all.js'
            }
        },

        uglify: {
            options: {
                // minify後のバナーのスタイルを指定
                banner: '/** <%= pkg.title %> version:<%= pkg.version %> author:<%= pkg.author.name %> at:<%= grunt.template.today("yyyy-mm-dd") %> */\n'
            },
            build: {
                // ソースファイルを指定
                src: '<%= pkg.name %>.all.js',
                // minify後のファイル名を指定
                dest: '<%= pkg.name %>.min.js'
            }
        },

        jshint: {
            // ターゲットを指定
            all: 'src/*.js',
            // option を設定
            options: {
                curly: true,
                eqnull: true,
                eqeqeq: true,
                undef: true,
                validthis: true,
                globals: {
                    tt: true
                }
            }
        },
    });

    // pluginをロードする
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-uglify');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-buster');

    // taskを登録
    grunt.registerTask('test', ['jshint', 'buster']);
    grunt.registerTask('default', ['jshint', 'buster', 'concat', 'uglify']);
};

run Grunt

必要なものは揃ったので、試しに走らせてみるテスト

// testのタスクを実行
$ grunt test

Running "jshint:all" (jshint) task
>> 1 file lint free.

Running "buster" task
buster-server running on http://localhost:1111
PhantomJS 1.8.1, Mac OS X: ...................................................
2 test cases, 51 tests, 164 assertions, 0 failures, 0 errors, 0 timeouts
Finished in 0.055s

Done, without errors.

// 何も指定していなければ default のタスクが実行される
$ grunt

Running "jshint:all" (jshint) task
>> 1 file lint free.

Running "buster" task
buster-server running on http://localhost:1111
PhantomJS 1.8.1, Mac OS X: ...................................................
2 test cases, 51 tests, 164 assertions, 0 failures, 0 errors, 0 timeouts
Finished in 0.062s

Running "concat:dist" (concat) task
File "tt.all.js" created.

Running "uglify:build" (uglify) task
File "tt.min.js" created.
Uncompressed size: 27308 bytes.
Compressed size: 2293 bytes gzipped (10683 bytes minified).

Done, without errors.

出力としてエラーを受け取った場合は、その箇所を修正して再度実行

結果、ファイル出力として、今回の設定では2つのファイルが生成される

  • tt.all.js
  • tt.min.js

また、concatとuglifyともにバナーを設定したので、それも確認する(今回はどっちも一緒[それもどうかと思うが])

// @tt.all.js#1
/** tt.js version:0.2.0 author:kei takahashi(twitter@dameleon) at:2013-03-05 */

// @tt.min.js#1
/** tt.js version:0.2.0 author:kei takahashi(twitter@dameleon) at:2013-03-05 */

以上で、簡単なビルド環境の設定は終了

あとは複数人でも一人で複数環境でも、安心して開発を行える(はず)

あとがき

実はgrunt-initなる機能があって、既に用意されたテンプレみたいなのも展開できたりもする

手っ取り早くGruntを利用したければこちらのほうがいいかも(ある程度の編集は必要)

see: Project Scaffolding

$ npm install -g grunt-init

// 試しにcommonjsのテンプレをcloneして
$ git clone git@github.com:gruntjs/grunt-init-commonjs.git ~/.grunt-init/commonjs

// 走らせてみる
$ grunt-init commonjs

// 対話式でいろいろ聞かれる
Please answer the following:
[?] Project name (grunttest) hoge
[?] Description (The best project ever.) fuga
[?] Version (0.1.0) 0.1.0
[?] Project git repository (git://github.com/dameleon/grunttest.git)
[?] Project homepage (https://github.com/dameleon/grunttest)
[?] Project issues tracker (https://github.com/dameleon/grunttest/issues)
[?] Licenses (MIT)
[?] Author name (dameleon)
[?] Author email ()
[?] Author url (none)
[?] What versions of node does it run on? (>= 0.6.0)
[?] Main module/entry point (lib/hoge)
[?] Npm test command (grunt nodeunit)
[?] Do you need to make any changes to the above before continuing? (y/N)

// なんか色々作ってくれる
$ ls

.gitignore
.jshintrc
Gruntfile.js
LICENSE-MIT
README.md
lib
package.json
test

もちろん、テンプレートを自分で作ることもできる

see: Project Scaffolding#custom-templates

今度は、今回作ったGrunt周りのものをオレオレテンプレ化してみたりとか

その前にはてブロを綺麗にしないと見づらくてしょうがない…

CSSだけでTemple Runをつくる

CSS Programming

どうも。 おっぱいの人 です。未だホンモノにはありつけていません。

このエントリは、CSS Programming Advent Calendar 2012 23日目の記事です。

CSS Programmingとは

もう今更説明しようがないですよね。

おっぱいとかそんなんより数倍変態な人たちがHTMLとCSSだけでゲームとか作っちゃうアレです。

ぼくはというと、今年一年中ガラケーと戦ってた(業務的に)のでCSS3とか実はほとんど触れていないので、リハビリの意味を込めての復帰戦となります。

CSSだけでTemple Runをつくる

Temple Runってコレです。iPhoneのランニングゲー(?)では一番有名ですよね。

手前味噌で恐縮ですが、Tap Ninja なんというのもKAYACさんからでております。ああ、すみません宣伝では無いんです。石を投げないでください。ごめんなさいごめんなさい。

というのも、今回はちょっと実装量的にもTap Ninjaに近くしたので紹介しました。

さて残された時間も少ないので早速のお披露目です!

CSS Temple Run

動作コードはjsdo.itに貼り付けました。

Chromeでのみ動作を確認しています。

相変わらず、少し大きく作り過ぎちゃったので(jsrun.it)http://jsrun.it/damele0n/jofZのほうで画面を広げて見てください。

キャラクターあたりをクリックして迫り来るサンタクロースの恐怖を回避しよう!!!!

…すごい…!これは、すごい!なんだろう、このすごいコレジャナイ感!!!!!!

Temple Runのいいところを120%握りつぶすようなシュール感と、絶対にやっちゃいけないゲームの琴線に触れたつまらなさが本作品のウリです。

大反省会

難しいですね。CSS Programming。いや、舐めてたわけじゃ無いんですよ?いやホントに。ああ、石を投げないでください。犬を放たないでください。ああ。

今回、sassのsassたる形式を使ったのでjsdo.it上でコンパイルできなくなってしまい、仕方なくjsdo.it上にはコンパイル後のファイルをベタで置いてあります。

動作品の完全なコードは、githubに上げておきました。

画面上の仕組みとしては、

  • 背景
  • 人物やサンタ、隠れたradioなど

で構成してあります。

背景レイヤーについては大まかに

    // 背景のコンテナ
    .bg {
        // 遠近感を設定
        -webkit-perspective: 500;
    }
    // .road, .wall_l, .wall_rの3面で壁を構成
    .road {
        top: 35px;
        width: 300px;
        height: 500px;
        -webkit-transform: rotateX(-290deg);
    }
    .wall_l {
        top: 23px;
        left: -360px;
        width: 770px;
        height: 200px;
        -webkit-transform: rotateY(98.6deg);
    }
    .wall_r {
        top: 23px;
        left: -110px;
        width: 770px;
        height: 200px;
        -webkit-transform: rotateY(-98.6deg);
    }

として、座標系とrotateをいじりながら3面を3Dで配置しました。DevTool見ながら手で。(強引)

逆に操作系というか、パーツ系というか、アニメーションなどが絡むものは全て2Dで扱っています。

// input[type=radio]へ適用。radio自体は隠しちゃう。
.state {
    -webkit-appearance: none;

    &[value=left]:checked {
        // checkedとは逆の要素にむけたlabelのz-indexを上げる
        & ~ .ctrl_r {
            z-index: 10;
        }
        // background-positionで裸のオッサンの位置を変える
        & ~ .action {
            background-position: left top;
        }
    }
    &[value=right]:checked {
        & ~ .ctrl_l {
            z-index: 10;
        }
        & ~ .action {
            background-position: right top;
        }
    }
}


// 衝突やオッサンの方向などは.actionがすべてもつようにする
.action {
    position: absolute;
    z-index: 9;
    top: 410px;
    left: -50px;
    width: 400px;
    height: 150px;
    background-image: url(https://dl.dropbox.com/s/ef9pdfctl2fr12n/charactor.gif);
    background-repeat: no-repeat;
    background-position: left top;
    opacity: 1;
}


// 凶悪なサンタクロースたちのスタイル
// アニメで動かすので、とりあえず適当に配置してopacity:0に
.stage a[class*=block_] {
    position: absolute;
    z-index: 11;
    top: 105px;
    left: 55px;
    width: 190px;
    height: 70px;
    -webkit-appearance: none;
    background-image: url(https://dl.dropbox.com/s/63z2uiqq1060bbu/santa.png);
    background-repeat: no-repeat;
    background-size: auto 100%;
    opacity: 0;
}

// 衝突情報とdelay秒数のブレのセット
// 0 なら left, 1 なら right で衝突
$blocks:
        0 0,
        1 0,
        0 -1,
        ...;
// ディレイのベース秒数
$delay_base: 2.5;

// 衝突情報を元にスタイルを書き出す
@for $i from 1 through length($blocks) {
    $block: nth($blocks, $i);
    $angle: nth($block, 1);
    $delay: ($delay_base * $i) + nth($block, 2);
    $class_name: block_#{$i};

    // 左で衝突の場合、#state_lのcheckboxがcheckedであったらcrashのアニメを.action上で再生
    @if $angle == 0 {
        #state_l:checked ~ .#{$class_name}:hover ~ .action {
            @extend %crash;
        }
    }
    // 右で衝突の場合、#state_rのcheckboxがcheckedであったらcrashのアニメを.action上で再生
    @else {
        #state_r:checked ~ .#{$class_name}:hover ~ .action {
            @extend %crash;
        }
    }

    // $iの番号を元に.base_Nの要素に対して、ディレイと方向を設定する
    .#{$class_name} {
        -webkit-animation-delay: #{$delay}s;
        @if $angle == 0 {
            background-position: left top;
        }
        @else {
            background-position: right top;
        }
    }
}

このあたりは、たぶんCSS Programmerなら誰でもやってる(?) "~"セレクタ連結で状態を管理しながら画面表示を行う手法です。

また、SCSS内各所にてcreate-animeというmixinを呼んでいますが、実は3ヶ月ほど温めておいたものです。

その名の通り、animationを簡単に作れるようにしたものなんですが、ポイントとして設定されたFPSでアニメーションを書き出せるという点です。

// 従来のkeyframes
// 秒数あたりのパーセントで動いてちょっとキモイ。っていうか分かりづらい。(個人的な感想です)
@keyframes hogehoge {
    0% {
        //prop: value;
    }
    ...
    100% {
        //prop: value;
    }
}


// create-animeだと
@include create-anime(
    // アニメーション名を設定。placeholder形式ではき出す(%hogehoge)ので使用するセレクタ内で@extend %hogehogeする
    'hogehoge',
    // その他animationの設定値を設定
    (
        timing-function linear,
        iteration-count infinite
    ),
    // ここでいう1はFPSあたりの1フレームのこと。FPS: 24ならフレーム内秒(1/24)*1
    1, (
        background-position (center top)
    ),
    // 100フレームの意。FPS: 24ならフレーム内秒(1/24)*100
    // animation-durationは最後の設定フレームから自動的に設定される
    100, (
        background-position (center bottom)
    )
);

// 書き出されるとこんな感じ
.hogehoge {
  animation-name: kf-hogehoge;
  animation-duration: 4.16667s;
  animation-timing-function: linear;
  animation-iteration-count: infinite;
}
@keyframes kf-hogehoge {
  1% {
    background-position: center top;
  }
  100% {
    background-position: center bottom;
  }
}

ね、フレーム単位でカウントした方が分かりやすいし、他のアニメーションとも連携しやすそうじゃないですか?

突貫で作ったのでまだまだ機能不足ですが、create-animeはこれだけ別にしてまたの機会に。

おわり

今23:54です。何とか間に合いました。

クリスマスの予定など皆無かつ、当然のように明日も仕事ですが、みなさんは素敵なクリスマスをお過ごしくださいね。

ぼくは駅前で踏み絵でもしようと思います。

さて、明日は No_1026 さんの「ギャンブる」なお話です。お楽しみに!

tt.jsについてのアレコレ - 1

javascript tt.js

tt.jsというSelector Basedなjavascriptライブラリを書いたお話。

やったー!新しい車輪できたよー!!

既に @uupaa や @kyo_ago にtwitter上でRTされてはいるんですが、tt.jsというライブラリを書いてみました。

about tt.js

(特にスマホ案件で)jQueryほど機能はいらないしパフォーマンスも気になる...でもZeptoもjqMobiも結局さほど変わらないし...。

そんなことを思ったこと、男のコなら1度はありますよね?(たぶんない)

tt.jsは、とくに高速化へ注力して書いたスマートフォン向け(モダンブラウザ向け)jQuery Likeなライブラリです。

論より証拠として、ベンチマークをいくつか。

コンセプトというほど大したものはなかったんですが

  • jQueryの2倍速かつ、どれだけスピードが伸ばせるか
  • 使用環境は主にスマートフォン
  • カジュアルにDOMと遊べる
  • jQuerer(っていうのか分からないけど)にとって使用が億劫でない

みたいなものを目指しました。

一番の目標である速度に関しては、わりと達成はできたのかなと思っています。(一部メソッドはまだまだ改善の余地あり)

制作に当たっては、本家jQuery, Zepto, jqMobi

また @uupaa師匠作 mofmof.js, uupaa.js愛と勇気と缶ビールの@zentooさん作である riddle.js も参考にさせていただきました。

@kyo_ago大先生からpullreqもいただいており、ありがたいかぎりでございます。

簡単な使い方

jQuery likeと前述したとおり、jQueryっぽく使うことができます。

<div id="id-name">ピャー</div>

// DOMContentLoadedのタイミング、もしくはすでにロード後の場合即時実行される関数を登録
tt(function() {
    var ttDiv = tt("#id-name");

    // 結果の要素を得る
    ttDiv.get(); // return HTMLDivElement
    
    // 結果の要素にたいしてclassを追加する
    ttDiv.addClass("class-name"); // <div id="id-name" class="class-name">ピャー</div>
    
    // 結果の要素全てに関数を適用する
    ttDiv.each(function(index) { // @arg index Number: 要素の出現順インデックス
        var element = this; // @param this HTMLElement: eachにて、取得した要素はthisで渡されます
    });
});

注意点として、jQueryや他ライブラリで見られるこのような書き方には対応していません

<div class="first">ピャー</div>
<div class="second">ピェー</div>

// jQuery
$("div")[0]; // div.first
$("div")[1]; // div.second

// tt.js
tt("div")[0]; // undefined
tt("div").get(0); // div.first get()でも同様の結果
tt("div").get(1); // div.second

これに関しては、実装等々を語る時にあわせて述べたいと思います。

あとがき

これに関して経緯は色々とあるんですが、「javascript覚えるなら最初にライブラリ書いた方がいいよ」(@uupaa談)なんていうありがたいお言葉を元に

jsをきちんと触り初めてちょうど1年くらいになるので、オレオレ関数詰め合わせみたいなものと一緒に書いてみたというところ。

また、社内でも「jQueryほど機能はいらないけどZeptoもjQMobiもさほどパフォーマンス変わらないし…」という要望に応えたみたいな話もあったりなかったり。

弊社技術部勉強会ではすでに一度発表させていただいており

2012.10.26 19:27:33 <typester> BKすぎてすごい

というお褒めの(?)言葉もいただけて、大変ありがたく思っております。

細かい実装等々はまた追々。