非公開 open2chOekakiEX

    @@ -34,9 +34,11 @@ var drawRedo = []; var layers = []; -var layerOnFlag = false; +var layerOnFlag = true; +//var layerOnFlag = false; initDrawTool(); +initLayerTool(); var show = $('#layerTool').next().children(); show.html("ctrl+←:UNDO<br/>ctrl+→:REDO<br/>" + show.html()); @@ -123,6 +125,40 @@ var br = $('<br>'); + var figureInput = $('<input>', { + id: 'figure', + type: 'radio', + name: 'pmode' + }); + var figureLabel = $('<label>', { + for: 'figure' + }); + var figureText = $('<b>', { + text: ' 図形:' + }); + figureText.appendTo(figureLabel); + + var figure = ['-','□','■','○','●']; + var figureSelect = $('<select>', { + id: 'figureType' + }); + for(var i in figure){ + $('<option>', { + value: i, + text: figure[i], + }).appendTo(figureSelect); + } + + var goButton = $('<input>', { + type: 'button', + value: '進', + id: 'goButton', + click: function(){ + changeAction(drawRedo, canvas.actions); + canvas.redraw(); + } + }); + $('#backButton') .before(fillInput) .before(fillLabel) @@ -134,7 +170,11 @@ .before(boldCheck) .before(italicText) .before(italicCheck) - .before(br); + .before(br) + .before(figureInput) + .before(figureLabel) + .before(figureSelect) + .after(goButton); var mojiA = $('<a>', { href: '#sketch', @@ -144,9 +184,14 @@ href: '#sketch', 'data-tool': 'fill' }); + var figureA = $('<a>', { + href: '#sketch', + 'data-tool': 'figure' + }); mojiInput.click(function(){$("[data-tool=moji]").click()}); fillInput.click(function(){$("[data-tool=fill]").click()}); - $('.tools').after(fillA).after(mojiA); + figureInput.click(function(){$("[data-tool=figure]").click()}); + $('.tools').after(fillA).after(mojiA).after(figureA); var exportButton = $('<input>', { @@ -168,19 +213,13 @@ actionStringToColor(actionToString()); }); - var importButton = $('<input>', { - id: 'importButton', - type: 'button', - value: '再生' + var tmpCanvas = $('<canvas>').attr({ + id: 'tmpCanvas', + width: canvas.el.width, + height: canvas.el.height, + style: 'position:absolute; z-index:-1' }); - -// var tmpCanvas = $('<canvas>').attr({ -// id: 'tmpCanvas', -// width: canvas.el.width, -// height: canvas.el.height, -// style: 'display: none' -// }); -// $('#sketch').before(tmpCanvas); + $('#sketch').before(tmpCanvas); var layerTool = $('<div>', { id: 'layerTool', @@ -200,7 +239,7 @@ layerOnButton.remove(); } }); - layerTool.append(layerText).append(layerOnButton); +// layerTool.append(layerText).append(layerOnButton); var mergeLayerButton = $('<input>', { @@ -310,21 +349,6 @@ } function createPreview(){ -/* var img = new Image(); - img.id = 'preview' + (layers.length); - img.value = layers.length; - img.width = canvas.el.width * PREVIEW_SIZE; - img.height = canvas.el.height * PREVIEW_SIZE; - img.setAttribute('style', 'border:1pt solid #999; background-image:url(http://open2ch.net/image/oekaki/background.png)'); - img.displayed = 1; - $('#previewBox').append(img); - - $('#' + img.id).click( - function(){ - selectLayer(img.value); - } - ); -*/ var preview = $('<canvas>').attr({ id: 'preview' + (layers.length), width: canvas.el.width, @@ -347,7 +371,6 @@ $(this).css('border', '2pt solid #DAA'); } this.selected = true; - console.log(this.selected); }else{ if(this.displayed){ $(this).css('border', '2pt solid #777'); @@ -371,13 +394,6 @@ } function updatePreview(){ -/* - var src = layers[canvas.layerNum].canvas.toDataURL(); - var preview = $('#preview' + canvas.layerNum)[0]; - if(preview.src != src){ - preview.src = src; - } -*/ var preview = $('#preview' + canvas.layerNum)[0]; var context = preview.getContext('2d'); var imageData = canvas.context.getImageData(0, 0, canvas.el.width, canvas.el.height); @@ -419,11 +435,7 @@ layers[oldLayerNum] = layers[newLayerNum]; layers[newLayerNum] = tmpLayer; canvas.actions = layers[oldLayerNum].actions; -/* - var tmpPreviewSrc = $('#preview' + oldLayerNum)[0].src; - $('#preview' + oldLayerNum)[0].src = $('#preview' + newLayerNum)[0].src; - $('#preview' + newLayerNum)[0].src = tmpPreviewSrc; -*/ + var oldCtx = $('#preview' + oldLayerNum)[0].getContext('2d'); var newCtx = $('#preview' + newLayerNum)[0].getContext('2d'); var oldImageData = oldCtx.getImageData(0, 0, canvas.el.width, canvas.el.height); @@ -516,8 +528,8 @@ function changeCanvas(targetCanvas){ var orgCanvas = canvas.el; var orgCtx = canvas.context; - var orgBgcolor = canvas.bgcolor; - var orgBaseImageURL = canvas.baseImageURL; +// var orgBgcolor = canvas.bgcolor; +// var orgBaseImageURL = canvas.baseImageURL; // canvas.bgcolor = 'rgba(0, 0, 0, 0)'; // canvas.baseImageURL = ''; // canvas.baseImageCache = ''; @@ -772,6 +784,107 @@ }); } +$.sketch.tools.figure = { + onEvent: function(e) { + switch (e.type) { + case 'mousedown': + case 'touchstart': + startPreviewing(e); + break; + case 'mouseup': + case 'mouseout': + case 'mouseleave': + case 'touchend': + case 'touchcancel': + stopPreviewing(e); + } + if(canvas.preview){ + previewing(e); + } + }, + draw: function(action){ + drawFigure(action, canvas.context); + } +} + +function startPreviewing(e){ + var pageX = e.pageX; + var pageY = e.pageY; + var offsetX = $('#sketch').offset().left; + var offsetY = $('#sketch').offset().top; + var x = Math.floor(pageX - offsetX); + var y = Math.floor(pageY - offsetY); + + canvas.preview = { + x: x, + y: y, + tool: 'figure', + figureType: $('#figureType').val(), + color: canvas.color, + size: canvas.size + }; +} + +function stopPreviewing(e){ + canvas.actions.push(canvas.preview); + canvas.preview = null; + var tmpCtx = $('#tmpCanvas')[0].getContext('2d'); + tmpCtx.clearRect(0, 0, canvas.el.width, canvas.el.height); + canvas.redraw(); + if(layerOnFlag){updatePreview();} +} + +function previewing(e){ + var pageX = e.pageX; + var pageY = e.pageY; + var offsetX = $('#sketch').offset().left; + var offsetY = $('#sketch').offset().top; + var x = Math.floor(pageX - offsetX); + var y = Math.floor(pageY - offsetY); + + canvas.preview.w = x - canvas.preview.x; + canvas.preview.h = y - canvas.preview.y; + + var tmpCtx = $('#tmpCanvas')[0].getContext('2d'); + tmpCtx.clearRect(0, 0, canvas.el.width, canvas.el.height); + drawFigure(canvas.preview, tmpCtx); +} + +function drawFigure(action, context){ + switch(action.figureType){ + case '0': //- + context.beginPath(); + context.lineWidth = action.size; + context.lineCap = 'butt'; + context.strokeStyle = action.color; + context.moveTo(action.x, action.y); + context.lineTo(action.x + action.w, action.y + action.h); + context.stroke(); + break; + case '1': //□ + context.beginPath(); + context.lineWidth = action.size; + context.lineCap = 'butt'; + context.strokeStyle = action.color; + context.strokeRect(action.x, action.y, action.w, action.h); + break; + case '2': //■ + context.beginPath(); + context.lineCap = 'butt'; + context.fillStyle = action.color; + context.fillRect(action.x, action.y, action.w, action.h); + break; + case '3': //○ + context.beginPath(); + context.lineWidth = action.size; + context.lineCap = 'butt'; + context.strokeStyle = action.color; + ctx.beginPath(); +   ctx.arc(70, 70, 60, 0, Math.PI*2, false); + ctx.stroke(); + } +} + function actionToString(){ var actionString = ''; var actDel = '!'; @@ -1015,12 +1128,7 @@ return (padding + string).slice(-length); } -function keydownEvent(e, keyNum, popList, pushList){ - if(e.which === keyNum && e.ctrlKey && popList.length > 0){ - pushList.push(popList.pop()); - canvas.redraw(); - } -} + $(document).keydown(function(e){ keydownEvent(e, 37, canvas.actions, drawRedo); @@ -1029,6 +1137,25 @@ if(layerOnFlag){updatePreview();} }); + +$("#backButton").unbind(); +$("#backButton").click(function() { + changeAction(canvas.actions, drawRedo); + canvas.redraw(); +}); + +function keydownEvent(e, keyNum, popList, pushList){ + if(e.which === keyNum && e.ctrlKey && popList.length > 0){ + changeAction(popList, pushList); + canvas.redraw(); + } +} + +function changeAction(popList, pushList){ + pushList.push(popList.pop()); +} + + canvas.stopPainting = function(){ if (this.action) { this.actions.push(this.action);
  • /*
     * @title open2chOekakiEX
     * @description おーぷん2ちゃんお絵かき機能拡張ブックマークレット 
     * @private
     */
    
    /*
    【更新履歴】
    Ver1.0.0  2014/03/29    文字入力機能追加
    Ver1.1.0  2014/03/29    お絵かき機能ツールメニュー内に文字入力機能を追加 文字サイズ指定追加
    Ver1.2.0  2014/03/30    フォント指定、修飾指定追加
    Ver1.3.0  2014/03/30    線描画と文字入力のUNDO/REDO機能追加 イタリックが効かないバグ修正
    Ver2.0.0  2014/03/31    塗りつぶし機能追加
    Ver2.1.0  2014/03/31    塗りつぶし機能にUNDO/REDO機能追加
    Ver2.1.1  2014/03/31    IE、Chromeで塗りつぶしが効かないバグ修正
    Ver2.2.0  2014/04/01    背景色以外の色も塗りつぶせるように修正
    Ver2.3.0  2014/04/01    透明度を指定して塗りつぶせるように修正
    Ver2.4.0  2014/04/02    文字入力でフォントの直接指定&改行入力&縦書出力に対応
    Ver3.0.0  2014/04/05    お絵かき再生機能追加
    Ver3.1.0  2014/04/06    お絵かき再生機能のエクスポート方式をテキストから画像埋め込みに変更
    Ver3.2.0  2014/04/10    お絵かき再生機能で塗りつぶしと消しゴムが再生できるように修正 線を引くときにちらつくバグを修正
    Ver4.0.0  2014/04/19    レイヤ機能追加
    Ver4.1.0  2014/04/20    レイヤの表示/非表示切替機能追加 最前面のレイヤしか投稿できないバグ修正 レイヤの移動に関するバグ修正 コラボするとレイヤの重なりがおかしくなるバグ修正
    Ver4.1.1  2014/04/24    IE10未満で起動できないバグを修正
    Ver4.1.2  2014/04/28    IEでプレビューが正常に表示できないバグを修正
    Ver4.2.0  2014/04/29    レイヤ機能をデフォルトではオフに変更 レイヤ機能オン時の性能向上
    Ver4.2.1  2014/04/29    絵が投稿できないバグを修正
    Ver4.3.0  2014/04/30    線の太さ、文字の大きさを追加
    */
    
    var PREVIEW_SIZE = 0.2;
    
    var canvas = $('#sketch').sketch();
    var drawRedo = [];
    var layers = [];
    
    var layerOnFlag = true;
    //var layerOnFlag = false;
    
    initDrawTool();
    initLayerTool();
    
    var show = $('#layerTool').next().children();
    show.html("ctrl+←:UNDO<br/>ctrl+→:REDO<br/>" + show.html());
    
    
    function initDrawTool(){
        var penSizeSelect = $('#psize');
        penSizeSelect.children().remove();
        var penSize = [0.5, 1, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 24, 28, 32, 36, 40, 48, 56, 64, 72, 80, 100];
        for(var i in penSize){
            $('<option>', {
                value: penSize[i],
                text: penSize[i],
                selected: (i==2)?true:false
            }).appendTo(penSizeSelect);
        }
    
        var fillInput = $('<input>', {
            id: 'fill',
            type: 'radio',
            name: 'pmode'
        });
        var fillLabel = $('<label>', {
            for: 'fill'
        });
        var fillImg = $('<img>', {
            id: 'fillImg',
            src: 'http://image.open2ch.net/image/oekaki/nuri.png',
        }).appendTo(fillLabel);
    
        var mojiInput = $('<input>', {
            id:'moji',
            type:'radio',
            name:'pmode'
        });
        var mojiText = $('<b>',{
            text:'[A]:'
        });
        var mojiLabel = $('<label>', {
            for:'moji'
        });
        mojiText.appendTo(mojiLabel);
    
        var size = [4, 8, 10, 12, 14, 16, 18, 20, 24, 28, 32, 36, 40, 48, 56, 64, 72, 80, 100];
        var mojiSelect = $('<select>', {
            id: 'mojiSize'
        });
        for(var i in size){
            $('<option>', {
                value: size[i],
                text: size[i],
                selected: (i==7)?true:false
            }).appendTo(mojiSelect);
        }
    
        var font = ['ゴシック','明朝','筆記体','装飾','等幅'];
        var fontSelect = $('<select>', {
            id: 'mojiFont'
        });
        for(var i in font){
            $('<option>', {
                value: i,
                text: font[i],
            }).appendTo(fontSelect);    
        }
    
        var boldText = $('<b>', {
            text: ' B:'
        });
        var boldCheck = $('<input>', {
            id: 'mojiBold',
            type: 'checkbox',
            value: 'bold'
        });
    
        var italicText = $('<i>', {
            text: ' I:'
        });
        var italicCheck = $('<input>', {
            id: 'mojiItalic',
            type: 'checkbox',
            value: 'italic'
        });
    
        var br = $('<br>');
    
        var figureInput = $('<input>', {
            id: 'figure',
            type: 'radio',
            name: 'pmode'
        });
        var figureLabel = $('<label>', {
            for: 'figure'
        });
        var figureText = $('<b>', {
            text: ' 図形:'
        });
        figureText.appendTo(figureLabel);
    
        var figure = ['-','□','■','○','●'];
        var figureSelect = $('<select>', {
            id: 'figureType'
        });
        for(var i in figure){
            $('<option>', {
                value: i,
                text: figure[i],
            }).appendTo(figureSelect);    
        }
    
        var goButton = $('<input>', {
            type: 'button',
            value: '進',
            id: 'goButton',
            click: function(){
                changeAction(drawRedo, canvas.actions);
                canvas.redraw();
            }
        });
    
        $('#backButton')
        .before(fillInput)
        .before(fillLabel)
        .before(mojiInput)
        .before(mojiLabel)
        .before(mojiSelect)
        .before(fontSelect)
        .before(boldText)
        .before(boldCheck)
        .before(italicText)
        .before(italicCheck)
        .before(br)
        .before(figureInput)
        .before(figureLabel)
        .before(figureSelect)
        .after(goButton);
    
        var mojiA = $('<a>', {
            href: '#sketch',
            'data-tool': 'moji'
        });
        var fillA = $('<a>', {
            href: '#sketch',
            'data-tool': 'fill'
        });
        var figureA = $('<a>', {
            href: '#sketch',
            'data-tool': 'figure'
        });
        mojiInput.click(function(){$("[data-tool=moji]").click()});
        fillInput.click(function(){$("[data-tool=fill]").click()});
        figureInput.click(function(){$("[data-tool=figure]").click()});
        $('.tools').after(fillA).after(mojiA).after(figureA);
    
    
        var exportButton = $('<input>', {
            id: 'exportButton',
            type: 'button',
            value: '出力'
        });
        var importButton = $('<input>', {
            id: 'importButton',
            type: 'button',
            value: '再生'
        });
        //$('#saveButton').after(importButton).after(exportButton);
    
        importButton.click(function(){
           playback(stringToAction(colorToActionString()), 10);
        });
        exportButton.click(function(){
            actionStringToColor(actionToString());
        });
    
        var tmpCanvas = $('<canvas>').attr({
            id: 'tmpCanvas',
            width: canvas.el.width,
            height: canvas.el.height,
            style: 'position:absolute; z-index:-1'
        });
        $('#sketch').before(tmpCanvas);
    
        var layerTool = $('<div>', {
            id: 'layerTool',
            align: 'left',
            style: 'background:#ccc;padding:2px;font-size:9pt'
        });
        var layerText = $('<b>', {
            text: '[レイヤ]:'
        });
        var layerOnButton = $('<input>', {
            id: 'layerOnButton',
            type: 'button',
            value: '機能ON',
            click: function(){
                layerOnFlag = true;
                initLayerTool();
                layerOnButton.remove();
            }
        });
    //    layerTool.append(layerText).append(layerOnButton);
    
    
        var mergeLayerButton = $('<input>', {
            id: 'mergeLayerButton',
            type: 'button',
            value: '結合',
            click: function(){mergeLayer()}
        });    $('#_canvas').after(layerTool);
    //    layerTool.append(mergeLayerButton);
    }
    
    function initLayerTool(){
        var layerTool = $('#layerTool');
        
        var addLayerButton = $('<input>', {
            id: 'addLayerButton',
            type: 'button',
            value: '追加',
            click: function(){addLayer()}
        });
        
        var displayButton= $('<input>', {
            id: 'displayButton',
            type: 'button',
            value: '表示',
            click: function(){changeDisplay()}
        });
       
        var changeLayerLeftButton= $('<input>', {
            id: 'changeLayerLeftButton',
            type: 'button',
            value: '←',
            click: function(){changeLayer(canvas.layerNum-1)}
        });
        
        var changeLayerRightButton = $('<input>', {
            id: 'changeLayerRightButton',
            type: 'button',
            value: '→',
            click: function(){changeLayer(canvas.layerNum+1)}
        });
        
        var mergeLayerButton = $('<input>', {
            id: 'mergeLayerButton',
            type: 'button',
            value: '結合',
            click: function(){mergeLayer()}
        });
        
        var previewBox = $('<div>', {
            id: 'previewBox',
            align: 'left'
        });
    
        layerTool
        .append(addLayerButton)
        .append(displayButton)
        .append(changeLayerLeftButton)
        .append(changeLayerRightButton)
    //    .append(mergeLayerButton)
        .append(previewBox);
    
        initLayer();
    }
    
    function initLayer(){
        createLayer();
        layers.push({
            actions:[]
        });
        $('#layerCanvas0')[0].style.backgroundImage = 'url(http://open2ch.net/image/oekaki/background.png)';
        sketch.style.backgroundImage='none';
        
        createLayer();
        createPreview();
        layers.push({
            canvas:$('#layerCanvas1')[0],
            context:$('#layerCanvas1')[0].getContext('2d'),
        //    bgcolor:canvas.bgcolor,
            bgcolor:'rgba(0, 0, 0, 0)',
            baseImageURL:canvas.baseImageURL,
            actions:canvas.actions
        });
        canvas.layerNum = 1;
        canvas.actions = [];
        canvas.bgcolor = 'rgba(0, 0, 0, 0)';
        canvas.baseImageURL = '';
        canvas.baseImageCache = '';
        canvas.redraw();
        
        canvas.el = layers[1].canvas;
        canvas.baseImageURL = layers[1].baseImageURL;
        canvas.baseImageCache = '';
        canvas.actions = layers[1].actions;
        updatePreview();
        selectLayer(canvas.layerNum);
    }
    
    function createLayer(){
        var layerCanvas = $('<canvas>').attr({
            id: 'layerCanvas' + layers.length,
            width: canvas.el.width,
            height: canvas.el.height,
            style: 'position:absolute; z-index:' + (layers.length-100)
        });
        $('#sketch').before(layerCanvas);
    }
    
    function createPreview(){
        var preview = $('<canvas>').attr({
            id: 'preview' + (layers.length),
            width: canvas.el.width,
            height: canvas.el.height,
            value: layers.length,
            style: 'border:1pt solid #999; background-image:url(http://open2ch.net/image/oekaki/background.png); width:' + canvas.el.width * PREVIEW_SIZE + '; height:' + canvas.el.height * PREVIEW_SIZE,
        });
        preview.click(function(){selectLayer(preview[0].value)});
        preview[0].displayed = true;
        $('#previewBox').append(preview);
    }
    
    function selectLayer(newLayerNum ){
        var oldLayerNum = canvas.layerNum;
        $('canvas[id^=preview]').each(function(i){
            if((i+1) == newLayerNum){
                if(this.displayed){
                    $(this).css('border', '2pt solid #D33');
                }else{
                    $(this).css('border', '2pt solid #DAA');
                }
                this.selected = true;
            }else{
                if(this.displayed){
                    $(this).css('border', '2pt solid #777');
                }else{
                    $(this).css('border', '2pt solid #BBB');
                }
                this.selected = false;
            }
        });
        canvas.layerNum = newLayerNum;
        layers[oldLayerNum].actions = canvas.actions;
        layers[oldLayerNum].bgcolor = canvas.bgcolor;
    //    layers[oldLayerNum].baseImageURL = canvas.baseImageURL;
        canvas.el = layers[newLayerNum].canvas;
        canvas.bgcolor = layers[newLayerNum].bgcolor;
        canvas.baseImageURL = layers[newLayerNum].baseImageURL;
        canvas.baseImageCache = '';
        canvas.actions = layers[newLayerNum].actions;
        canvas.redraw();    
    //    updatePreview();
    }
    
    function updatePreview(){
        var preview = $('#preview' + canvas.layerNum)[0];
        var context = preview.getContext('2d');
        var imageData = canvas.context.getImageData(0, 0, canvas.el.width, canvas.el.height);
        context.putImageData(imageData, 0, 0);
    }
    
    function addLayer(){
        var oldLayerNum = canvas.layerNum;
    
        createLayer();
        createPreview();
    
        layers.push({
            canvas:$('#layerCanvas' + (layers.length))[0],
            context:$('#layerCanvas' + (layers.length))[0].getContext('2d'),
            bgcolor:'rgba(0, 0, 0, 0)',
            actions:[]
        });
        var newLayerNum = layers.length-1;
        canvas.layerNum = newLayerNum;
        layers[oldLayerNum].actions = canvas.actions;
        canvas.el = layers[newLayerNum].canvas;
        canvas.actions = layers[newLayerNum].actions;
        canvas.redraw();
        updatePreview();
        selectLayer(newLayerNum);
    }
    
    function changeLayer(newLayerNum){
        if(newLayerNum <= 0 || newLayerNum > layers.length-1){return}
    
        var oldLayerNum = canvas.layerNum;
    
        var tmpZIndex = layers[oldLayerNum].canvas.style.zIndex;
        layers[oldLayerNum].canvas.style.zIndex = layers[newLayerNum].canvas.style.zIndex;
        layers[newLayerNum].canvas.style.zIndex = tmpZIndex;
    
        var tmpLayer = layers[oldLayerNum];
        layers[oldLayerNum] = layers[newLayerNum];
        layers[newLayerNum] = tmpLayer;
        canvas.actions = layers[oldLayerNum].actions;
    
        var oldCtx = $('#preview' + oldLayerNum)[0].getContext('2d');
        var newCtx = $('#preview' + newLayerNum)[0].getContext('2d');
        var oldImageData = oldCtx.getImageData(0, 0, canvas.el.width, canvas.el.height);
        var newImageData = newCtx.getImageData(0, 0, canvas.el.width, canvas.el.height);
        oldCtx.putImageData(newImageData, 0, 0);
        newCtx.putImageData(oldImageData, 0, 0);
    
        var tmpPreviewDisplayed = $('#preview' + oldLayerNum)[0].displayed;
        $('#preview' + oldLayerNum)[0].displayed = $('#preview' + newLayerNum)[0].displayed;
        $('#preview' + newLayerNum)[0].displayed = tmpPreviewDisplayed;
    
        canvas.el = layers[oldLayerNum].canvas;
        canvas.bgcolor = layers[oldLayerNum].bgcolor;
        canvas.baseImageURL = layers[oldLayerNum].baseImageURL;
        canvas.baseImageCache = '';
        selectLayer(newLayerNum);
    }
    
    function changeDisplay(){
        $('canvas[id^=preview]').each(function(i){
            if(this.selected){
                if(this.displayed){
                    $(this).css('border', '2pt solid #D99');
                    layers[i+1].canvas.style.display = 'none';
                    this.displayed = false;
                }else{
                    $(this).css('border', '2pt solid #D33');
                    layers[i+1].canvas.style.display = '';
                    this.displayed = true;
                }
            }
        });
    }
    
    
    var fillCanvas;
    var seeds;
    
    $.sketch.tools.fill= {
        onEvent: function(e) {
          switch (e.type) {
            case 'mousedown':
            case 'touchstart':
              fill(e);
            break;
          }
        },
        draw: function(action){
            if(!action.fill && canvas.filling){
                return;
            }else if(!canvas.filling){
                canvas.filling = true;
    
    //            var tmpCanvas = $('<canvas>').attr({
    //                width: canvas.el.width,
    //                height: canvas.el.height,
    //            })[0];
    //            var tmpCtx = tmpCanvas.getContext('2d');
    //            var orgCanvas = changeCanvas(tmpCanvas);
    //            canvas.redraw();
    
    //            fillCanvas = tmpCtx.getImageData(0, 0, tmpCanvas.width, tmpCanvas.height);
                fillCanvas = canvas.context.getImageData(0, 0, canvas.el.width, canvas.el.height);
                var fillColor = action.fillColor;
                var targetColor = getRGBA(action.x, action.y);
                seeds = [{
                     'x':Number(action.x),
                     'y':Number(action.y)
                }];
        
                //var start = new Date();
                while(seeds.length > 0){
                   var seed = seeds.shift();
                    paint(seed.x, seed.y, fillColor, targetColor);
                }
                //var end = new Date();
                //console.log(end - start + 'msec');
                
    //            tmpCtx.putImageData(fillCanvas, 0, 0);
                //action.fill = tmpCanvas;
                action.fill = fillCanvas;
    //            restoreCanvas(orgCanvas);
                canvas.filling = false;
            }
            //canvas.context.drawImage(action.fill, 0, 0, canvas.el.width, canvas.el.height);
            canvas.context.putImageData(action.fill, 0, 0);
        }
    }
    
    function changeCanvas(targetCanvas){
        var orgCanvas = canvas.el;
        var orgCtx = canvas.context;
    //    var orgBgcolor = canvas.bgcolor;
    //    var orgBaseImageURL = canvas.baseImageURL;
    //    canvas.bgcolor = 'rgba(0, 0, 0, 0)';
    //    canvas.baseImageURL = '';
    //    canvas.baseImageCache = '';
        canvas.el = targetCanvas;
    
        return {
            canvas: orgCanvas,
            context: orgCtx,
    //        bgcolor: orgBgcolor,
    //        baseImageURL: orgBaseImageURL
        }
    }
    
    function restoreCanvas(orgCanvas){
        canvas.el = orgCanvas.canvas;
        canvas.context = orgCanvas.context;
    //    canvas.bgcolor = orgCanvas.bgcolor;
    //    canvas.baseImageURL = orgCanvas.baseImageURL;
    }
    
    function fill(e){
        var pageX = e.pageX;
        var pageY = e.pageY;
        var offsetX = $('#sketch').offset().left;
        var offsetY = $('#sketch').offset().top;
        var x = Math.floor(pageX - offsetX);
        var y = Math.floor(pageY - offsetY);
    
        var fillRGBA = canvas.color.match(/(\d|\.)+/g);
        var alpha;
        if(fillRGBA[3] == undefined){
            alpha = 255;
        }else{
            alpha = alphaToInt(fillRGBA[3]);
        }
    
        var fillColor = ((Number(fillRGBA[0]) << 24) + (Number(fillRGBA[1]) << 16) + (Number(fillRGBA[2]) << 8) + alpha)>>>0;
        //var targetColor = getRGBA(x, y);
    
        canvas.actions.push({
            x: x,
            y: y,
            tool: canvas.tool,
            fillColor: fillColor
        });
    
        canvas.redraw();
        if(layerOnFlag){updatePreview();}
    }
    
    function paint(x, y, fillColor, targetColor){
        var color = getRGBA(x, y);
        if(color == fillColor){
            return;
        }
        fillRGBA(x, y, fillColor);
        
        var rightX = x + 1;
        while(rightX < fillCanvas.width){
            var color = getRGBA(rightX, y);
            if(color == targetColor){
                fillRGBA(rightX, y, fillColor);
            }else{
                break;
            }
            rightX++;
        }
        
        var leftX = x -1;
        while(leftX >= 0){
            var color = getRGBA(leftX, y);
            if(color == targetColor){
                fillRGBA(leftX, y, fillColor);
            }else{
                break;
            }
            leftX--;
        }
        
        if(y -1 >= 0){
            scanSeed(leftX, rightX, y-1, targetColor);
        }
        if(y + 1 < fillCanvas.height){
            scanSeed(leftX, rightX, y+1, targetColor);
        }
    }
    
    function scanSeed(leftX, rightX, y, targetColor){
        var seed = false;
    
        for(var x = leftX + 1; x < rightX; x++){
            var color = getRGBA(x, y);
            if(color == targetColor){
                seed = true;
            }else if(seed){
                seeds.push({"x":x - 1, "y":y});
                seed = false;
            }
        }
        if(seed){
            seeds.push({"x":rightX - 1, "y":y});
        }
    }
    
    function fillRGBA(x, y, color) {
        var img = fillCanvas.data;
        var w = fillCanvas.width;
        var h = fillCanvas.height;
        var p = ((w * y) + x) * 4;
        img[p]   = (color & 0xFF000000) >>> 24;
        img[p+1] = (color & 0xFF0000) >> 16;
        img[p+2] = (color & 0xFF00) >> 8;
        img[p+3] = color & 0xFF;
    }
    
    function fillRGB(x, y, color) {
        var img = fillCanvas.data;
        var w = fillCanvas.width;
        var h = fillCanvas.height;
        var p = ((w * y) + x) * 4;
        img[p]   = (color & 0xFF0000) >> 16;
        img[p+1] = (color & 0xFF00) >> 8;
        img[p+2] = color & 0xFF;
        img[p+3] = 0xFF;
    }
    
    function getRGBA(x, y){
        var img = fillCanvas.data;
        var w = fillCanvas.width;
        var h = fillCanvas.height;
        var p = ((w * y) + x) * 4;
        return ((img[p] << 24) + (img[p+1] << 16) + (img[p+2] << 8) + img[p+3])>>>0;
    }
    
    function getRGB(x, y){
        var img = fillCanvas.data;
        var w = fillCanvas.width;
        var h = fillCanvas.height;
        var p = ((w * y) + x) * 4;
        return ((img[p] << 16) + (img[p+1] << 8) + (img[p+2]));
    }
    function getRGBAString(color){
        return 'rgba('
        + (color & 0xFF000000) >>> 24 + ', ' 
        + (color & 0xFF0000) >> 16 + ', '
        + (color & 0xFF00) >> 8 + ', '
        + (color & 0xFF) + ')';
    }
    function getRGBString(color){
        return 'rgb('
        + ((color & 0xFF0000) >> 16) + ', '
        + ((color & 0xFF00) >> 8) + ', '
        + (color & 0xFF) + ')';
    }
    function alphaToInt(floatAlpha){
        return Math.floor(Number(floatAlpha * 255));
    }
    
    function alphaToFloat(intAlpha){
        return Math.floor(intAlpha / 255 * 100) * 100;
    }
    
    function drawText(e){
        var pageX = e.pageX;
        var pageY = e.pageY;
        var offsetX = $('#sketch').offset().left;
        var offsetY = $('#sketch').offset().top;
        var x = Math.floor(pageX - offsetX);
        var y = Math.floor(pageY - offsetY);
        var context = canvas.context;
        
        var text = window.prompt("文字を入力。");
        if(!text){
            text= '';
        }
        var str = text.match(/^(kyaha!|\:v|\!)(.*)/i);
        var mode = '';
        if(str != null){
            var mode = str[1];
            var text = str[2];
        }
        str = text.match(/^(?:usa|\[)(.*)(?:min|\])(.*)/i);
        var mojiFont;
        if(str != null && str[1] != null){
            mojiFont = str[1];
            text = str[2];
        }else{
            var fontFamily = ['sans-serif','serif','cursive','fantasy','monospace'];
            mojiFont =  fontFamily[$('#mojiFont').val()];
        }
        text = text.replace(/nana|\\n/g, "\n");
    
        
        var mojiSize = $('#mojiSize').val();
        
        if($('#mojiBold:checked').val()){
           var mojiBold = $('#mojiBold:checked').val() + ' ';
        }else{
           var mojiBold = ' ';
        }
        
        if($('#mojiItalic:checked').val()){
           var mojiItalic = $('#mojiItalic:checked').val() + ' ';
        }else{
           var mojiItalic = ' ';
        }
    
        canvas.actions.push({
            x: x,
            y: y,
            tool: canvas.tool,
            color: canvas.color,
            font: mojiBold + mojiItalic + mojiSize + 'px ' + mojiFont,
            mode: mode,
            text: text
        });
    
        canvas.redraw();
        updatePreview();
    }
    
    $.sketch.tools.moji = {
        onEvent: function(e) {
          switch (e.type) {
            case 'mousedown':
            case 'touchstart':
              drawText(e);
            break;
          }
        },
        draw: function(action){
            canvas.context.fillStyle = action.color;
            canvas.context.font = action.font;
            canvas.context.baseline = 'top';
            fillText(canvas.context, action.mode, action.text, action.x, action.y);
        }
    }
    
    function fillText(context, mode, text, x, y){
        var lines = text.split('\n');
        var h = context.measureText("あ").width;
        jQuery.each(lines, function(i, line) {
            if(mode == ''){
                context.textAlign = 'left'
                context.fillText(this, x, y+h*i);
            }else{
                jQuery.each(line, function(j, char){
                    context.textAlign = 'center';
                    context.fillText(char, x - h*i, y+h*j);
                });
            }
        });
    }
    
    $.sketch.tools.figure = {
        onEvent: function(e) {
            switch (e.type) {
                case 'mousedown':
                case 'touchstart':
                    startPreviewing(e);
                    break;
                case 'mouseup':
                case 'mouseout':
                case 'mouseleave':
                case 'touchend':
                case 'touchcancel':
                    stopPreviewing(e);
            }
            if(canvas.preview){
                previewing(e);
            }
        },
        draw: function(action){
            drawFigure(action, canvas.context);
        }
    }
    
    function startPreviewing(e){
        var pageX = e.pageX;
        var pageY = e.pageY;
        var offsetX = $('#sketch').offset().left;
        var offsetY = $('#sketch').offset().top;
        var x = Math.floor(pageX - offsetX);
        var y = Math.floor(pageY - offsetY);
    
        canvas.preview = {
          x: x,
          y: y,
          tool: 'figure',
          figureType: $('#figureType').val(),
          color: canvas.color,
          size: canvas.size
        };
    }
    
    function stopPreviewing(e){
        canvas.actions.push(canvas.preview);
        canvas.preview = null;
        var tmpCtx = $('#tmpCanvas')[0].getContext('2d');
        tmpCtx.clearRect(0, 0, canvas.el.width, canvas.el.height);
        canvas.redraw();
        if(layerOnFlag){updatePreview();}
    }
    
    function previewing(e){
        var pageX = e.pageX;
        var pageY = e.pageY;
        var offsetX = $('#sketch').offset().left;
        var offsetY = $('#sketch').offset().top;
        var x = Math.floor(pageX - offsetX);
        var y = Math.floor(pageY - offsetY);
    
        canvas.preview.w = x - canvas.preview.x;
        canvas.preview.h = y - canvas.preview.y;
    
        var tmpCtx = $('#tmpCanvas')[0].getContext('2d');
        tmpCtx.clearRect(0, 0, canvas.el.width, canvas.el.height);
        drawFigure(canvas.preview, tmpCtx);
    }
    
    function drawFigure(action, context){
        switch(action.figureType){
            case '0': //-
                context.beginPath();
                context.lineWidth = action.size;
                context.lineCap = 'butt';
                context.strokeStyle = action.color;
                context.moveTo(action.x, action.y);
                context.lineTo(action.x + action.w, action.y + action.h);
                context.stroke();
                break;
            case '1': //□
                context.beginPath();
                context.lineWidth = action.size;
                context.lineCap = 'butt';
                context.strokeStyle = action.color;
                context.strokeRect(action.x, action.y, action.w, action.h);
                break;
            case '2': //■
                context.beginPath();
                context.lineCap = 'butt';
                context.fillStyle = action.color;
                context.fillRect(action.x, action.y, action.w, action.h);
                break;
            case '3': //○
                context.beginPath();
                context.lineWidth = action.size;
                context.lineCap = 'butt';
                context.strokeStyle = action.color;
                  ctx.beginPath();
       ctx.arc(70, 70, 60, 0, Math.PI*2, false);
      ctx.stroke();
        }
    }
    
    function actionToString(){
        var actionString = '';
        var actDel = '!';
        var propDel = '~';
        var tools = {
            marker: 'm',
            eraser: 'e',
            moji: 's',
            fill: 'f'
        };
    
        jQuery.each(canvas.actions, function(i, action){
            if(tools[action.tool]){
    
                actionString += actDel + tools[action.tool];
    
                switch(action.tool){
                    case 'marker':
                    case 'eraser':
                        var actionX = Math.floor(action.events[0].x);
                        var actionY = Math.floor(action.events[0].y);
                        var beforeX = actionX;
                        var beforeY = actionY;
                        actionString += lpad(actionX, 3, '0') + lpad(actionY, 3, '0') + lpad(action.size, 3, '0') + action.color.replace(/ /g, '') + propDel;
                    
                        jQuery.each(action.events, function(j, event){
                            actionX = Math.floor(event.x);
                            actionY = Math.floor(event.y);
                            actionString += String.fromCharCode((actionX - beforeX + 64), (actionY - beforeY + 64));
                            beforeX = actionX;
                            beforeY = actionY;
                        });
                        break;
                    case 'moji':
                        actionString += lpad(action.x, 3, '0') + lpad(action.y, 3, '0') + action.mode + propDel + action.color + propDel + action.font + propDel + action.text;
                        break;
                    case 'fill':
                        actionString += lpad(action.x, 3, '0') + lpad(action.y, 3, '0') + propDel + action.fillColor + propDel + action.targetColor;
                        break;
                }
            }
        });
        actionString = actionString.substr(1);
        return actionString;
    }
    
    function actionStringToColor(actionString){
        console.log('ExportString'+actionString);
        //var undefCharCode = 35;
        var ch = canvas.el.height;
        var m = -10;
        var w = 1;
        var h = 1;
        //canvas.el.height += Math.floor((actionString.length+3)/(canvas.el.width+m)/n)+10;
        
        fillCanvas = canvas.context.getImageData(0, 0, canvas.el.width, canvas.el.height);
        fillN(1, 0, w, h, 0x000000);
            
        for(var i = 0; i < actionString.length/3; i++){
            var c1 = actionString.charCodeAt(i*3);
            var c2 = actionString.charCodeAt(i*3 + 1);
            var c3 = actionString.charCodeAt(i*3 + 2);
            if(!c1){c1 = 35;}
            if(!c2){c2 = 35;}
            if(!c3){c3 = 35;}
            var color = (c1 << 16) + (c2 << 8) + c3;
            //console.log('x>' + (i+2)%canvas.el.width + ' y>' + (Math.floor((i+2)/canvas.el.width) + h));
            fillN(((i+1)*w)%(canvas.el.width+m)+1, Math.floor(((i+1)*w)/(canvas.el.width+m))*h, w, h, color);
        }
        
        fillN(((i+1)*w)%(canvas.el.width+m)+1, Math.floor(((i+1)*w)/(canvas.el.width+m))*h, w, h, 0x000000);
        
        var orgActions = canvas.actions;
        canvas.actions = [''];
        var beforeBaseImage = canvas.baseImageURL;
        canvas.redraw();
        canvas.context.putImageData(fillCanvas, 0, 0);
        var src = canvas.el.toDataURL('imgae/png');
        canvas.setBaseImageURL(src);
        canvas.actions = orgActions;
        canvas.redraw();
    }
    
    function fillN(x, y, w, h, color){
        for(var i = 0; i < w; i++){
            for(var j = 0; j < h; j++){
                fillRGB(x + i,   y + j, color);
             }
        }
    }
    
    function colorToActionString(){
        fillCanvas = canvas.context.getImageData(0, 0, canvas.el.width, canvas.el.height);
        var actionString = '';
        var undefCharCode = 35;
        var ch = 1;
        var m = -10;
        var w = 1;
        var h = 1;
        var c = getRGB(1, 0);
        if(c!=0x000000){return;}
    
        var i = 0;
        while(i < canvas.el.width * canvas.el.height / 4){
            var color = getRGB(((i+1)*w)%(canvas.el.width+m)+1, (Math.floor(((i+1)*h)/(canvas.el.width+m)))*h);
            if(color==0x000000){break;}
            c1 = (color&0xFF0000)>>16;
            c2 = (color&0xFF00)>>8;
            c3 = (color&0xFF);
            i++;
            
            actionString += String.fromCharCode(c1);
            actionString += String.fromCharCode(c2);
            actionString += String.fromCharCode(c3);
        }
        console.log('ImportString' + actionString.replace(new RegExp(String.fromCharCode(undefCharCode), 'g'), ''));
        return actionString.replace(new RegExp(String.fromCharCode(undefCharCode), 'g'), '');
    }
    
    function stringToAction(actionString){
        if(!actionString){alert('描画情報が見つかりませんでした。');return [];}
        if(!confirm('お絵かきを再生します。\n※再生を開始すると、あなたの描いた絵の情報はクリアされます')){return [];}
    
        canvas.clear();
        
        var actionDelimiter = '!';
        var propDelimiter = '~';
        var splitActions = actionString.split(actionDelimiter);
        var actions =[];
        var tools = {
            m: 'marker',
            e: 'eraser',
            s: 'moji',
            f: 'fill'
        };
    
        jQuery.each(splitActions, function(i, actionsLine){
            var splitAction = actionsLine.split(propDelimiter);
            var actionLine = splitAction[0];
            var tool = tools[actionLine.substr(0, 1)];
            
            switch(tool){
                case 'marker':
                case 'eraser':
                    var bX = actionLine.substr(1, 3);
                    var bY = actionLine.substr(4, 3);
                    var size = actionLine.substr(7, 3);
                    var color = actionLine.substr(10);
                    var action = {
                       tool: tool,
                       size: parseFloat(size),
                       color: color,
                       events: []
                    }
                         
                    action.events.push({x: bX, y: bY});
                    var eventLine = splitAction[1];
                    for(var i = 1; i <= eventLine.length/2; i++){
                        action.events.push({
                        x: Number(action.events[i-1].x) + Number(eventLine.charCodeAt(i*2) - 64), 
                        y: Number(action.events[i-1].y) + Number(eventLine.charCodeAt(i*2+1) - 64)});
                    }
                    break;
                //case 'moji':
                //    var action = {
                //        tool: tool,
                //        mode: actionLine.substr(1, 1),
                //        color: splitAction[1],
                //        font: splitAction[2],
                //        text: splitAction[3]
                //    };
                //    break;
                case 'fill':
                    var action = {
                        tool: tool,
                        x: actionLine.substr(1, 3),
                        y: actionLine.substr(4, 3),
                        fillColor: splitAction[1],
                        targetColor: splitAction[2]
                    };
                    break;
            }
            actions.push(action); 
        });
        return actions;
    }
    
    function playback(actions, time){
        console.log('playback');
        console.log(actions);
        if(actions.length == 0){return;}
        var painting = false;
        var id1 = setInterval(function(){
            if(actions[0]){
                var action = actions[0];
                if(!painting){
                    switch(action.tool){
                        case 'marker':
                        case 'eraser':
                            var i = 0;
                            var events = action.events;
                            var id2 = setInterval(function(){
                                painting = true;
                                if(events && i+1 < events.length){
                                    canvas.context.beginPath();
                                    canvas.context.moveTo(events[i].x, events[i].y);
                                    canvas.context.lineJoin = 'round';
                                    canvas.context.lineCap = 'round';
                                    canvas.context.lineTo(events[i+1].x, events[i+1].y);
                                    canvas.context.strokeStyle = action.color;
                                    canvas.context.lineWidth = action.size;
                                    canvas.context.stroke();i++;
                                }else{
                                    clearInterval(id2);
                                    painting = false;
                                    canvas.actions.push(actions.shift());
                                    canvas.redraw();
                                }
                            },time);
                            break;
                        case 'moji':
                        case 'fill':
                            painting = true;
                            canvas.actions.push(actions.shift());
                            canvas.redraw();
                            painting = false;
                            break;
                    }
                }
            }else{
                clearInterval(id1);
            }
        },time*4);
    }
    
    function lpad(string, length, char){
       var padding;
       for(var i = 1; i <= length; i++){
           padding += char;
       }
       return (padding + string).slice(-length);
    }
    
    
    
    $(document).keydown(function(e){
        keydownEvent(e, 37, canvas.actions, drawRedo);
        keydownEvent(e, 39, drawRedo, canvas.actions);
        canvas.redraw();
        if(layerOnFlag){updatePreview();}
    });
    
    
    $("#backButton").unbind();
    $("#backButton").click(function() {
        changeAction(canvas.actions, drawRedo);
        canvas.redraw();
    });
    
    function keydownEvent(e, keyNum, popList, pushList){
        if(e.which === keyNum && e.ctrlKey && popList.length > 0){
            changeAction(popList, pushList);
            canvas.redraw();
        }
    }
    
    function changeAction(popList, pushList){
        pushList.push(popList.pop());
    }
    
    
    canvas.stopPainting = function(){
        if (this.action) {
           this.actions.push(this.action);
        }
        this.painting = false;
        this.action = null;
        if(layerOnFlag){updatePreview();}
    };
    
    function mergeLayer(){
        if(layerOnFlag){
            canvas.context.clearRect(0, 0, canvas.el.width, canvas.el.height);
    
            $('canvas[id^=preview]').each(function(i){
                if(this.displayed){
                    canvas.context.drawImage($(this)[0], 0, 0, canvas.el.width, canvas.el.height);
                }
            });
        }
    //    var img = new Image();
    //    img.src = canvas.el.toDataURL();
    //    $('#layerTool').append(img);
    };
    
    $('#submit_button').click(function(){mergeLayer()});
  • Permalink
    このページへの個別リンクです。
    RAW
    書かれたコードへの直接のリンクです。
    Packed
    文字列が圧縮された書かれたコードへのリンクです。
    Userscript
    Greasemonkey 等で利用する場合の .user.js へのリンクです。
    Loader
    @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
    Metadata
    コード中にコメントで @xxx と書かれたメタデータの JSON です。

