非公開 open2chOekakiEX

    @@ -18,6 +18,7 @@ Ver2.4.0 2014/04/02 文字入力でフォントの直接指定&改行入力&縦書出力に対応 Ver3.0.0 2014/04/05 お絵かき再生機能追加 Ver3.1.0 2014/04/06 お絵かき再生機能のエクスポート方式をテキストから画像埋め込みに変更 +Ver3.1.1 2014/04/09 */ drawRedo = []; canvas = $('#sketch').sketch(); @@ -114,7 +115,7 @@ var exp = document.createElement('input'); exp.setAttribute('id', 'exportButton'); exp.setAttribute('type', 'button'); -exp.setAttribute('value', 'エクスポート!'); +exp.setAttribute('value', 'エクスポート'); var imp = document.createElement('input'); imp.setAttribute('id', 'importButton'); @@ -170,7 +171,8 @@ y: y, tool: canvas.tool, fillColor: fillColor, - targetColor: targetColor + targetColor: targetColor, + fill:null }); canvas.redraw(); @@ -325,19 +327,27 @@ } }, draw: function(action){ - var fillColor = action.fillColor; - fillCanvas = canvas.context.getImageData(0, 0, canvas.el.width, canvas.el.height); - var targetColor = action.targetColor; - seeds = [{'x':action.x, 'y':action.y}]; - - //var start = new Date(); - while(seeds.length > 0){ - var seed = seeds.shift(); - paint(seed.x, seed.y, fillColor, targetColor); + if(action.fill){ + fillCanvas = action.fill; + }else{ + var fillColor = action.fillColor; + fillCanvas = canvas.context.getImageData(0, 0, canvas.el.width, canvas.el.height); + var targetColor = action.targetColor; + 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'); + + action.fill = fillCanvas; } - //var end = new Date(); - //console.log(end - start + 'msec'); - return canvas.context.putImageData(fillCanvas, 0, 0); } } @@ -436,29 +446,53 @@ 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(action.tool == 'marker'){ - 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, '') + '' + '~'; - 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; - }); - } + 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); + console.log('ExportString'+actionString); + //var undefCharCode = 35; var ch = canvas.el.height; var m = -10; var w = 1; @@ -472,9 +506,9 @@ var c1 = actionString.charCodeAt(i*3); var c2 = actionString.charCodeAt(i*3 + 1); var c3 = actionString.charCodeAt(i*3 + 2); - if(!c1){c1 = 33;console.log('NaN')} - if(!c2){c2 = 33;console.log('NaN')} - if(!c3){c3 = 33;console.log('NaN')} + 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); @@ -504,20 +538,14 @@ 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; - //while(ch < canvas.el.height){ - var c = getRGB(1, 0); - // h++; - if(c!=0x000000){return;} - //} + var c = getRGB(1, 0); + if(c!=0x000000){return;} - //if(h <= 0){console.log('not found');return;} - //console.log('importStart H->' + h); - 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); @@ -531,8 +559,8 @@ actionString += String.fromCharCode(c2); actionString += String.fromCharCode(c3); } - //console.log('Import String' + actionString.replace(/\!/g,'')); - return actionString.replace(/\!/g,''); + console.log('ImportString' + actionString.replace(new RegExp(String.fromCharCode(undefCharCode), 'g'), '')); + return actionString.replace(new RegExp(String.fromCharCode(undefCharCode), 'g'), ''); } function stringToAction(actionString){ @@ -541,61 +569,109 @@ canvas.clear(); - var splitActions = actionString.split(' '); + 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('~'); + var splitAction = actionsLine.split(propDelimiter); var actionLine = splitAction[0]; - var bX = actionLine.substr(0, 3); - var bY = actionLine.substr(3, 3); - var size = actionLine.substr(6, 3); - var color = actionLine.substr(9); - var action = { - tool: 'marker', - size: parseFloat(size), - color: color, - events: [] - } + 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)}); - } - actions.push(action); + 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 exportActions = actions; var painting = false; var id1 = setInterval(function(){ if(actions[0]){ var action = actions[0]; - var events = action.events; - var i = 0; if(!painting){ - var id2 = setInterval(function(){ - painting = true; - if(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; + 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()); - } - },time); + canvas.redraw(); + painting = false; + break; + } } }else{ clearInterval(id1); @@ -622,33 +698,3 @@ keydownEvent(e, 39, drawRedo, canvas.actions); }); -canvas.startPainting = function(){ - orgActions = canvas.actions; - if(!orgActions){ - orgActions = []; - } - canvas.actions = []; - beforeBaseImage = canvas.baseImageURL; - var src = canvas.el.toDataURL('imgae/png'); - canvas.setBaseImageURL(src); - canvas.painting = true; - return canvas.action = { - tool: canvas.tool, - color: canvas.color, - size: parseFloat(canvas.size), - events: [] - }; -}; - -canvas.stopPainting = function() { - if (canvas.action && canvas.painting) { - orgActions.push(canvas.action); - canvas.setBaseImageURL(beforeBaseImage); - canvas.actions = orgActions; - } - canvas.painting = false; - canvas.action = null; - return setTimeout(function(){canvas.redraw();},10); -}; - -
  • /*
     * @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.1.1  2014/04/09    
    */
    drawRedo = [];
    canvas = $('#sketch').sketch();
    
    var fillInput = document.createElement('input');
    fillInput.setAttribute('id', 'fill');
    fillInput.setAttribute('type', 'radio');
    fillInput.setAttribute('name', 'pmode');
    var fillImg = document.createElement('img');
    fillImg.setAttribute('src', 'http://image.open2ch.net/image/oekaki/nuri.png');
    var fillLabel = document.createElement('label');
    fillLabel.appendChild(fillImg);
    
    var textInput = document.createElement('input');
    textInput.setAttribute('id', 'moji');
    textInput.setAttribute('type', 'radio');
    textInput.setAttribute('name', 'pmode');
    
    var textLabel = document.createElement('label');
    textLabel.setAttribute('for', 'moji');
    var b = document.createElement('b');
    var textNode = document.createTextNode('[A]:');
    b.appendChild(textNode);
    textLabel.appendChild(b);
    
    var size = [10,12,14,16,18,20,24,28,32,36,40,48,56,64,72,80,90,100];
    var mojiSelect = document.createElement('select'); 
    mojiSelect.setAttribute('id', 'mojiSize');
    for(var i = 0; i < size.length; i++){
        var option = document.createElement('option');
        if(i == 5){
           option.setAttribute('selected','selected');
        }
        option.value = size[i];
        var text = document.createTextNode(size[i]);
        option.appendChild(text);
        mojiSelect.appendChild(option);
    }
    
    var fontSelect = document.createElement('select');
    fontSelect.setAttribute('id', 'mojiFont');
    var font = ['ゴシック','明朝','筆記体','装飾','等幅'];
    for(var i = 0; i < font.length; i++){
        var option = document.createElement('option');
        option.value = i;
        var text = document.createTextNode(font[i]);
        option.appendChild(text);
        fontSelect.appendChild(option);
    }
    
    var boldCheck = document.createElement('input');
    boldCheck.setAttribute('id', 'mojiBold');
    boldCheck.setAttribute('type', 'checkbox');
    boldCheck.setAttribute('value', 'bold');
    var b = document.createElement('b');
    var textNode = document.createTextNode(' B:');
    b.appendChild(textNode);
    
    var italicCheck = document.createElement('input');
    italicCheck.setAttribute('id', 'mojiItalic');
    italicCheck.setAttribute('type', 'checkbox');
    italicCheck.setAttribute('value', 'italic');
    var i = document.createElement('i');
    var textNode = document.createTextNode(' I:');
    i.appendChild(textNode);
    
    var br = document.createElement('br');
    
    $('#backButton').before(fillInput);
    $('#backButton').before(fillLabel);
    $('#backButton').before(textInput);
    $('#backButton').before(textLabel);
    $('#backButton').before(mojiSelect);
    $('#backButton').before(fontSelect);
    $('#backButton').before(b);
    $('#backButton').before(boldCheck);
    $('#backButton').before(i);
    $('#backButton').before(italicCheck);
    $('#backButton').before(br);
    
    var mojiA = document.createElement('a');
    mojiA.setAttribute('data-tool','moji');
    mojiA.setAttribute('href', '#sketch');
    
    var fillA = document.createElement('a');
    fillA.setAttribute('data-tool','fill');
    fillA.setAttribute('href', '#sketch');
    
    $('.tools').after(fillA);
    $('.tools').after(mojiA);
    $("#moji").click(function(){$("[data-tool=moji]").click()});
    $("#fill").click(function(){$("[data-tool=fill]").click()});
    
    var exp = document.createElement('input');
    exp.setAttribute('id', 'exportButton');
    exp.setAttribute('type', 'button');
    exp.setAttribute('value', 'エクスポート');
    
    var imp = document.createElement('input');
    imp.setAttribute('id', 'importButton');
    imp.setAttribute('type', 'button');
    imp.setAttribute('value', 'インポート');
    
    $('#saveButton').after(imp);
    $('#saveButton').after(exp);
    $('#importButton').click(function(){
       playback(stringToAction(colorToActionString()), 10);
    });
    $('#exportButton').click(function(){
        actionStringToColor(actionToString());
    });
    
    var show = $('#_canvas').next().children();
    show.html("ctrl+←:UNDO<br/>ctrl+→:REDO<br/>" + show.html());
    
    
    function fill(e){
        fillCanvas = canvas.context.getImageData(0, 0, canvas.el.width, canvas.el.height);
    
        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 fillRGB = canvas.color.match(/(\d|\.)+/g);
        if(fillRGB[3] == undefined){
            var alpha = 255;
        }else{
            var alpha = alphaToInt(fillRGB[3]);
        }
    
        var fillColor = ((Number(fillRGB[0]) << 24) + (Number(fillRGB[1]) << 16) + (Number(fillRGB[2]) << 8) + alpha)>>>0;
        //console.log('fillColor>' + fillColor.toString(2));
        //console.log('fillR>' + fillRGB[0] + ' fillG>' + fillRGB[1] + ' fillB>' + fillRGB[2] + ' fillA' + alpha);
        //console.log('fillRbit>' + ((fillColor & 0xFF000000) >>> 24));
        //console.log('fillGbit>' + ((fillColor & 0xFF0000) >> 16));
        //console.log('fillBbit>' + ((fillColor & 0xFF00) >> 8));
        //console.log('fillAbit>' + (fillColor & 0xFF));
        
        var targetColor = getRGBA(x, y);
        //console.log('targetRbit>' + ((targetColor & 0xFF000000) >>> 24));
        //console.log('targetGbit>' + ((targetColor & 0xFF0000) >> 16));
        //console.log('targetBbit>' + ((targetColor & 0xFF00) >> 8));
        //console.log('targetAbit>' + (targetColor & 0xFF));
    
        canvas.actions.push({
            x: x,
            y: y,
            tool: canvas.tool,
            fillColor: fillColor,
            targetColor: targetColor,
            fill:null
        });
    
        canvas.redraw();
    }
    
    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.width){
            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;
        //console.log('beforeR>' + ((color & 0xFF000000) >>> 24));
        //console.log('beforeG>' + ((color & 0xFF0000) >> 16));
        //console.log('beforeB>' + ((color & 0xFF00) >> 8));
        //console.log('beforeA>' + ((color & 0xFF)));
        img[p]   = (color & 0xFF000000) >>> 24;
        img[p+1] = (color & 0xFF0000) >> 16;
        img[p+2] = (color & 0xFF00) >> 8;
        img[p+3] = color & 0xFF;
        //console.log('afterR>' + img[p]);
        //console.log('afterG>' + img[p+1]);
        //console.log('afterB>' + img[p+2]);
        //console.log('afterA>' + img[p+3]);
    }
    
    function fillRGB(x, y, color) {
        //console.log('x:' + x + ' y:' + y);
        var img = fillCanvas.data;
        var w = fillCanvas.width;
        var h = fillCanvas.height;
        var p = ((w * y) + x) * 4;
        //console.log('beforeR>' + img[p]);
        //console.log('beforeG>' + img[p+1]);
        //console.log('beforeB>' + img[p+2]);
        //console.log('beforeA>' + img[p+3]);
        img[p]   = (color & 0xFF0000) >> 16;
        img[p+1] = (color & 0xFF00) >> 8;
        img[p+2] = color & 0xFF;
        img[p+3] = 0xFF;
        //console.log('afterR>' + img[p]);
        //console.log('afterG>' + img[p+1]);
        //console.log('afterB>' + img[p+2]);
        //console.log('afterA>' + img[p+3]);
    }
    
    function getRGBA(x, y){
        var img = fillCanvas.data;
        var w = fillCanvas.width;
        var h = fillCanvas.height;
        var p = ((w * y) + x) * 4;
        //console.log('getR>' + img[p]);
        //console.log('getG>' + img[p+1]);
        //console.log('getB>' + img[p+2]);
        //console.log('getA>' + img[p+3]);
        //console.log('putR>' + ((img[p] << 24)>>>0));
        //console.log('putG>' + (img[p+1] << 16));
        //console.log('putB>' + (img[p+2] << 8));
        //console.log('putA>' + (img[p+3]));
        //console.log(((Number(img[p]) << 24) + (Number(img[p+1]) << 16) + (Number(img[p+2]) << 8) + img[p+3])>>>0);
        return ((img[p] << 24) + (img[p+1] << 16) + (img[p+2] << 8) + img[p+3])>>>0;
    }
    
    function getRGB(x, y){
        //console.log('x:' + x + ' y:' + 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;
    }
    
    $.sketch.tools.fill= {
        onEvent: function(e) {
          switch (e.type) {
            case 'mousedown':
            case 'touchstart':
              fill(e);
            break;
          }
        },
        draw: function(action){
            if(action.fill){
                fillCanvas = action.fill;
            }else{
                var fillColor = action.fillColor;
                fillCanvas = canvas.context.getImageData(0, 0, canvas.el.width, canvas.el.height);
                var targetColor = action.targetColor;
                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');
        
                action.fill = fillCanvas;
            }
            return canvas.context.putImageData(fillCanvas, 0, 0);
        }
    }
    
    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();
    }
    
    $.sketch.tools.moji = {
        onEvent: function(e) {
          switch (e.type) {
            case 'mousedown':
            case 'touchstart':
              drawText(e);
            break;
          }
        },
        draw: function(action){
            var context = canvas.context;
            context.fillStyle = action.color;
            context.font = action.font;
            context.baseline = 'top';
            return fillText(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);
                });
            }
        });
    }
    
    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);
        
        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);
    }
    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);
        keydownEvent(e, 39, drawRedo, canvas.actions);
    });
    
    
  • 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