Mach3.laBlog

CSS3のbox-shadowでお絵かきアプリを書いてみたものの…

この記事は賞味期限切れです。(更新から1年が経過しています)

先日、CSS3のbox-shadowで描画されたモナリザが話題となりましたが、 インスパイアされて同じ手法でお絵かきアプリを作ったらどうなるか試してみました。

CSS3のbox-shadowでお絵かきアプリを書いてみたものの…

作ってみたもの

まずはデモから。当たり前ですが、box-shadowに対応していないブラウザでは動きません。

JS Bin

感想

作って動かしてみた率直な感想を申し上げると…そもそもこういう用途を想定していないと思うので、当然あまり捗りませんでした。 が、描かれる物の雰囲気は、これはこれで嫌いではないです。水墨画的な物が描けそう。

重さが加速する

Webkitはかなり軽快に動くのですが、Firefoxだとかなりもっさりした動きになります。IE9だとまだマシです。 そして、書けば書くほど重くなっていきます。 box-shadowを一点ずつどんどん重ねていっているわけですから、そりゃ当然重くなりますよね。

線を引きにくい

基本的にブラシで点描を繰り返している様な物なので、あまりはやく描こうとすると途切れて線になりません。 そういうブラシだと思うしかないでしょう。 間を補完するような感じに描画しようかとも思いましたが、むしろ味が損なわれる感じがしたので途中でやめました。

ライブラリ

書いてみたライブラリがこちら。別にやってる事はどうということはないです。 使い道は多分ないと思うのですが、使ってみたい方はお好きにお使いください。

ShadowCanvas : Drawing illustration with css box-shadow — Gist

/**
 * ShadowCanvas
 * 
 * Drawing illustration with css box-shadow
 *
 * @version 0.9
 * @author mach3ss
 * @require jQuery
 */
var ShadowCanvas = function(selector, option){

    // config
    this.option = $.extend({}, this.option, option);
    this.node = $.extend({}, this.node);

    // nodes
    this.node.container = $(selector);
    this.node.canvas = $("<div>")
    .css({position:"absolute"})
    .appendTo(this.node.container);

    // events
    this.node.container
    .on("mousemove", $.proxy(this._onMouseMove, this))
    .on("mousedown", $.proxy(this.start, this))
    .on("mouseleave mouseup", $.proxy(this.stop, this));
};
(function(fn){

    fn.boxShadowText = "{x}px {y}px {blur}px {size}px {color}";
    fn.drawing = false;

    fn.node = {
        container : null,
        canvas : null
    };

    fn.option = {
        color: "black",
        blur : 5,
        size : 5 
    };

    /**
     * Configure option or get the option value
     *
     * @param String key
     * @param Mixed value (optional)
     * @return Mixed
     */
    fn.config = function(key, value){
        if(this.option.hasOwnProperty(key)){
            if(typeof(value) !== "undefined"){
                this.option[key] = value;
                return this;
            } else {
                return this.option[key];
            }
        }
    };

    /**
     * Get css text for box-shadow
     * 
     * @param Integer x
     * @param Integer y
     * @return String
     */
    fn._getBoxShadowText = function(x, y){
        var o, callback;
        o = this.option;
        o.x = x;
        o.y = y;
        callback = function(a, b){
            return o[b];
        };
        return this.boxShadowText.replace((/\{(\w+)\}/g), callback);
    };

    /**
     * Draw the point with box-shadow
     * 
     * @param Integer x
     * @param Integer y
     * @return self
     */
    fn.draw = function(x, y){
        var shadow = this.node.canvas.css("boxShadow");
        shadow = shadow === "none" ? "" : "," + shadow ;
        shadow = this._getBoxShadowText(x, y) + shadow;
        this.node.canvas.css("boxShadow", shadow);
        return this;
    };


    /**
     * Start drawing
     *
     * @return self
     */
    fn.start = function(){
        this.drawing = true;
        return this;
    };

    /**
     * Stop drawing
     *
     * @return self
     */
    fn.stop = function(){
        this.drawing = false;
        return this;
    };

    fn._onMouseMove = function(e){
        var offset, x, y;

        if(! this.drawing){
            return;
        }

        offset = this.node.container.offset();
        x = e.clientX - offset.left + document.body.scrollLeft;
        y = e.clientY - offset.top + document.body.scrollTop;
        if(x < this.node.container.width() && y < this.node.container.height()){
            this.draw(x, y);
        }
    };

    /**
     * Clear all on canvas
     *
     * @return self
     */
    fn.clear = function(){
        this.node.canvas.css("boxShadow", "none");
        return this;
    };

    /**
     * Get css text of the illustration on canvas now
     *
     * @return String
     */
    fn.getCSS = function(){
        return this.node.canvas.css("boxShadow");
    };

}(ShadowCanvas.prototype));

使い方は、キャンバスにしたいボックス要素のセレクターを引数にしてnewするだけです。 各設定はconfigで。

var myCanvas = new ShadowCanvas("#my-canvas");
myCanvas.config("color", "black");
myCanvas.config("size", 8);
myCanvas.config("blur", 10);

まとめ

表現力は結構ありそうですが、実用的なアプリかと問われると…

cf) CSS3のbox-shadowだけで作られたモナリザ・・・ – かちびと.net

コメント

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

*