History

  1. 2014/08/17 15:19:12 - 2014-08-17
  2. 2014/07/25 18:17:25 - 2014-07-25
  3. 2014/06/15 22:58:18 - 2014-06-15
  4. 2014/06/12 22:55:45 - 2014-06-12
  5. 2014/06/08 22:13:05 - 2014-06-08
  6. 2014/06/08 19:01:10 - 2014-06-08
  7. 2014/06/07 23:59:27 - 2014-06-07
  8. 2014/06/04 23:43:06 - 2014-06-04
  9. 2014/06/02 15:20:24 - 2014-06-02
  10. 2014/06/01 17:49:08 - 2014-06-01
  11. 2014/05/28 23:01:10 - 2014-05-28
  12. 2014/05/28 21:17:42 - 2014-05-28
  13. 2014/05/28 00:38:24 - 2014-05-28
  14. 2014/05/28 00:37:53 - 2014-05-28
  15. 2014/05/28 00:35:44 - 2014-05-28
  16. 2014/05/28 00:30:52 - 2014-05-28
  17. 2014/05/27 00:16:58 - 2014-05-27
  18. 2014/05/25 20:20:52 - 2014-05-25
  19. 2014/05/17 17:09:01 - 2014-05-17
  20. 2014/05/11 01:15:56 - 2014-05-11
  21. 2014/05/07 22:45:33 - 2014-05-07
  22. 2014/05/07 22:18:28 - 2014-05-07
  23. 2014/05/06 20:25:53 - 2014-05-06
  24. 2014/05/06 20:17:36 - 2014-05-06
  25. 2014/05/05 13:10:28 - 2014-05-05
  26. 2014/05/03 21:57:01 - 2014-05-03
  27. 2014/05/03 21:40:44 - 2014-05-03
  28. 2014/05/03 21:19:54 - 2014-05-03
  29. 2014/05/01 23:11:00 - 2014-05-01
  30. 2014/05/01 22:29:09 - 2014-05-01
  31. 2014/05/01 22:27:31 - 2014-05-01
  32. 2014/04/29 19:12:48 - 2014-04-29
  33. 2014/04/29 17:28:57 - 2014-04-29
  34. 2014/04/29 17:27:44 - 2014-04-29
  35. 2014/04/29 17:02:37 - 2014-04-29
  36. 2014/04/28 00:51:26 - 2014-04-28
  37. 2014/04/24 01:18:19 - 2014-04-24
  38. 2014/04/20 18:09:29 - 2014-04-20
  39. 2014/04/20 02:23:05 - 2014-04-20
  40. 2014/04/20 02:21:40 - 2014-04-20
  41. 2014/04/20 01:39:54 - 2014-04-20
  42. 2014/04/20 01:38:41 - 2014-04-20
  43. 2014/04/20 01:37:58 - 2014-04-20
  44. 2014/04/20 00:17:06 - 2014-04-20
  45. 2014/04/10 22:03:04 - 2014-04-10
  46. 2014/04/10 21:38:09 - 2014-04-10
  47. 2014/04/10 21:36:19 - 2014-04-10
  48. 2014/04/08 22:09:27 - 2014-04-08
  49. 2014/04/08 22:00:21 - 2014-04-08