CSS3で疑似3D表現を実現するSprite3D.jsを触ってみた、その2

以前の記事で紹介しましたが、JavaScriptとCSS3だけで疑似的に3D表現を行うことができるSprite3D.jsを再びさわりましたので投稿します。

視差を利用して、立体的な表現を手に入れるパララックスも流行りましたが、もっと立体的な表現ができるSprite3Dによるトランジションは意外と効果的ではないかと思い作成しました。一見普通のコンテンツですが、リンクをクリックしたときの驚きは、パララックスをはじめてさわった時に勝るとも劣らないんではないかと思います。しかもパララックスだとFixedがまともに使えないスマフォでは再現がほとんど出来ないと思いますが、これはスマフォで問題なく表示可能です。実装も非常に簡単なので是非一度さわってみてください。

サンプル

20130604_img

20130604_img2

Sprite3Dとはあまり関係ないですが、実装にはTypeScriptを使用しました。TypeScriptはクラスベースでJavaScriptを構築出来るため非常に設計がしやすいのですが、あくまでクラスベースの記述をJavaScriptにコンパイルするだけですので、実際の機能は全て独自に実装する必要があります。ActionScriptにはMovieClipという機能満載のクラスがありましたが、TypeScriptで記述する場合は、jQuery等を基本使うことになるかと思います。今回は、TypeScriptを使ってSprite3Dの機能をラップして作成しました。

class Sprite3dItem implements IView {
    public id:string;
    public element:any;
    public children:any[];
    private $element:any;

    constructor(id:string) {
        this.id = id;
        this.element = Sprite3D.create(document.getElementById(id));
        this.children = [];
        this.$element = $("#" + id);
    }

    public addChild(target:IView, isUpdate:bool = true):void {
        var flg = true;
        var i = 0, max;
        for (i = 0, max = this.children.length; i < max; i = i + 1) {
            if (this.children[i].id == target.id) {
                flg = false;
                return;
            }
        }
        if (flg) {
            target.element.style.position = "absolute";
            target.element.style.top = 0;
            target.element.style.left = 0;
            target.element.style.display = "block";
            this.element.appendChild(target.element);
            this.children.push(target);
            if (isUpdate) {
                target.update();
            }
        }
    }

    public removeChild(target:IView):void {
        var flg = false;
        var arr = [];
        var i = 0, max;
        for (i = 0, max = this.children.length; i < max; i = i + 1) {
            if (this.children[i].id == target.id) {
                flg = true;
            } else {
                arr.push(this.children[i]);
            }
        }
        if (flg) {
            this.children = arr;
            this.element.removeChild(target.element);
        }
    }

    public update():void {
        this.element.update();
    }

    public setAlpha(num:number):void {
        this.$element.css({opacity: num});
    }

    public getAlpha():number {
        return this.$element.css("opacity");
    }

    public setX(num:number):void {
        this.element.x(num);
    }

    public getX():number {
        return this.element.x();
    }

    public setY(num:number, isUpdate:bool = true):void {
        this.element.y(num);
        if (isUpdate) {
            this.update();
        }
    }

    public getY():number {
        return this.element.y();
    }

    public setZ(num:number, isUpdate:bool = true):void {
        this.element.z(num);
        if (isUpdate) {
            this.update();
        }
    }

    public getZ():number {
        return this.element.z();
    }

    public setRotationX(num:number, isUpdate:bool = true):void {
        this.element.rotationX(num);
        if (isUpdate) {
            this.update();
        }
    }

    public getRotationX():number {
        return this.element.rotationX();
    }

    public setRotationY(num:number, isUpdate:bool = true):void {
        this.element.rotationY(num);
        if (isUpdate) {
            this.update();
        }
    }

    public getRotationY():number {
        return this.element.rotationY();
    }

    public setRotationZ(num:number, isUpdate:bool = true):void {
        this.element.rotationZ(num);
        if (isUpdate) {
            this.update();
        }
    }

    public getRotationZ():number {
        return this.element.rotationZ();
    }

    public getScale():number {
        return this.element.scale();
    }

    public setScale(num:number, isUpdate:bool = true):void {
        this.element.scale(num);
        if (isUpdate) {
            this.update();
        }
    }

    public setOrigin(x:number = 0, y:number = 0, z:number = 0, isUpdate:bool = true):void {
        this.element.origin(Math.floor(x), Math.floor(y), Math.floor(z));
        if (isUpdate) {
            this.update();
        }
    }

    public setPosition(x:number = 0, y:number = 0, z:number = 0, isUpdate:bool = true):void {
        this.element.position(x, y, z);
        if (isUpdate) {
            this.update();
        }
    }

    public setMove(x:number = 0, y:number = 0, z:number = 0, isUpdate:bool = true):void {
        this.element.move(x, y, z);
        if (isUpdate) {
            this.update();
        }
    }
}

TypeScriptはクラスベースで記述でき、コンパイル後のJavaScriptも非常に読みやすく、導入が容易なことが特徴です。ただ2013年6月時点では0.9が最新で、バージョンごとに仕様が異なるために、まだまだ今後の仕様変更をある程度覚悟して使う必要はあります。こういったモックアップ作成時には非常に重宝します。
TypeScriptに関しては改めてまとめたいと思いますが、ActionScriptになれた僕にとっては非常に使いやすいものでした。
ちなみにこちらのサイトが非常にわかりやすく説明されています。
TypeScript Quick Guide

話がはずれてしまいましたが、3D表現の機会がありましたらSprite3Dを試してみてください。