みかづきブログ その3

3ヶ月つづけてみました。

Canvasで落書き 2.0.1

前回つくったものベジェ曲線にしようと試みていたんですが、点が多すぎると処理が大変なので、 この前つくったThrottleクラス をつかってmousemoveを間引くという地味なマイナーアップデートを施してみました。

JavaScript

(function(win, doc) {

    "use strict";
    
    win.Can = {};
    
})(this, document);

(function(win, doc, ns) {
    
    "use strict";
    
    function Throttle(opt_interval, opt_callback) {
        this._timer         = null;
        this._lastEventTime = 0;
        this._interval      = opt_interval || 500;
        this._callback      = opt_callback || function() {};
    }
    
    Throttle.prototype.setInterval = function(ms) {
        this._interval = ms;
    };
    
    Throttle.prototype.addEvent = function(fn) {
        this._callback = fn;
    };
    
    Throttle.prototype.fireEvent = function(opt_arg) {
        var that          = this,
            currentTime   = new Date() - 0,
            timerInterval = this._interval / 10;
        
        clearTimeout(that.timer);
        
        if (currentTime - that._lastEventTime > that._interval) {
            _fire();
        } else {
            that.timer = setTimeout(_fire, timerInterval);
        }
        
        function _fire() {
            that._callback.call(that, opt_arg || null);
            that._lastEventTime = currentTime;
        }
    };
    
    ns.Throttle = Throttle;
    
    
})(this, document, Can);

(function(win, doc, ns) {

    "use strict";

    var canvas         = doc.getElementById("canvas"),
        LINE_INTARVAAL = 100,
        FPS            = 30,
        START_EVENT    = "mousedown",
        MOVE_EVENT     = "mousemove",
        END_EVENT      = "mouseup";

    init();
    
    function init() {
        canvas.width  = win.innerWidth;
        canvas.height = win.innerHeight;
        addSketchEventForCanvas(canvas);
    }
    
    function addSketchEventForCanvas(elm) {
        var throttle     = new ns.Throttle(LINE_INTARVAAL, handleThrottleMoveEvent),
            ctx          = elm.getContext("2d"),
            positionList = [],
            index = 0;
        
        elm.addEventListener(START_EVENT, handleStartEvent, false);
        doc.addEventListener(END_EVENT,   handleEndEvent,   false);
        
        setInterval(sketch, 1000 / FPS);

        function handleThrottleMoveEvent(evt) {
            positionList[index].push({x: evt.offsetX, y: evt.offsetY});
        }
        
        function handleStartEvent(evt) {
            positionList.push([{x: evt.offsetX, y: evt.offsetY}]);
            elm.addEventListener(MOVE_EVENT, handleMoveEvent, false);
        }
        
        function handleMoveEvent(evt) {
            throttle.fireEvent(evt);
        }
        
        function handleEndEvent(evt) {
            positionList[index++].push({x: evt.offsetX, y: evt.offsetY});
            elm.removeEventListener(MOVE_EVENT, handleMoveEvent, false);
        }
        
        function sketch() {
            var objLength = positionList.length,
                pathLength,
                i, j;

            ctx.clearRect(0, 0, canvas.width, canvas.height);
            ctx.save();
                ctx.strokeStyle = "rgba(255, 25, 25, .5)";
                ctx.lineCap     = "round";
                ctx.lineJoin    = "miter";
                ctx.miterLimit  = 2;
                ctx.lineWidth   = 2;
                
                ctx.beginPath();

                for (i = 0; i < objLength; i++) {
                    pathLength = positionList[i].length;

                    for (j = 0; j < pathLength; j++) {
                        if (!j) {
                            ctx.moveTo(positionList[i][j].x, positionList[i][j].y);
                        } else {
                            ctx.lineTo(positionList[i][j].x, positionList[i][j].y);    
                        }
                    }
                }
            
                ctx.stroke();
            ctx.restore();
        }
    }

})(this, document, Can);

DEMO



地味な改修ですが、かなりデバッグしやすくなりました。
そしてベジェ曲線の導入には想像以上に手こずっています。
今回は以上です。