open2chOekakiEX
by
xnimasu
2014-08-17 [2014/08/17 15:19:12]
おーぷん2ちゃんお絵かき機能拡張ブックマークレット
@@ -4,60 +4,27 @@
* @require https://googledrive.com/host/0B1BW1N6rqpWFNjdEazFaNm1XSjA/jquery-ui-1.10.4.custom.min.js
* @require https://googledrive.com/host/0B1BW1N6rqpWFR2NCRFFUbmJzN0U/jquery-ui-1.10.4.custom.min.css
* @require https://googledrive.com/host/0B1BW1N6rqpWFNjdEazFaNm1XSjA/spline.js
+ * @require https://googledrive.com/host/0B1BW1N6rqpWFNjdEazFaNm1XSjA/replay.js
+ * @require https://googledrive.com/host/0B1BW1N6rqpWFNjdEazFaNm1XSjA/version.js
+ * @require https://googledrive.com/host/0B1BW1N6rqpWFNjdEazFaNm1XSjA/manual.js
* @private
*/
-
//【更新履歴】
-var VERSION= 'Ver8.1.0';
-var VERSION_INFO = {
-'Ver1.0.0': {Date:'2014/03/29', Info:'文字入力機能追加'},
-'Ver1.1.0': {Date:'2014/03/29', Info:'お絵かき機能ツールメニュー内に文字入力機能を追加 文字サイズ指定追加'},
-'Ver1.2.0': {Date:'2014/03/30', Info:'フォント指定、修飾指定追加'},
-'Ver1.3.0': {Date:'2014/03/30', Info:'線描画と文字入力のUNDO/REDO機能追加 イタリックが効かないバグ修正'},
-'Ver2.0.0': {Date:'2014/03/31', Info:'塗りつぶし機能追加'},
-'Ver2.1.0': {Date:'2014/03/31', Info:'塗りつぶし機能にUNDO/REDO機能追加'},
-'Ver2.1.1': {Date:'2014/03/31', Info:'IE、Chromeで塗りつぶしが効かないバグ修正'},
-'Ver2.2.0': {Date:'2014/04/01', Info:'背景色以外の色も塗りつぶせるように修正'},
-'Ver2.3.0': {Date:'2014/04/01', Info:'透明度を指定して塗りつぶせるように修正'},
-'Ver2.4.0': {Date:'2014/04/02', Info:'文字入力でフォントの直接指定&改行入力&縦書出力に対応'},
-'Ver3.0.0': {Date:'2014/04/05', Info:'お絵かき再生機能追加'},
-'Ver3.1.0': {Date:'2014/04/06', Info:'お絵かき再生機能のエクスポート方式をテキストから画像埋め込みに変更'},
-'Ver3.2.0': {Date:'2014/04/10', Info:'お絵かき再生機能で塗りつぶしと消しゴムが再生できるように修正 線を引くときにちらつくバグを修正'},
-'Ver4.0.0': {Date:'2014/04/19', Info:'レイヤ機能追加'},
-'Ver4.1.0': {Date:'2014/04/20', Info:'レイヤの表示/非表示切替機能追加 最前面のレイヤしか投稿できないバグ修正 レイヤの移動に関するバグ修正 コラボするとレイヤの重なりがおかしくなるバグ修正'},
-'Ver4.1.1': {Date:'2014/04/24', Info:'IE10未満で起動できないバグを修正'},
-'Ver4.1.2': {Date:'2014/04/28', Info:'IEでプレビューが正常に表示できないバグを修正'},
-'Ver4.2.0': {Date:'2014/04/29', Info:'レイヤ機能をデフォルトではオフに変更 レイヤ機能オン時の性能向上'},
-'Ver4.2.1': {Date:'2014/04/29', Info:'絵が投稿できないバグを修正'},
-'Ver4.3.0': {Date:'2014/04/29', Info:'線の太さ、文字の大きさを追加'},
-'Ver5.0.0': {Date:'2014/05/01', Info:'図形描画機能追加 レイヤ機能をデフォルトでオンに変更 「進」ボタン追加'},
-'Ver5.1.0': {Date:'2014/05/03', Info:'文字入力後に文字位置を移動できる機能を追加 マニュアル表示追加'},
-'Ver5.1.1': {Date:'2014/05/03', Info:'一部文字が投稿できないバグを修正'},
-'Ver5.2.0': {Date:'2014/05/05', Info:'文字入力後に文字を回転できる機能を追加 IEで文字のフォント直接指定が機能していなかったバグを修正'},
-'Ver5.3.0': {Date:'2014/05/06', Info:'お絵かき中にページ遷移しようとすると確認ダイアログが出る機能を追加'},
-'Ver5.4.0': {Date:'2014/05/07', Info:'お絵かき投稿前に絵の内容を確認できる機能を追加'},
-'Ver6.0.0': {Date:'2014/05/10', Info:'選択範囲の切り取り&コピー機能を追加 文字や図形のみの絵が投稿できないバグを修正'},
-'Ver6.0.1': {Date:'2014/05/17', Info:'キャンバスのサイズ変更に対応 範囲選択時に表示する枠の線幅を修正 塗り潰し後に性能劣化するバグ修正'},
-'Ver7.0.0': {Date:'2014/05/25', Info:'手ブレ補正機能(α版)公開'},
-'Ver7.1.0': {Date:'2014/05/26', Info:'手ブレ補正機能(β版)公開 新着お知らせ機能追加'},
-'Ver7.2.0': {Date:'2014/05/27', Info:'UI変更'},
-'Ver7.3.0': {Date:'2014/05/28', Info:'手ブレ補正機能正式版公開 文字入力でフォント指定が効かないバグを修正'},
-'Ver8.0.0': {Date:'2014/06/01', Info:'拡大・縮小機能追加'},
-'Ver8.1.0': {Date:'2014/06/02', Info:'Chrome以外のブラウザでの消しゴム機能対応(仮)'}
-};
+var VERSION= 'Ver9.0.0';
var PREVIEW_SIZE = 0.2;
var MARGIN = 0;
var settings = {
- version: localStorage.getItem('version') || 'Ver0.0.0',
+ version: localStorage.getItem('version') || 'Ver0.0.0',
checkVersion: localStorage.getItem('checkVersion') || 1,
- saveType: localStorage.getItem('saveType') || 1,
- saveCycle: localStorage.getItem('saveCycle') || 5,
- saveMaxAge: localStorage.getItem('saveMaxAge') || 1
+ saveType: localStorage.getItem('saveType') || 1,
+ saveCycle: localStorage.getItem('saveCycle') || 10,
+ saveMaxAge: localStorage.getItem('saveMaxAge') || 2,
+ layerOn: localStorage.getItem('layerOn') || 1
}
-//var savedImages = loadSavedImages();
+var savedImages;
var canvas = $('#sketch').sketch();
var drawRedo = [];
@@ -70,63 +37,19 @@
var scaleH;
var degree;
-var layerOnFlag = true;
-//var layerOnFlag = false;
-
var icons = {
- rotateIcon: 'rotate2.png',
- curveIcon: 'curve.png',
- mojiIcon: 'moji.png',
- figureIcon: 'figure.png',
- selectionIcon: 'selection.png',
- saveIcon: 'save.png',
- settingsIcon: 'settings.png',
+ rotateIcon: 'rotate2.png',
+ curveIcon: 'curve.png',
+ mojiIcon: 'moji.png',
+ figureIcon: 'figure.png',
+ selectionIcon: 'selection.png',
+ saveIcon: 'save.png',
+ settingsIcon: 'settings.png',
rotateRightIcon: 'rotateRight.png',
- rotateLeftIcon: 'rotateLeft.png'
+ rotateLeftIcon: 'rotateLeft.png',
+ reloadIcon: 'reload.png'
};
-
-var manual = "\
-<FONT size=+1><B>【主な機能】</B></FONT><BR><BR>\
-・<B>線描画機能</B><BR>\
- - 選べる線の太さを拡張<BR>\
-<BR>\
-・<B>手ぶれ補正機能</B><BR>\
- - 描いた線を滑らかに補正<BR>\
-<BR>\
-・<B>文字入力機能</B><BR>\
- - ツールメニューの[A]を選択して、文字を書きたい場所をクリック<BR>\
- - 色、サイズ、フォント、装飾をツールメニューから選択可能<BR>\
- - 先頭に『!』と入力すると縦書で出力(フォント指定よりも前に入力)<BR>\
- - 先頭に『[フォント名]』と入力すると指定したフォントで文字を出力<BR>\
- - 文字列中に『\\n』を入れるとそこで改行<BR>\
- - 他の操作を行うまで文字の移動、回転が可能<BR>\
-<BR>\
-・<B>塗りつぶし機能</B><BR>\
- - ツールメニューのバケツマークを選択して、塗りつぶしたい箇所をクリック<BR>\
- - 色、透明度を選択可能<BR>\
- <BR>\
-・<B>図形描画機能</B><BR>\
- - ツールメニューの「図形」プルダウンから図形を選択して、図形を描きたい範囲を選択<BR>\
- - 直線、四角形、円を描画可能<BR>\
-<BR>\
-・<B>範囲選択機能</B><BR>\
- - ツールメニューの「選択」プルダウンから選択後の動作を選択して、範囲を選択<BR>\
- - 選択範囲に枠が表示されるのでドラッグ&ドロップで移動<BR>\
-<BR>\
-・<B>お絵かき再生機能(現在停止中)</B><BR>\
- <S>- 絵を描いた後「出力」ボタンを押すと絵の情報が画像内に埋め込まれる</S><BR>\
- <S>- 情報が埋め込まれた絵をコラボして「再生」ボタンを押すと再生</S><BR>\
- <BR>\
-・<B>レイヤ機能</B><BR>\
- - キャンバス下の「機能ON」をクリックすることでレイヤ機能が有効化<BR>\
- - 「追加」をクリックでレイヤを追加<BR>\
- - プレビューをクリックでレイヤの選択<BR>\
- - 「表示」をクリックで選択したレイヤの表示/非表示切替<BR>\
- - 「←」「→」で選択したレイヤの位置(前面、背面)を入れ替え<BR>\
-<BR>\
-・<B>ショートカットキー</B><BR>\
- - [ctrl + ←]:UNDO <BR>\
- - [ctrl + →]:REDO";
+loadIcon(icons);
var browser = checkBrowser();
checkNewVersion();
@@ -135,14 +58,20 @@
initManual();
setCanvasScale();
+var drawTimer = '';
+var saveTimer = '';
+startAutoSave();
-function checkNewVersion(){
- if(!settings.checkVersion) return;
-console.log(settings.version);
- if(settings.version != VERSION){
- localStorage.setItem('version', VERSION);
- alert(VERSION + ' ' + VERSION_INFO[VERSION].Date + ' ' + VERSION_INFO[VERSION].Info);
+function startAutoSave(){
+ clearInterval(saveTimer);
+
+ if(settings.saveCycle=='任意'){
+ autoSave = false;
+ saveTimer = '';
+ }else{
+ autoSave = true;
+ saveTimer = setInterval(saveImage, settings.saveCycle * 60 * 1000);
}
}
@@ -150,95 +79,129 @@
var ua = window.navigator.userAgent.toLowerCase();
var ver = window.navigator.appVersion.toLowerCase();
var name = '';
-
- if (ua.indexOf('msie') != -1){
- if (ver.indexOf('6.') != -1){
- name = 'ie6';
- }else if (ver.indexOf('7.') != -1){
- name = 'ie7';
- }else if (ver.indexOf('8.') != -1){
- name = 'ie8';
- }else if (ver.indexOf('9.') != -1){
- name = 'ie9';
- }else if (ver.indexOf('10.') != -1){
- name = 'ie10';
- }else{
- name = 'ie';
- }
- }else if(ua.indexOf('trident/7') != -1){
- name = 'ie11';
- }else if (ua.indexOf('chrome') != -1){
- name = 'chrome';
- }else if (ua.indexOf('safari') != -1){
- name = 'safari';
- }else if (ua.indexOf('opera') != -1){
- name = 'opera';
- }else if (ua.indexOf('firefox') != -1){
- name = 'firefox';
+ if(ua.indexOf('msie') != -1){
+ if (ver.indexOf('6.') != -1) {name = 'ie6';}
+ else if(ver.indexOf('7.') != -1) {name = 'ie7';}
+ else if(ver.indexOf('8.') != -1) {name = 'ie8';}
+ else if(ver.indexOf('9.') != -1) {name = 'ie9';}
+ else if(ver.indexOf('10.') != -1) {name = 'ie10';}
+ else {name = 'ie';}
+ }else if(ua.indexOf('trident/7') != -1){name = 'ie11';}
+ else if(ua.indexOf('chrome') != -1) {name = 'chrome';}
+ else if(ua.indexOf('safari') != -1) {name = 'safari';}
+ else if(ua.indexOf('opera') != -1) {name = 'opera';}
+ else if(ua.indexOf('firefox') != -1) {name = 'firefox';
}
return name;
}
+function checkNewVersion(){
+ if(settings.checkVersion && settings.version != VERSION){
+ localStorage.setItem('version', VERSION);
+ alert(VERSION + ' ' + VERSION_INFO[VERSION].Date + ' ' + VERSION_INFO[VERSION].Info);
+ }
+}
+
function saveSettings(){
-console.log('saveStart');
for(var key in settings){
-console.log(key + ':' + settings[key]);
localStorage.setItem(key, settings[key]);
}
-console.log('saveEnd');
+ startAutoSave();
}
-/*
+
+
$('#saveButton').unbind();
$('#saveButton').click(function(){
-console.log('click');
- saveImage($('#layerCanvas1')[0].toDataURL());
+ saveImage('manual');
+ loadSavedImages();
});
-*/
-function saveImage(src){
+
+function saveImage(type){
console.log('saveImageStart');
- var saveNum = localStorage.getItem('saveNum') + 1 || 1
- if(saveNum > settings.saveMaxAge){
- saveNum = 1;
- }
+ if(!autoSave && !type) return;
+
+ var saveNum = parseInt(localStorage.getItem('saveNum')) + 1 || 1;
+ if(saveNum > settings.saveMaxAge) saveNum = 1;
var date = new Date();
var name = [
date.getFullYear(),
('0' + (date.getMonth() + 1)).slice(-2),
- ('0' + date.getDate()).slice(-2),
- ('0' + date.getHours()).slice(-2) +
- ('0' + date.getMinutes()).slice(-2) +
- ('0' + date.getSeconds()).slice(-2)
- ].join( '-' ) + '.png';
+ ('0' + date.getDate()).slice(-2)
+ ].join( '-' ) + ' ' +
+ ('0' + date.getHours()).slice(-2) + ':' +
+ ('0' + date.getMinutes()).slice(-2) + ':' +
+ ('0' + date.getSeconds()).slice(-2);
+
+ var mergeCanvas = $('<canvas>').attr({
+ width: realW,
+ height: realH
+ });
+ var ctx = mergeCanvas[0].getContext('2d');
+
+ var saveImages = [];
+ $('canvas[id^=preview]').each(function(i){
+ saveImages.push({
+ name: name + '_layer' + (i+1),
+ src: $(this)[0].toDataURL()
+ });
- var saveImage = {
+ ctx.drawImage($(this)[0], 0, 0);
+ });
+ saveImages.unshift({
name: name,
- src: src
- }
+ src: mergeCanvas[0].toDataURL()
+ });
+
localStorage.setItem('saveNum', saveNum);
- localStorage.setItem('savedImage' + saveNum, JSON.stringify(saveImage));
+ localStorage.setItem('savedImage' + saveNum, JSON.stringify(saveImages));
console.log('saveImageEnd');
-loadSavedImage(saveNum);
}
-
-function loadSavedImage(num){
- var loadImage = JSON.parse(localStorage.getItem('savedImage' + num));
-
- var img = $('<img>', {
- id: 'savedImage' + loadImage.age,
- src: loadImage.src
- }).appendTo($('#oekakiCanvas'));
- var a = $('<a>', {
- id: 'downloadLink' + loadImage.age,
- download: loadImage.name,
- href: loadImage.src,
- text: loadImage.name
- }).appendTo($('#oekakiCanvas'));
+function loadSavedImages(){
+console.log('loadImageStart');
+ var loadImages = [];
+
+ for(var i = 1; i <= settings.saveMaxAge; i++){
+ var s = localStorage.getItem('savedImage' + i);
+ var loadImage = JSON.parse(s);
+ if(!loadImage) break;
+ loadImages.push(loadImage);
+ }
+ if(!loadImages.length > 0) return;
+
+ for(var i in loadImages){
+ var m = parseInt(i) + 1;
+ var tabName = loadImages[i][0].name.replace(/\_.*/, '');
+ var loadImage = loadImages[i];
+ $('#savedImage_' + m).remove();
+ $('#savedImageTabList').append(
+ $('<li>', {id: 'savedImage_' + m}).append($('<a>', {href: '#tab-saved-image-' + m, text: tabName.slice(0, 16)}))
+ );
+
+ $('#tab-saved-image-' + m).remove();
+ $('#savedImageTab').append($('<div>', {id: 'tab-saved-image-' + m}));
+ for(var j in loadImage){
+ var a = $('<a>', {
+ id: 'downloadLink_' + loadImage[j].name,
+ download: loadImage[j].name + '.png',
+ href: loadImage[j].src,
+ }).append(
+ $('<img>', {
+ id: 'savedImage_' + loadImage[j].name,
+ src: loadImage[j].src,
+ title: loadImage[j].name,
+ style: ' border: solid ' + ((j==0)?'3pt #F00':'1pt') + ';' +
+ ' width: ' + ((j==0)?realW-30:realW/3-10) + ';' +
+ ' background-image: url(http://open2ch.net/image/oekaki/background.png)'
+ }));
+ ($('#tab-saved-image-' + m)).append(a);
+ }
+ }
+ $('#savedImageTab').tabs('refresh');
+console.log('loadImageEnd');
}
-
-
var correctionLv = 8;
var interval = 40;
var interpolate = 4;
@@ -249,30 +212,16 @@
var menu = $('<div>', {id: 'menu'}).append(
$('<ul>').append(
- $('<li>').append(
- $('<a>', {href: '#tab-kaku'}).append($('label[for=kaku]'))
- ),
- $('<li>').append(
- $('<a>', {href: '#tab-curve'})
- ),
- $('<li>').append(
- $('<a>', {href: '#tab-kesu'}).append($('label[for=kesu]'))
- ),
- $('<li>').append(
- $('<a>', {href: '#tab-spoit'}).append($('label[for=spoit]'))
- ),
- $('<li>').append(
- $('<a>', {href: '#tab-fill'})
- ),
- $('<li>').append(
- $('<a>', {href: '#tab-moji'})
- ),
- $('<li>').append(
- $('<a>', {href: '#tab-figure'})
- ),
- $('<li>').append(
- $('<a>', {href: '#tab-selection'})
- )
+ $('<li>').append($('<a>', {href: '#tab-kaku'}).append($('label[for=kaku]'))),
+ $('<li>').append($('<a>', {href: '#tab-curve'})),
+ $('<li>').append($('<a>', {href: '#tab-kesu'}).append($('label[for=kesu]'))),
+ $('<li>').append($('<a>', {href: '#tab-spoit'}).append($('label[for=spoit]'))),
+ $('<li>').append($('<a>', {href: '#tab-fill'})),
+ $('<li>').append($('<a>', {href: '#tab-moji'})),
+ $('<li>').append($('<a>', {href: '#tab-figure'})),
+ $('<li>').append($('<a>', {href: '#tab-selection'})),
+ $('<li>').append($('<a>', {href: '#tab-save'}))
+// $('<li>').append($('<a>', {href: '#tab-settings'}))
),
$('<div>', {id: 'tab-kaku'}),
$('<div>', {id: 'tab-curve'}),
@@ -281,7 +230,9 @@
$('<div>', {id: 'tab-fill'}),
$('<div>', {id: 'tab-moji'}),
$('<div>', {id: 'tab-figure'}),
- $('<div>', {id: 'tab-selection'})
+ $('<div>', {id: 'tab-slection'}),
+ $('<div>', {id: 'tab-save'})
+// $('<div>', {id: 'tab-settings'})
).tabs();
$('#upImage').after(menu);
@@ -291,9 +242,6 @@
function makeMenuElement(){
$('#_canvas').attr('style', 'position: relative');
- loadIcon(icons);
-
-
var scaleSize = [50, 75, 100, 125, 150, 200, 250, 300, 400, 500];
var scaleSelect = $('<select>', {
id: 'canvasScale',
@@ -308,18 +256,14 @@
}
$('#canvasSize').after(scaleSelect).after($('<b>').text('x'));
-
var penType = ['ブラシ','鉛筆'];
- var penSelect = $('<select>', {
- id: 'penType'
- });
+ var penSelect = $('<select>', {id: 'penType'});
for(var i in penType){
$('<option>', {
value: i,
text: penType[i],
}).appendTo(penSelect);
}
-
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];
var penSizeSelect = $('#psize');
penSizeSelect.children().remove();
@@ -331,11 +275,8 @@
}).appendTo(penSizeSelect);
}
-
var curveImg = $('#curveIcon');
curveImg[0].style.display = '';
- $('a[href=#tab-curve]').append(curveImg);
-
var corrections = [2, 4, 8, 16, 32, 64];
var correctionLvText = $('<b>', {text: '補正レベル'});
var correctionSelect = $('<select>', {
@@ -349,7 +290,6 @@
selected: (i==2)?true:false
}).appendTo(correctionSelect);
}
-
var intervals = [5, 10, 20, 40, 80, 120, 160];
var intervalText = $('<b>', {text: ' 粒度'});
var intervalSelect = $('<select>', {
@@ -363,7 +303,6 @@
selected: (i==3)?true:false
}).appendTo(intervalSelect);
}
-
var interpolates = [2, 4, 8, 12, 16];
var interpolateText = $('<b>', {text: ' なめらかさ'});
var interpolateSelect = $('<select>', {
@@ -377,7 +316,6 @@
selected: (i==1)?true:false
}).appendTo(interpolateSelect);
}
-
var controllPointText = $('<b>', {text: ' 制御点表示:'});
var controllPointCheck = $('<input>', {
id: 'controllPoint',
@@ -385,18 +323,13 @@
checked: showPointFlag,
click: function(){showPointFlag = $(this)[0].checked}
});
-
var curveOption = $('<div>', {id: 'curveOption'})
- .append(correctionLvText)
- .append(correctionSelect)
- .append(intervalText)
- .append(intervalSelect)
- .append(interpolateText)
- .append(interpolateSelect)
- .append(controllPointText)
- .append(controllPointCheck);
+ .append(correctionLvText) .append(correctionSelect)
+ .append(intervalText) .append(intervalSelect)
+ .append(interpolateText) .append(interpolateSelect)
+ .append(controllPointText).append(controllPointCheck);
$('#tab-curve').append(curveOption);
-
+ $('a[href=#tab-curve]').append(curveImg);
var fillImg = $('<img>', {
id: 'fillImg',
@@ -404,16 +337,11 @@
});
$('a[href=#tab-fill]').append(fillImg);
-
var mojiImg = $('#mojiIcon');
mojiImg[0].style.display = '';
- $('a[href=#tab-moji]').append(mojiImg);
-
var mojiSize = [4, 8, 10, 12, 14, 16, 18, 20, 24, 28, 32, 36, 40, 48, 56, 64, 72, 80, 100];
var mojiSizeText = $('<b>', {text: '文字サイズ:'});
- var mojiSizeSelect = $('<select>', {
- id: 'mojiSize'
- });
+ var mojiSizeSelect = $('<select>', {id: 'mojiSize'});
for(var i in mojiSize){
$('<option>', {
value: mojiSize[i],
@@ -421,40 +349,34 @@
selected: (i==7)?true:false
}).appendTo(mojiSizeSelect);
}
-
var fontType = ['ゴシック','明朝','筆記体','装飾','等幅'];
var fontTypeText = $('<b>', {text: ' フォント:'});
- var fontTypeSelect = $('<select>', {
- id: 'mojiFont'
- });
+ var fontTypeSelect = $('<select>', {id: 'mojiFont'});
for(var i in fontType){
$('<option>', {
value: i,
text: fontType[i],
}).appendTo(fontTypeSelect);
}
-
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 mojiOption = $('<div>', {id: 'mojiOption'})
.append(mojiSizeText).append(mojiSizeSelect)
.append(fontTypeText).append(fontTypeSelect)
- .append(boldText).append(boldCheck)
- .append(italicText).append(italicCheck);
+ .append(boldText) .append(boldCheck)
+ .append(italicText) .append(italicCheck);
$('#tab-moji').append(mojiOption);
-
+ $('a[href=#tab-moji]').append(mojiImg);
var figureImg = $('#figureIcon');
figureImg[0].style.display = '';
@@ -462,30 +384,22 @@
var figureType = ['-','□','■','○','●'];
var figureTypeText = $('<b>', {text: '図形:'});
- var figureTypeSelect = $('<select>', {
- id: 'figureType'
- });
+ var figureTypeSelect = $('<select>', {id: 'figureType'});
for(var i in figureType){
$('<option>', {
value: i,
text: figureType[i],
}).appendTo(figureTypeSelect);
}
-
var figureOption = $('<div>', {id: 'figureOption'})
.append(figureTypeText).append(figureTypeSelect);
$('#tab-figure').append(figureOption);
-
var selectionImg = $('#selectionIcon');
selectionImg[0].style.display = '';
- $('a[href=#tab-selection]').append(selectionImg);
-
var selectionTypeText = $('<b>', {text: '動作'});
var selectionType = ['切り取り','コピー'];
- var selectionTypeSelect = $('<select>', {
- id: 'selectionType'
- });
+ var selectionTypeSelect = $('<select>', {id: 'selectionType'});
for(var i in selectionType){
$('<option>', {
value: i,
@@ -495,7 +409,89 @@
var selectionOption = $('<div>', {id: 'selectionOption'})
.append(selectionTypeText).append(selectionTypeSelect);
$('#tab-selection').append(selectionOption);
+ $('a[href=#tab-selection]').append(selectionImg);
+ var saveImg = $('#saveIcon');
+ saveImg[0].style.display = '';
+ var saveMaxAgeText = $('<b>', {text: '保存数:'});
+ var saveMaxAge = [1, 2, 3];
+ var saveMaxAgeSelect = $('<select>', {
+ id: 'saveMaxAge',
+ change: function(){
+ settings.saveMaxAge = $(this).val();
+ saveSettings();
+ }
+ });
+ for(var i in saveMaxAge){
+ $('<option>', {
+ value: saveMaxAge[i],
+ text: saveMaxAge[i],
+ selected: (saveMaxAge[i]==settings.saveMaxAge)?true:false,
+ }).appendTo(saveMaxAgeSelect);
+ }
+ var saveCycleText = $('<b>', {text: ' 間隔:'});
+ var saveCycle = ['任意', '1', '3', '5', '10', '15', '20', '30'];
+ var saveCycleSelect = $('<select>', {
+ id: 'saveCycle',
+ change: function(){
+ settings.saveCycle = $(this).val();
+ saveSettings();
+ }
+ });
+ for(var i in saveCycle){
+ $('<option>', {
+ value: saveCycle[i],
+ text: saveCycle[i] + ((i==0)? '':'分'),
+ selected: (saveCycle[i]==settings.saveCycle)?true:false,
+ }).appendTo(saveCycleSelect);
+ }
+ var saveOption = $('<div>', {id: 'saveOption'})
+ .append(saveMaxAgeText).append(saveMaxAgeSelect)
+ .append(saveCycleText).append(saveCycleSelect);
+ $('#tab-save').append(saveOption);
+ $('a[href=#tab-save]').append(saveImg);
+
+ var reloadImg = $('#reloadIcon');
+ reloadImg[0].style.display = '';
+ var savedImageTab = $('<div>', {id: 'savedImageTab'}).append(
+ $('<ul>', {id: 'savedImageTabList'}).append(
+ $('<li>').append($('<a>', {
+ href: '#tab-saved-image-reload',
+ click: loadSavedImages
+ }).append(reloadImg))
+ ),
+ $('<div>', {id: 'tab-saved-image-reload'})
+ ).tabs();
+ $('#tab-save').append(savedImageTab);
+
+ var curveA = $('<a>', {href: '#sketch', 'data-tool': 'curve'});
+ var mojiA = $('<a>', {href: '#sketch', 'data-tool': 'moji'});
+ var fillA = $('<a>', {href: '#sketch', 'data-tool': 'fill'});
+ var figureA = $('<a>', {href: '#sketch', 'data-tool': 'figure'});
+ var selectionA = $('<a>', {href: '#sketch', 'data-tool': 'selection'});
+ var saveA = $('<a>', {href: '#sketch', 'data-tool': 'save'});
+ var settingsA = $('<a>', {href: '#sketch', 'data-tool': 'settings'});
+ $('.tools').after(curveA).after(fillA).after(mojiA).after(figureA)
+ .after(selectionA).after(saveA).after(settingsA);
+
+ $('a[href=#tab-kaku]') .click(function(){$('[data-tool=marker]').click()});
+ $('a[href=#tab-curve]') .click(function(){$('[data-tool=curve]').click()});
+ $('a[href=#tab-kesu]') .click(function(){$('[data-tool=eraser]').click()});
+ $('a[href=#tab-spoit]') .click(function(){$('[data-tool=spoit]').click()});
+ $('a[href=#tab-moji]') .click(function(){$('[data-tool=moji]').click()});
+ $('a[href=#tab-fill]') .click(function(){$('[data-tool=fill]').click()});
+ $('a[href=#tab-figure]') .click(function(){$('[data-tool=figure]').click()});
+ $('a[href=#tab-selection]').click(function(){$('[data-tool=selection]').click()});
+ $('a[href=#tab-save]') .click(function(){
+ $('[data-tool=save]').click();
+ $('a[href=#tab-saved-image-reload]').click();
+ autoSave = false;
+ });
+ $('a[href=#tab-settings]') .click(function(){$('[data-tool=settings]').click()});
+ $('[data-tool]').click(function(){
+ fixPreview();
+ autoSave = (settings.saveCycle=='任意')?false:true;
+ });
var goButton = $('<input>', {
type: 'button',
@@ -506,44 +502,8 @@
canvas.redraw();
}
});
-
$('#backButton').after(goButton);
-
- var curveA = $('<a>', {
- href: '#sketch',
- 'data-tool': 'curve'
- });
- var mojiA = $('<a>', {
- href: '#sketch',
- 'data-tool': 'moji'
- });
- var fillA = $('<a>', {
- href: '#sketch',
- 'data-tool': 'fill'
- });
- var figureA = $('<a>', {
- href: '#sketch',
- 'data-tool': 'figure'
- });
- var selectionA = $('<a>', {
- href: '#sketch',
- 'data-tool': 'selection'
- });
- $('.tools').after(curveA).after(fillA).after(mojiA).after(figureA).after(selectionA);
-
- $('a[href=#tab-kaku]').click(function(){$('[data-tool=marker]').click()});
- $('a[href=#tab-curve]').click(function(){$('[data-tool=curve]').click()});
- $('a[href=#tab-kesu]').click(function(){$('[data-tool=eraser]').click()});
- $('a[href=#tab-spoit]').click(function(){$('[data-tool=spoit]').click()});
- $('a[href=#tab-moji]').click(function(){$('[data-tool=moji]').click()});
- $('a[href=#tab-fill]').click(function(){$('[data-tool=fill]').click()});
- $('a[href=#tab-figure]').click(function(){$('[data-tool=figure]').click()});
- $('a[href=#tab-selection]').click(function(){$('[data-tool=selection]').click()});
-
- $('[data-tool]').click(function(){fixPreview();});
-
-
var exportButton = $('<input>', {
id: 'exportButton',
type: 'button',
@@ -579,27 +539,13 @@
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 layerText = $('<b>', {text: '[レイヤ]:'});
var mergeLayerButton = $('<input>', {
id: 'mergeLayerButton',
type: 'button',
value: '結合',
- click: function(){mergeLayer()}
+ click: function(){mergeLayer(canvas)}
});
$('#_canvas').after(layerTool);
// layerTool.append(mergeLayerButton);
@@ -742,7 +688,7 @@
canvas.layerNum = newLayerNum;
layers[oldLayerNum].actions = canvas.actions;
layers[oldLayerNum].bgcolor = canvas.bgcolor;
-// layers[oldLayerNum].baseImageURL = canvas.baseImageURL;
+ layers[oldLayerNum].baseImageURL = canvas.baseImageURL;
canvas.el = layers[newLayerNum].canvas;
canvas.bgcolor = layers[newLayerNum].bgcolor;
canvas.baseImageURL = layers[newLayerNum].baseImageURL;
@@ -851,14 +797,15 @@
});
}
-function mergeLayer(){
- if(layerOnFlag){
+function mergeLayer(mergeCanvas){
+ if(settings.layerOn){
updatePreview();
- canvas.context.clearRect(0, 0, canvas.el.width, canvas.el.height);
+ var context = mergeCanvas.getContext('2d');
+ context.clearRect(0, 0, realW, realH);
$('canvas[id^=preview]').each(function(i){
if(this.displayed){
- canvas.context.drawImage($(this)[0], 0, 0, canvas.el.width, canvas.el.height);
+ context.drawImage($(this)[0], 0, 0, realW, realH);
}
});
}
@@ -903,15 +850,14 @@
this.context.strokeStyle = action.color;
this.context.lineWidth = action.size;
this.context.stroke();
- //showPoints(action.events, 'rgb(0,0,255)', 0.1);
}
};
-var timer = '';
function startCurvePainting(e){
try{
- if(timer){
- clearInterval(timer);
+ if(drawTimer){
+ clearInterval(drawTimer);
+ drawTimer= '';
}
canvas.painting = true;
canvas.action = {
@@ -923,7 +869,7 @@
}
setPoint(e);
getPoint();
- timer = setInterval(getPoint, interval);
+ drawTimer = setInterval(getPoint, interval);
}catch(ex){
console.log('Exception' + ex);
stopCurvePainting(e);
@@ -938,8 +884,8 @@
canvas.action.events = ss;
canvas.actions.push(canvas.action);
}
- clearInterval(timer);
- timer = '';
+ clearInterval(drawTimer);
+ drawTimer = '';
canvas.painting = false;
canvas.action = null;
@@ -1016,7 +962,6 @@
for(var i = 0; i < points.length; i++){
var point = points[i];
-
canvas.context.lineWidth = 2;
canvas.context.beginPath();
canvas.context.strokeStyle = color;
@@ -1029,7 +974,6 @@
var fillCanvas;
var seeds;
-
$.sketch.tools.fill= {
onEvent: function(e) {
switch (e.type) {
@@ -1103,9 +1047,7 @@
}else{
alpha = alphaToInt(fillRGBA[3]);
}
-
var fillColor = ((Number(fillRGBA[0]) << 24) + (Number(fillRGBA[1]) << 16) + (Number(fillRGBA[2]) << 8) + alpha)>>>0;
- //var targetColor = getRGBA(pos.x, pos.y);
canvas.actions.push({
x: Math.floor(pos.x),
@@ -1115,7 +1057,7 @@
});
canvas.redraw();
- if(layerOnFlag){updatePreview();}
+ if(settings.layerOn) updatePreview();
}
function paint(x, y, fillColor, targetColor){
@@ -1250,8 +1192,6 @@
return;
}
- var pos = getPosition(e);
-
var text = window.prompt("文字を入力。", "");
if(!text) return;
@@ -1286,6 +1226,8 @@
var mojiItalic = ' ';
}
+ var pos = getPosition(e);
+
canvas.preview = {
x: pos.x,
y: pos.y,
@@ -1346,10 +1288,7 @@
}
});
- return {
- w: maxW,
- h: maxH
- }
+ return {w: maxW, h: maxH}
}
function movePreview(context, preview, size){
@@ -1361,7 +1300,12 @@
id: 'moveCanvas',
width: size.w + MARGIN,
height: size.h + MARGIN,
- style: 'border:' + border + 'pt dotted #666; position:absolute; top: ' + (top - (MARGIN + border)/2) + '; left: ' + (left - (MARGIN + border)/2) + '; width: ' + size.w * scale + '; height: ' + size.h * scale + ';z-index:10; cursor: move'
+ style: 'border:' + border + 'pt dotted #666; position:absolute; ' +
+ 'top: ' + (top - (MARGIN + border)/2) + '; ' +
+ 'left: ' + (left - (MARGIN + border)/2) + '; ' +
+ 'width: ' + size.w * scale + '; ' +
+ 'height: ' + size.h * scale + '; ' +
+ 'z-index:10; cursor: move'
});
var tmpImg = context.getImageData(left/scale, top/scale, size.w + MARGIN, size.h + MARGIN);
@@ -1374,7 +1318,10 @@
id: 'rotateCanvas',
width: rotateImg.width,
height: rotateImg.height,
- style: 'position:absolute; top: ' + ((top - (MARGIN + border)/2) - rotateImg.height) + '; left: ' + ((left - (MARGIN + border)/2) + moveCanvas.width()/2 - rotateImg.width/2) + '; z-index:11; cursor:pointer;'
+ style: 'position:absolute; ' +
+ 'top: ' + ((top - (MARGIN + border)/2) - rotateImg.height) + '; ' +
+ 'left: ' + ((left - (MARGIN + border)/2) + moveCanvas.width()/2 - rotateImg.width/2) + '; ' +
+ 'z-index:11; cursor:pointer;'
});
rotateCanvas[0].getContext('2d').drawImage(rotateImg, 0, 0, rotateImg.width, rotateImg.height);
if(!canvas.selection){$('#sketch').before(rotateCanvas);}
@@ -1400,12 +1347,10 @@
if(!canvas.move) return;
var pos = getPosition(e.originalEvent);
-
var mx = this.style.left.replace('px', '');
var my = this.style.top.replace('px', '');
var rx = rotateCanvas[0].style.left.replace('px', '');
var ry = rotateCanvas[0].style.top.replace('px', '');
-
var ox = canvas.move.x;
var oy = canvas.move.y;
var odx = (pos.x - ox)*scale;
@@ -1474,7 +1419,7 @@
$('#moveCanvas').remove();
$('#rotateCanvas').remove();
canvas.redraw();
- if(layerOnFlag){updatePreview();}
+ if(settings.layerOn) updatePreview();
}
@@ -1574,7 +1519,7 @@
canvas.preview = null;
tmpCtx.clearRect(0, 0, canvas.el.width, canvas.el.height);
canvas.redraw();
- if(layerOnFlag){updatePreview();}
+ if(settings.layerOn) updatePreview();
}
}
@@ -1675,16 +1620,6 @@
}
function drawSelection(context, action){
-/*
- switch(action.type){
- case '0': //切り抜き
- context.clearRect(action.sx, action.sy, action.img.width, action.img.height);
- break;
- case '1': //コピー
-
- break;
- }
-*/
context.translate(action.x + action.img.width/2, action.y + action.img.heihgt/2);
context.rotate(action.deg * Math.PI/180);
context.putImageData(action.img, action.x, action.y);
@@ -1707,10 +1642,7 @@
var x = parseFloat(pageX - offsetX) / scale;
var y = parseFloat(pageY - offsetY) / scale;
- return {
- x: x,
- y: y
- };
+ return {x: x, y: y};
}
function setCanvasScale(){
@@ -1751,6 +1683,24 @@
canvas.el.style.msTransform = 'rotateZ(' + deg + 'deg)';
}
+$.sketch.tools.save = {
+ onEvent: function(){
+ //console.log('save onEvent');
+ },
+ draw: function(){
+ //console.log('save draw')
+ }
+}
+
+$.sketch.tools.settings = {
+ onEvent: function(){
+ //
+ },
+ draw: function(){
+ //
+ }
+}
+
function loadIcon(icons){
var baseUrl = 'https://googledrive.com/host/0B1BW1N6rqpWFa0lTUW1aZThuT28/';
@@ -1785,7 +1735,7 @@
function changeAction(popList, pushList){
pushList.push(popList.pop());
canvas.redraw();
- if(layerOnFlag){updatePreview();}
+ if(settings.layerOn) updatePreview();
}
@@ -1812,7 +1762,6 @@
}
}
sketch = this;
-// this.context.scale(1/scale, 1/scale);
$.each(this.actions, function() {
if (this.tool) {
return $.sketch.tools[this.tool].draw.call(sketch, this);
@@ -1821,7 +1770,6 @@
if (this.painting && this.action) {
return $.sketch.tools[this.action.tool].draw.call(sketch, this.action);
}
-// this.context.scale(scale, scale);
};
canvas.stopPainting = function(){
@@ -1830,7 +1778,7 @@
}
this.painting = false;
this.action = null;
- if(layerOnFlag){updatePreview();}
+ if(settings.layerOn) updatePreview();
};
$.sketch.tools.marker = {
@@ -1913,11 +1861,25 @@
changeCanvasScale();
});
+setFile = function(file) {
+ var img = new Image();
+ var fileReader = new FileReader();
+ fileReader.onload = function(event) {
+ $(img).attr('src', event.target.result);
+ }
+ fileReader.readAsDataURL(file);
+ img.onload = function() {
+ fitImage(canvas.context, img);
+ canvas.setBaseImageURL(canvas.el.toDataURL());
+ isOekakiDone = 1;
+ };
+}
+
$('#submit_button').click(function(){
if(isOekakiDone){
addLayer();
fixPreview();
- mergeLayer();
+ mergeLayer(canvas.el);
var imgData = canvas.context.getImageData(0, 0, canvas.el.width, canvas.el.height);
/*
* @title open2chOekakiEX
* @description おーぷん2ちゃんお絵かき機能拡張ブックマークレット
* @require https://googledrive.com/host/0B1BW1N6rqpWFNjdEazFaNm1XSjA/jquery-ui-1.10.4.custom.min.js
* @require https://googledrive.com/host/0B1BW1N6rqpWFR2NCRFFUbmJzN0U/jquery-ui-1.10.4.custom.min.css
* @require https://googledrive.com/host/0B1BW1N6rqpWFNjdEazFaNm1XSjA/spline.js
* @require https://googledrive.com/host/0B1BW1N6rqpWFNjdEazFaNm1XSjA/replay.js
* @require https://googledrive.com/host/0B1BW1N6rqpWFNjdEazFaNm1XSjA/version.js
* @require https://googledrive.com/host/0B1BW1N6rqpWFNjdEazFaNm1XSjA/manual.js
* @private
*/
//【更新履歴】
var VERSION= 'Ver9.0.0';
var PREVIEW_SIZE = 0.2;
var MARGIN = 0;
var settings = {
version: localStorage.getItem('version') || 'Ver0.0.0',
checkVersion: localStorage.getItem('checkVersion') || 1,
saveType: localStorage.getItem('saveType') || 1,
saveCycle: localStorage.getItem('saveCycle') || 10,
saveMaxAge: localStorage.getItem('saveMaxAge') || 2,
layerOn: localStorage.getItem('layerOn') || 1
}
var savedImages;
var canvas = $('#sketch').sketch();
var drawRedo = [];
var layers = [];
var scale;
var realW;
var realH;
var scaleW;
var scaleH;
var degree;
var icons = {
rotateIcon: 'rotate2.png',
curveIcon: 'curve.png',
mojiIcon: 'moji.png',
figureIcon: 'figure.png',
selectionIcon: 'selection.png',
saveIcon: 'save.png',
settingsIcon: 'settings.png',
rotateRightIcon: 'rotateRight.png',
rotateLeftIcon: 'rotateLeft.png',
reloadIcon: 'reload.png'
};
loadIcon(icons);
var browser = checkBrowser();
checkNewVersion();
initMenu();
initLayerTool();
initManual();
setCanvasScale();
var drawTimer = '';
var saveTimer = '';
startAutoSave();
function startAutoSave(){
clearInterval(saveTimer);
if(settings.saveCycle=='任意'){
autoSave = false;
saveTimer = '';
}else{
autoSave = true;
saveTimer = setInterval(saveImage, settings.saveCycle * 60 * 1000);
}
}
function checkBrowser(){
var ua = window.navigator.userAgent.toLowerCase();
var ver = window.navigator.appVersion.toLowerCase();
var name = '';
if(ua.indexOf('msie') != -1){
if (ver.indexOf('6.') != -1) {name = 'ie6';}
else if(ver.indexOf('7.') != -1) {name = 'ie7';}
else if(ver.indexOf('8.') != -1) {name = 'ie8';}
else if(ver.indexOf('9.') != -1) {name = 'ie9';}
else if(ver.indexOf('10.') != -1) {name = 'ie10';}
else {name = 'ie';}
}else if(ua.indexOf('trident/7') != -1){name = 'ie11';}
else if(ua.indexOf('chrome') != -1) {name = 'chrome';}
else if(ua.indexOf('safari') != -1) {name = 'safari';}
else if(ua.indexOf('opera') != -1) {name = 'opera';}
else if(ua.indexOf('firefox') != -1) {name = 'firefox';
}
return name;
}
function checkNewVersion(){
if(settings.checkVersion && settings.version != VERSION){
localStorage.setItem('version', VERSION);
alert(VERSION + ' ' + VERSION_INFO[VERSION].Date + ' ' + VERSION_INFO[VERSION].Info);
}
}
function saveSettings(){
for(var key in settings){
localStorage.setItem(key, settings[key]);
}
startAutoSave();
}
$('#saveButton').unbind();
$('#saveButton').click(function(){
saveImage('manual');
loadSavedImages();
});
function saveImage(type){
console.log('saveImageStart');
if(!autoSave && !type) return;
var saveNum = parseInt(localStorage.getItem('saveNum')) + 1 || 1;
if(saveNum > settings.saveMaxAge) saveNum = 1;
var date = new Date();
var name = [
date.getFullYear(),
('0' + (date.getMonth() + 1)).slice(-2),
('0' + date.getDate()).slice(-2)
].join( '-' ) + ' ' +
('0' + date.getHours()).slice(-2) + ':' +
('0' + date.getMinutes()).slice(-2) + ':' +
('0' + date.getSeconds()).slice(-2);
var mergeCanvas = $('<canvas>').attr({
width: realW,
height: realH
});
var ctx = mergeCanvas[0].getContext('2d');
var saveImages = [];
$('canvas[id^=preview]').each(function(i){
saveImages.push({
name: name + '_layer' + (i+1),
src: $(this)[0].toDataURL()
});
ctx.drawImage($(this)[0], 0, 0);
});
saveImages.unshift({
name: name,
src: mergeCanvas[0].toDataURL()
});
localStorage.setItem('saveNum', saveNum);
localStorage.setItem('savedImage' + saveNum, JSON.stringify(saveImages));
console.log('saveImageEnd');
}
function loadSavedImages(){
console.log('loadImageStart');
var loadImages = [];
for(var i = 1; i <= settings.saveMaxAge; i++){
var s = localStorage.getItem('savedImage' + i);
var loadImage = JSON.parse(s);
if(!loadImage) break;
loadImages.push(loadImage);
}
if(!loadImages.length > 0) return;
for(var i in loadImages){
var m = parseInt(i) + 1;
var tabName = loadImages[i][0].name.replace(/\_.*/, '');
var loadImage = loadImages[i];
$('#savedImage_' + m).remove();
$('#savedImageTabList').append(
$('<li>', {id: 'savedImage_' + m}).append($('<a>', {href: '#tab-saved-image-' + m, text: tabName.slice(0, 16)}))
);
$('#tab-saved-image-' + m).remove();
$('#savedImageTab').append($('<div>', {id: 'tab-saved-image-' + m}));
for(var j in loadImage){
var a = $('<a>', {
id: 'downloadLink_' + loadImage[j].name,
download: loadImage[j].name + '.png',
href: loadImage[j].src,
}).append(
$('<img>', {
id: 'savedImage_' + loadImage[j].name,
src: loadImage[j].src,
title: loadImage[j].name,
style: ' border: solid ' + ((j==0)?'3pt #F00':'1pt') + ';' +
' width: ' + ((j==0)?realW-30:realW/3-10) + ';' +
' background-image: url(http://open2ch.net/image/oekaki/background.png)'
}));
($('#tab-saved-image-' + m)).append(a);
}
}
$('#savedImageTab').tabs('refresh');
console.log('loadImageEnd');
}
var correctionLv = 8;
var interval = 40;
var interpolate = 4;
var limA = -0.8;
var showPointFlag = false;
function initMenu(){
$('[name=pmode]').hide();
var menu = $('<div>', {id: 'menu'}).append(
$('<ul>').append(
$('<li>').append($('<a>', {href: '#tab-kaku'}).append($('label[for=kaku]'))),
$('<li>').append($('<a>', {href: '#tab-curve'})),
$('<li>').append($('<a>', {href: '#tab-kesu'}).append($('label[for=kesu]'))),
$('<li>').append($('<a>', {href: '#tab-spoit'}).append($('label[for=spoit]'))),
$('<li>').append($('<a>', {href: '#tab-fill'})),
$('<li>').append($('<a>', {href: '#tab-moji'})),
$('<li>').append($('<a>', {href: '#tab-figure'})),
$('<li>').append($('<a>', {href: '#tab-selection'})),
$('<li>').append($('<a>', {href: '#tab-save'}))
// $('<li>').append($('<a>', {href: '#tab-settings'}))
),
$('<div>', {id: 'tab-kaku'}),
$('<div>', {id: 'tab-curve'}),
$('<div>', {id: 'tab-kesu'}),
$('<div>', {id: 'tab-spoit'}),
$('<div>', {id: 'tab-fill'}),
$('<div>', {id: 'tab-moji'}),
$('<div>', {id: 'tab-figure'}),
$('<div>', {id: 'tab-slection'}),
$('<div>', {id: 'tab-save'})
// $('<div>', {id: 'tab-settings'})
).tabs();
$('#upImage').after(menu);
makeMenuElement();
}
function makeMenuElement(){
$('#_canvas').attr('style', 'position: relative');
var scaleSize = [50, 75, 100, 125, 150, 200, 250, 300, 400, 500];
var scaleSelect = $('<select>', {
id: 'canvasScale',
change: changeCanvasScale
});
for(var i in scaleSize){
$('<option>', {
value: scaleSize[i] / 100,
text: scaleSize[i] + '%',
selected: (i==2)?true:false
}).appendTo(scaleSelect);
}
$('#canvasSize').after(scaleSelect).after($('<b>').text('x'));
var penType = ['ブラシ','鉛筆'];
var penSelect = $('<select>', {id: 'penType'});
for(var i in penType){
$('<option>', {
value: i,
text: penType[i],
}).appendTo(penSelect);
}
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];
var penSizeSelect = $('#psize');
penSizeSelect.children().remove();
for(var i in penSize){
$('<option>', {
value: penSize[i],
text: penSize[i],
selected: (i==2)?true:false
}).appendTo(penSizeSelect);
}
var curveImg = $('#curveIcon');
curveImg[0].style.display = '';
var corrections = [2, 4, 8, 16, 32, 64];
var correctionLvText = $('<b>', {text: '補正レベル'});
var correctionSelect = $('<select>', {
id: 'correctionLv',
change: function(){correctionLv = $(this).val();}
});
for(var i in corrections){
$('<option>', {
value: corrections[i],
text: parseInt(i)+1,
selected: (i==2)?true:false
}).appendTo(correctionSelect);
}
var intervals = [5, 10, 20, 40, 80, 120, 160];
var intervalText = $('<b>', {text: ' 粒度'});
var intervalSelect = $('<select>', {
id: 'interval',
change: function(){interval = $(this).val();}
});
for(var i in intervals){
$('<option>', {
value: intervals[i],
text: intervals[i],
selected: (i==3)?true:false
}).appendTo(intervalSelect);
}
var interpolates = [2, 4, 8, 12, 16];
var interpolateText = $('<b>', {text: ' なめらかさ'});
var interpolateSelect = $('<select>', {
id: 'interpolate',
change: function(){interpolate = $(this).val();}
});
for(var i in interpolates){
$('<option>', {
value: interpolates[i],
text: interpolates[i],
selected: (i==1)?true:false
}).appendTo(interpolateSelect);
}
var controllPointText = $('<b>', {text: ' 制御点表示:'});
var controllPointCheck = $('<input>', {
id: 'controllPoint',
type: 'checkbox',
checked: showPointFlag,
click: function(){showPointFlag = $(this)[0].checked}
});
var curveOption = $('<div>', {id: 'curveOption'})
.append(correctionLvText) .append(correctionSelect)
.append(intervalText) .append(intervalSelect)
.append(interpolateText) .append(interpolateSelect)
.append(controllPointText).append(controllPointCheck);
$('#tab-curve').append(curveOption);
$('a[href=#tab-curve]').append(curveImg);
var fillImg = $('<img>', {
id: 'fillImg',
src: 'http://image.open2ch.net/image/oekaki/nuri.png',
});
$('a[href=#tab-fill]').append(fillImg);
var mojiImg = $('#mojiIcon');
mojiImg[0].style.display = '';
var mojiSize = [4, 8, 10, 12, 14, 16, 18, 20, 24, 28, 32, 36, 40, 48, 56, 64, 72, 80, 100];
var mojiSizeText = $('<b>', {text: '文字サイズ:'});
var mojiSizeSelect = $('<select>', {id: 'mojiSize'});
for(var i in mojiSize){
$('<option>', {
value: mojiSize[i],
text: mojiSize[i],
selected: (i==7)?true:false
}).appendTo(mojiSizeSelect);
}
var fontType = ['ゴシック','明朝','筆記体','装飾','等幅'];
var fontTypeText = $('<b>', {text: ' フォント:'});
var fontTypeSelect = $('<select>', {id: 'mojiFont'});
for(var i in fontType){
$('<option>', {
value: i,
text: fontType[i],
}).appendTo(fontTypeSelect);
}
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 mojiOption = $('<div>', {id: 'mojiOption'})
.append(mojiSizeText).append(mojiSizeSelect)
.append(fontTypeText).append(fontTypeSelect)
.append(boldText) .append(boldCheck)
.append(italicText) .append(italicCheck);
$('#tab-moji').append(mojiOption);
$('a[href=#tab-moji]').append(mojiImg);
var figureImg = $('#figureIcon');
figureImg[0].style.display = '';
$('a[href=#tab-figure]').append(figureImg);
var figureType = ['-','□','■','○','●'];
var figureTypeText = $('<b>', {text: '図形:'});
var figureTypeSelect = $('<select>', {id: 'figureType'});
for(var i in figureType){
$('<option>', {
value: i,
text: figureType[i],
}).appendTo(figureTypeSelect);
}
var figureOption = $('<div>', {id: 'figureOption'})
.append(figureTypeText).append(figureTypeSelect);
$('#tab-figure').append(figureOption);
var selectionImg = $('#selectionIcon');
selectionImg[0].style.display = '';
var selectionTypeText = $('<b>', {text: '動作'});
var selectionType = ['切り取り','コピー'];
var selectionTypeSelect = $('<select>', {id: 'selectionType'});
for(var i in selectionType){
$('<option>', {
value: i,
text: selectionType[i],
}).appendTo(selectionTypeSelect);
}
var selectionOption = $('<div>', {id: 'selectionOption'})
.append(selectionTypeText).append(selectionTypeSelect);
$('#tab-selection').append(selectionOption);
$('a[href=#tab-selection]').append(selectionImg);
var saveImg = $('#saveIcon');
saveImg[0].style.display = '';
var saveMaxAgeText = $('<b>', {text: '保存数:'});
var saveMaxAge = [1, 2, 3];
var saveMaxAgeSelect = $('<select>', {
id: 'saveMaxAge',
change: function(){
settings.saveMaxAge = $(this).val();
saveSettings();
}
});
for(var i in saveMaxAge){
$('<option>', {
value: saveMaxAge[i],
text: saveMaxAge[i],
selected: (saveMaxAge[i]==settings.saveMaxAge)?true:false,
}).appendTo(saveMaxAgeSelect);
}
var saveCycleText = $('<b>', {text: ' 間隔:'});
var saveCycle = ['任意', '1', '3', '5', '10', '15', '20', '30'];
var saveCycleSelect = $('<select>', {
id: 'saveCycle',
change: function(){
settings.saveCycle = $(this).val();
saveSettings();
}
});
for(var i in saveCycle){
$('<option>', {
value: saveCycle[i],
text: saveCycle[i] + ((i==0)? '':'分'),
selected: (saveCycle[i]==settings.saveCycle)?true:false,
}).appendTo(saveCycleSelect);
}
var saveOption = $('<div>', {id: 'saveOption'})
.append(saveMaxAgeText).append(saveMaxAgeSelect)
.append(saveCycleText).append(saveCycleSelect);
$('#tab-save').append(saveOption);
$('a[href=#tab-save]').append(saveImg);
var reloadImg = $('#reloadIcon');
reloadImg[0].style.display = '';
var savedImageTab = $('<div>', {id: 'savedImageTab'}).append(
$('<ul>', {id: 'savedImageTabList'}).append(
$('<li>').append($('<a>', {
href: '#tab-saved-image-reload',
click: loadSavedImages
}).append(reloadImg))
),
$('<div>', {id: 'tab-saved-image-reload'})
).tabs();
$('#tab-save').append(savedImageTab);
var curveA = $('<a>', {href: '#sketch', 'data-tool': 'curve'});
var mojiA = $('<a>', {href: '#sketch', 'data-tool': 'moji'});
var fillA = $('<a>', {href: '#sketch', 'data-tool': 'fill'});
var figureA = $('<a>', {href: '#sketch', 'data-tool': 'figure'});
var selectionA = $('<a>', {href: '#sketch', 'data-tool': 'selection'});
var saveA = $('<a>', {href: '#sketch', 'data-tool': 'save'});
var settingsA = $('<a>', {href: '#sketch', 'data-tool': 'settings'});
$('.tools').after(curveA).after(fillA).after(mojiA).after(figureA)
.after(selectionA).after(saveA).after(settingsA);
$('a[href=#tab-kaku]') .click(function(){$('[data-tool=marker]').click()});
$('a[href=#tab-curve]') .click(function(){$('[data-tool=curve]').click()});
$('a[href=#tab-kesu]') .click(function(){$('[data-tool=eraser]').click()});
$('a[href=#tab-spoit]') .click(function(){$('[data-tool=spoit]').click()});
$('a[href=#tab-moji]') .click(function(){$('[data-tool=moji]').click()});
$('a[href=#tab-fill]') .click(function(){$('[data-tool=fill]').click()});
$('a[href=#tab-figure]') .click(function(){$('[data-tool=figure]').click()});
$('a[href=#tab-selection]').click(function(){$('[data-tool=selection]').click()});
$('a[href=#tab-save]') .click(function(){
$('[data-tool=save]').click();
$('a[href=#tab-saved-image-reload]').click();
autoSave = false;
});
$('a[href=#tab-settings]') .click(function(){$('[data-tool=settings]').click()});
$('[data-tool]').click(function(){
fixPreview();
autoSave = (settings.saveCycle=='任意')?false:true;
});
var goButton = $('<input>', {
type: 'button',
value: '進',
id: 'goButton',
click: function(){
changeAction(drawRedo, canvas.actions);
canvas.redraw();
}
});
$('#backButton').after(goButton);
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);
tmpCanvas.bind("mousedown", function(){
isOekakiDone = 1;
});
var layerTool = $('<div>', {
id: 'layerTool',
align: 'left',
style: 'background:#ccc;padding:2px;font-size:9pt'
});
var layerText = $('<b>', {text: '[レイヤ]:'});
var mergeLayerButton = $('<input>', {
id: 'mergeLayerButton',
type: 'button',
value: '結合',
click: function(){mergeLayer(canvas)}
});
$('#_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 initManual(){
$('#layerTool').next().css('background', '#ddd');
$('#layerTool').next().children().html(manual);
}
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 updateAllPreview(){
var nowLayerNum = canvas.layerNum;
jQuery.each(layers, function(i, layer){
if(i){
selectLayer(i);
updatePreview();
}
});
selectLayer(nowLayerNum);
}
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;
}
}
});
}
function deleteLayer(layerNum){
$('canvas[id^=preview]').each(function(i){
if(i == layerNum){
selectLayer(layerNum);
$(this).remove();
$(layers[i+1].canvas).remove();
layers.splice(i+1, 1);
}
});
}
function mergeLayer(mergeCanvas){
if(settings.layerOn){
updatePreview();
var context = mergeCanvas.getContext('2d');
context.clearRect(0, 0, realW, realH);
$('canvas[id^=preview]').each(function(i){
if(this.displayed){
context.drawImage($(this)[0], 0, 0, realW, realH);
}
});
}
};
$.sketch.tools.curve = {
onEvent: function(e) {
switch (e.type) {
case 'mousedown':
case 'touchstart':
startCurvePainting(e);
break;
case 'mouseup':
case 'mouseout':
case 'mouseleave':
case 'touchend':
case 'touchcancel':
stopCurvePainting(e);
}
if (this.painting) {
setPoint(e);
var p = getPosition(e);
canvas.action.events.push({
x: p.x,
y: p.y
});
return this.redraw();
}
},draw: function(action) {
var event, previous, _i, _len, _ref;
this.context.lineJoin = "round";
this.context.lineCap = "round";
this.context.beginPath();
this.context.moveTo(action.events[0].x, action.events[0].y);
_ref = action.events;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
event = _ref[_i];
this.context.lineTo(event.x, event.y);
previous = event;
}
this.context.strokeStyle = action.color;
this.context.lineWidth = action.size;
this.context.stroke();
}
};
function startCurvePainting(e){
try{
if(drawTimer){
clearInterval(drawTimer);
drawTimer= '';
}
canvas.painting = true;
canvas.action = {
tool: canvas.tool,
color: canvas.color,
size: canvas.size,
events: [],
points: []
}
setPoint(e);
getPoint();
drawTimer = setInterval(getPoint, interval);
}catch(ex){
console.log('Exception' + ex);
stopCurvePainting(e);
}
}
function stopCurvePainting(e){
setPoint(e);
if (canvas.action){
var fp = getFuturePoint(canvas.action.points);
var ss = splineStream(fp, interpolate);
canvas.action.events = ss;
canvas.actions.push(canvas.action);
}
clearInterval(drawTimer);
drawTimer = '';
canvas.painting = false;
canvas.action = null;
var wait = 0;
if(showPointFlag){
wait = 1000;
}
setTimeout(function(){
canvas.redraw();
updatePreview();
}, wait);
}
var position = {x: 0, y: 0}
function getPoint(){
var point = {
x: position.x,
y: position.y
}
canvas.action.points.push(point);
}
function setPoint(e){
var p = getPosition(e);
position.x = p.x;
position.y = p.y;
}
function getFuturePoint(points){
showPoints(points, 'rgb(255,0,0)', 1);
var p0 = points[0];
var fp = [p0];
var c = 0;
for(var i = 1; i < points.length-1; i++){
var p1 = points[i];
var dx1 = p0.x - p1.x;
var dy1 = p0.y - p1.y;
var dr = Math.pow(dx1, 2) + Math.pow(dy1, 2);
if(dr > Math.pow(correctionLv, 2) || c > interpolate * 100 / interval){
p0 = p1;
fp.push(p0);
c = 0;
}else{
var p2 = points[i+1];
var dx2 = p2.x - p1.x;
var dy2 = p2.y - p1.y;
var dc = (dx1*dx2 + dy1*dy2) / Math.sqrt((Math.pow(dx1, 2)+Math.pow(dy1, 2))*(Math.pow(dx2, 2)+Math.pow(dy2, 2)));
//console.log(dc);
if(dc > limA){
p0 = p1;
fp.push(p0);
c = 0;
}else if(dr > 0){
//c++;
}
}
}
var endPoint = points[points.length-1];
var endFp = fp[fp.length-1];
if(endPoint.x != endFp.x || endPoint.y != endFp.y){
fp.push(endPoint);
}
showPoints(fp, 'rgb(0,255,0)', 3);
return fp;
}
function showPoints(points, color, r){
if(!showPointFlag) return;
for(var i = 0; i < points.length; i++){
var point = points[i];
canvas.context.lineWidth = 2;
canvas.context.beginPath();
canvas.context.strokeStyle = color;
canvas.context.arc(point.x, point.y, r, 0, Math.PI*2, false);
canvas.context.stroke();
}
}
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(!action.fill && !canvas.filling){
canvas.filling = true;
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');
action.fill = fillCanvas;
canvas.filling = false;
}
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 pos = getPosition(e);
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;
canvas.actions.push({
x: Math.floor(pos.x),
y: Math.floor(pos.y),
tool: canvas.tool,
fillColor: fillColor
});
canvas.redraw();
if(settings.layerOn) 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 parseInt(Number(floatAlpha * 255));
}
function alphaToFloat(intAlpha){
return parseFloat(intAlpha / 255 * 100) * 100;
}
$.sketch.tools.moji = {
onEvent: function(e) {
switch (e.type) {
case 'mousedown':
case 'touchstart':
makeText(e);
break;
}
},
draw: function(action){
fillText(canvas.context, action);
}
}
function makeText(e){
if(canvas.preview){
fixPreview();
return;
}
var text = window.prompt("文字を入力。", "");
if(!text) return;
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 = ' ';
}
var pos = getPosition(e);
canvas.preview = {
x: pos.x,
y: pos.y,
deg: 0,
tool: canvas.tool,
color: canvas.color,
font: mojiBold + mojiItalic + mojiSize + 'px ' + mojiFont + '',
mode: mode,
text: text
};
var tmpCtx = $('#tmpCanvas')[0].getContext('2d');
var tmpSize = fillText(tmpCtx, canvas.preview);
movePreview(tmpCtx, canvas.preview, tmpSize);
}
function fillText(context, action){
context.fillStyle = action.color;
context.font = action.font;
context.textBaseline = 'top';
var lines = action.text.split('\n');
var size = measureTextAreaSize(context, action, lines);
context.translate(action.x + size.w/2, action.y + size.h/2);
context.rotate(action.deg * Math.PI/180);
var h = context.measureText("あ").width;
jQuery.each(lines, function(i, line) {
if(!action.mode){
context.textAlign = 'left'
context.fillText(line, -size.w/2, -size.h/2 + h*i);
}else{
jQuery.each(line, function(j, char){
context.textAlign = 'center';
context.fillText(char, -size.w/2 - h*i, -size.h/2 + h*j);
});
}
});
context.setTransform(1,0,0,1,0,0);
return size;
}
function measureTextAreaSize(context, action, lines){
var h = context.measureText("あ").width;
var maxW = 0;
var maxH = 0;
jQuery.each(lines, function(i, line) {
if(!action.mode){
var w = context.measureText(line).width;
if(w > maxW){maxW = w;}
maxH = h * (i+1);
}else{
jQuery.each(line, function(j, char){
if(h * (j+1) > maxH){maxH = h * (j+1)};
});
maxW = h * (i+1);
}
});
return {w: maxW, h: maxH}
}
function movePreview(context, preview, size){
var top = preview.y * scale;
var left = !preview.mode ? preview.x * scale - MARGIN : preview.x * scale - size.w*3/4 + MARGIN;
var border = 2;
var moveCanvas = $('<canvas>').attr({
id: 'moveCanvas',
width: size.w + MARGIN,
height: size.h + MARGIN,
style: 'border:' + border + 'pt dotted #666; position:absolute; ' +
'top: ' + (top - (MARGIN + border)/2) + '; ' +
'left: ' + (left - (MARGIN + border)/2) + '; ' +
'width: ' + size.w * scale + '; ' +
'height: ' + size.h * scale + '; ' +
'z-index:10; cursor: move'
});
var tmpImg = context.getImageData(left/scale, top/scale, size.w + MARGIN, size.h + MARGIN);
context.clearRect(0, 0, canvas.el.width, canvas.el.height);
moveCanvas[0].getContext('2d').putImageData(tmpImg, 0, 0);
$('#sketch').before(moveCanvas);
var rotateImg = $('#rotateIcon')[0];
var rotateCanvas = $('<canvas>').attr({
id: 'rotateCanvas',
width: rotateImg.width,
height: rotateImg.height,
style: 'position:absolute; ' +
'top: ' + ((top - (MARGIN + border)/2) - rotateImg.height) + '; ' +
'left: ' + ((left - (MARGIN + border)/2) + moveCanvas.width()/2 - rotateImg.width/2) + '; ' +
'z-index:11; cursor:pointer;'
});
rotateCanvas[0].getContext('2d').drawImage(rotateImg, 0, 0, rotateImg.width, rotateImg.height);
if(!canvas.selection){$('#sketch').before(rotateCanvas);}
var startMove = function(e){
pos = getPosition(e.originalEvent);
canvas.move = {
x: pos.x,
y: pos.y,
dx: pos.x - this.style.left.replace('px', ''),
dy: pos.y - this.style.top.replace('px', '')
};
}
var endMove = function(e){
if(!canvas.move) return;
var pos = getPosition(e.originalEvent);
preview.x += pos.x - canvas.move.x;
preview.y += pos.y - canvas.move.y;
canvas.move = null;
}
var moving = function(e){
if(!canvas.move) return;
var pos = getPosition(e.originalEvent);
var mx = this.style.left.replace('px', '');
var my = this.style.top.replace('px', '');
var rx = rotateCanvas[0].style.left.replace('px', '');
var ry = rotateCanvas[0].style.top.replace('px', '');
var ox = canvas.move.x;
var oy = canvas.move.y;
var odx = (pos.x - ox)*scale;
var ody = (pos.y - oy)*scale;
this.style.left = ox + odx - canvas.move.dx;
this.style.top = oy + ody - canvas.move.dy;
var dx = mx - rx;
var dy = my - ry;
rotateCanvas[0].style.left = ox + odx - canvas.move.dx - dx;
rotateCanvas[0].style.top = oy + ody - canvas.move.dy - dy;
}
moveCanvas.bind('mousedown touchstart', startMove);
moveCanvas.bind('mouseup mouseout mouseleave touchend touchcancel', endMove);
moveCanvas.bind('mousemove', moving);
var startRotate = function(e){
pos = getPosition(e.originalEvent);
canvas.rotate = {
x: parseFloat(moveCanvas[0].style.left.replace('px', '')) + moveCanvas[0].width/2,
y: parseFloat(moveCanvas[0].style.top.replace('px', '')) + moveCanvas[0].height/2,
};
}
var endRotate = function(e){
if(!canvas.rotate) return;
var pos = getPosition(e.originalEvent);
canvas.rotate = null;
}
var rotating = function(e){
if(!canvas.rotate) return;
var pos = getPosition(e.originalEvent);
this.style.left = pos.x * scale - this.width/2;
this.style.top = pos.y *scale - this.height/2;
var dx = pos.x * scale - canvas.rotate.x;
var dy = pos.y * scale - canvas.rotate.y;
var deg = Math.atan2(dy, dx) * 180/Math.PI + 90;
moveCanvas[0].style.MozTransform = 'rotateZ(' + deg + 'deg)';
moveCanvas[0].style.webkitTransform = 'rotateZ(' + deg + 'deg)';
moveCanvas[0].style.oTransform = 'rotateZ(' + deg + 'deg)';
moveCanvas[0].style.msTransform = 'rotateZ(' + deg + 'deg)';
preview.deg = deg;
}
rotateCanvas.bind('mousedown touchstart', startRotate);
rotateCanvas.bind('mouseup mouseout mouseleave touchend touchcancel', endRotate);
rotateCanvas.bind('mousemove', rotating);
return tmpImg;
}
function fixPreview(){
if(!$('#moveCanvas')[0]) return;
if(canvas.preview){
canvas.actions.push(canvas.preview);
canvas.preview = null;
}
if(canvas.selection){
canvas.actions.push(canvas.selection);
canvas.selection = null;
}
$('#moveCanvas').remove();
$('#rotateCanvas').remove();
canvas.redraw();
if(settings.layerOn) updatePreview();
}
$.sketch.tools.figure = {
onEvent: function(e) {
switch (e.type) {
case 'mousedown':
case 'touchstart':
startPreviewing(e, canvas.color, canvas.size, $('#figureType').val());
break;
case 'mouseup':
case 'mouseout':
case 'mouseleave':
case 'touchend':
case 'touchcancel':
stopPreviewing(e);
}
if(canvas.preview){
previewing(e);
}
},
draw: function(action){
drawFigure(canvas.context, action);
}
}
function startPreviewing(e, color, size, figureType){
var pos = getPosition(e);
canvas.preview = {
x: pos.x,
y: pos.y,
tool: canvas.tool,
color: color,
size: size,
figureType: figureType
};
}
function stopPreviewing(e){
if(canvas.preview){
var tmpCanvas = $('#tmpCanvas')[0];
var tmpCtx = tmpCanvas.getContext('2d');
if(canvas.preview.tool == 'figure'){
canvas.actions.push(canvas.preview);
}else if(canvas.preview.tool == 'selection'){
orgCanvas = canvas.el;
orgCtx = canvas.context;
canvas.el = tmpCanvas;
canvas.context = tmpCtx;
canvas.redraw();
if(canvas.preview.w < 0){
canvas.preview.x += canvas.preview.w;
canvas.preview.w = - canvas.preview.w;
}
if(canvas.preview.h < 0){
canvas.preview.y += canvas.preview.h;
canvas.preview.h = - canvas.preview.h;
}
canvas.selection = {
x: canvas.preview.x,
y: canvas.preview.y,
w: canvas.preview.w,
h: canvas.preview.h,
sx: canvas.preview.x,
sy: canvas.preview.y,
// sw: canvas.preview.w,
// sh: canvas.preview.h,
tool: canvas.preview.tool,
type: canvas.preview.type,
deg: canvas.preview.deg
};
var size = {
w: canvas.selection.w,
h: canvas.selection.h
};
canvas.selection.img = movePreview(tmpCtx, canvas.selection, size);
if(canvas.selection.type == '0'){
canvas.actions.push({
x: canvas.selection.x,
y: canvas.selection.y,
w: canvas.selection.w,
h: canvas.selection.h,
tool: 'figure',
figureType: '10'
});
}
canvas.el = orgCanvas;
canvas.context = orgCtx;
}
canvas.preview = null;
tmpCtx.clearRect(0, 0, canvas.el.width, canvas.el.height);
canvas.redraw();
if(settings.layerOn) updatePreview();
}
}
function previewing(e){
var pos = getPosition(e);
canvas.preview.w = pos.x - canvas.preview.x;
canvas.preview.h = pos.y - canvas.preview.y;
var tmpCtx = $('#tmpCanvas')[0].getContext('2d');
tmpCtx.clearRect(0, 0, canvas.el.width, canvas.el.height);
drawFigure(tmpCtx, canvas.preview);
}
function drawFigure(context, action){
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;
context.beginPath();
context.arc(action.x + action.w/2, action.y + action.h/2, (Math.abs(action.w) > Math.abs(action.h)) ? Math.abs(action.w/2) : Math.abs(action.h/2), 0, Math.PI*2, false);
context.stroke();
break;
case '4': //●
context.beginPath();
context.lineCap = 'butt';
context.fillStyle = action.color;
context.beginPath();
context.arc(action.x + action.w/2, action.y + action.h/2, (Math.abs(action.w) > Math.abs(action.h)) ? Math.abs(action.w/2) : Math.abs(action.h/2), 0, Math.PI*2, false);
context.fill();
break
case '9': //矩形選択
context.beginPath();
context.lineWidth = action.size;
context.lineCap = 'butt';
context.setLineDash([3, 3]);
context.strokeStyle = action.color;
context.strokeRect(action.x, action.y, action.w, action.h);
break;
case '10': //クリア
context.clearRect(action.x, action.y, action.w, action.h);
break;
}
}
$.sketch.tools.selection = {
onEvent: function(e) {
switch (e.type) {
case 'mousedown':
case 'touchstart':
if(canvas.selection){
fixPreview();
return;
}else{
startPreviewing(e, 'rgba(128, 128, 128, 0.9)', 1, '9');
canvas.preview.type = $('#selectionType').val();
}
break;
case 'mouseup':
case 'mouseout':
case 'mouseleave':
case 'touchend':
case 'touchcancel':
stopPreviewing(e);
}
if(canvas.preview){
previewing(e);
}
},
draw: function(action){
drawSelection(canvas.context, action);
}
}
function drawSelection(context, action){
context.translate(action.x + action.img.width/2, action.y + action.img.heihgt/2);
context.rotate(action.deg * Math.PI/180);
context.putImageData(action.img, action.x, action.y);
context.setTransform(1,0,0,1,0,0);
}
function lpad(string, length, char){
var padding;
for(var i = 1; i <= length; i++){
padding += char;
}
return (padding + string).slice(-length);
}
function getPosition(e){
var pageX = e.pageX;
var pageY = e.pageY;
var offsetX = $('#sketch').offset().left;
var offsetY = $('#sketch').offset().top;
var x = parseFloat(pageX - offsetX) / scale;
var y = parseFloat(pageY - offsetY) / scale;
return {x: x, y: y};
}
function setCanvasScale(){
scale = $('#canvasScale').val();
var size = $('#canvasSize').val().split("x");
realW = size[0];
realH = size[1];
scaleW = realW * scale;
scaleH = realH * scale;
}
function changeCanvasScale(){
setCanvasScale();
$('#oekakiCanvas')[0].style.width = scaleW;
$('#sketch')[0].style.width = scaleW;
$('#sketch')[0].style.height = scaleH;
$('#tmpCanvas')[0].style.width = scaleW;
$('#tmpCanvas')[0].style.height = scaleH;
$('canvas[id^=layerCanvas]').each(function(i){
this.width = scaleW;
this.height = scaleH;
});
updateAllPreview();
}
function setDegree(deg){
degree += deg;
rotateCanvas();
}
function rotateCanvas(){
canvas.el.style.MozTransform = 'rotateZ(' + deg + 'deg)';
canvas.el.style.webkitTransform = 'rotateZ(' + deg + 'deg)';
canvas.el.style.oTransform = 'rotateZ(' + deg + 'deg)';
canvas.el.style.msTransform = 'rotateZ(' + deg + 'deg)';
}
$.sketch.tools.save = {
onEvent: function(){
//console.log('save onEvent');
},
draw: function(){
//console.log('save draw')
}
}
$.sketch.tools.settings = {
onEvent: function(){
//
},
draw: function(){
//
}
}
function loadIcon(icons){
var baseUrl = 'https://googledrive.com/host/0B1BW1N6rqpWFa0lTUW1aZThuT28/';
for(var key in icons){
var img = new Image();
img.id = key;
img.src = baseUrl + icons[key];
img.style.display = 'none';
$('#oekakiCanvas').append(img);
}
}
$(document).keydown(function(e){
keydownEvent(e, 37, canvas.actions, drawRedo);
keydownEvent(e, 39, drawRedo, canvas.actions);
});
$("#backButton").unbind();
$("#backButton").click(function() {
changeAction(canvas.actions, drawRedo);
});
function keydownEvent(e, keyNum, popList, pushList){
if(e.which === keyNum && e.ctrlKey && popList.length > 0){
changeAction(popList, pushList);
return false;
}
}
function changeAction(popList, pushList){
pushList.push(popList.pop());
canvas.redraw();
if(settings.layerOn) updatePreview();
}
canvas.redraw = function() {
var sketch;
this.el.width = realW;
this.el.height = realH;
this.el.style.width = scaleW;
this.el.style.height = scaleH;
this.context = this.el.getContext('2d');
this.context.fillStyle = this.bgcolor;
this.context.fillRect(0, 0, this.canvas.width(), this.canvas.height());
if (canvas.baseImageURL) {
if (this.baseImageCache) {
this.context.drawImage(this.baseImageCache, 0, 0);
} else {
var img = new Image();
var _this = this;
img.src = this.baseImageURL;
img.onload = (function() {
_this.baseImageCache = img;
_this.context.drawImage(img, 0, 0);
});
}
}
sketch = this;
$.each(this.actions, function() {
if (this.tool) {
return $.sketch.tools[this.tool].draw.call(sketch, this);
}
});
if (this.painting && this.action) {
return $.sketch.tools[this.action.tool].draw.call(sketch, this.action);
}
};
canvas.stopPainting = function(){
if (this.action) {
this.actions.push(this.action);
}
this.painting = false;
this.action = null;
if(settings.layerOn) updatePreview();
};
$.sketch.tools.marker = {
onEvent: function(e) {
switch (e.type) {
case 'mousedown':
case 'touchstart':
this.startPainting();
break;
case 'mouseup':
case 'mouseout':
case 'mouseleave':
case 'touchend':
case 'touchcancel':
this.stopPainting();
}
if (this.painting) {
var pos = getPosition(e);
this.action.events.push({x: pos.x,y: pos.y,event: e.type});
return this.redraw();
}
},draw: function(action) {
var event, previous, _i, _len, _ref;
this.context.lineJoin = "round";
this.context.lineCap = "round";
this.context.beginPath();
this.context.moveTo(action.events[0].x, action.events[0].y);
_ref = action.events;
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
event = _ref[_i];
this.context.lineTo(event.x, event.y);
previous = event;
}
this.context.strokeStyle = action.color;
this.context.lineWidth = action.size;
return this.context.stroke();
}
};
$.sketch.tools.eraser = {
onEvent: function(e) {
$.sketch.tools.marker.onEvent.call(this, e);
},draw: function(action) {
var oldcomposite;
oldcomposite = this.context.globalCompositeOperation;
if(browser == "chrome"){
this.context.globalCompositeOperation = "copy";
action.color = this.bgcolor;
}else{
this.context.globalCompositeOperation = "destination-out";
action.color = 'rgb(0, 0, 0)';
}
$.sketch.tools.marker.draw.call(this, action);
this.context.globalCompositeOperation = oldcomposite;
}
};
$("#canvasSize").unbind();
$("#canvasSize").change(function() {
setCanvasScale();
$('canvas[id^=layerCanvas]').each(function(i){
this.width = realW;
this.height = realH;
});
$('canvas[id^=preview]').each(function(i){
this.width = realW;
this.height = realH;
this.style.width = realW * PREVIEW_SIZE;
this.style.height = realH * PREVIEW_SIZE;
});
var tmpCanvas = $('#tmpCanvas')[0];
tmpCanvas.width = realW;
tmpCanvas.height = realH;
changeCanvasScale();
});
setFile = function(file) {
var img = new Image();
var fileReader = new FileReader();
fileReader.onload = function(event) {
$(img).attr('src', event.target.result);
}
fileReader.readAsDataURL(file);
img.onload = function() {
fitImage(canvas.context, img);
canvas.setBaseImageURL(canvas.el.toDataURL());
isOekakiDone = 1;
};
}
$('#submit_button').click(function(){
if(isOekakiDone){
addLayer();
fixPreview();
mergeLayer(canvas.el);
var imgData = canvas.context.getImageData(0, 0, canvas.el.width, canvas.el.height);
var imgCanvas = $('<canvas>').attr({
id: 'imgCanvas',
width: canvas.el.width,
height: canvas.el.height,
style: 'border: 10pt ridge #D00; background: #EEE;'
});
imgCanvas[0].getContext('2d').putImageData(imgData, 0, 0);
$('#oekakiMode').before(imgCanvas);
var result = false;
if(window.confirm('この内容で投稿しますか?')){
result = true;
}
deleteLayer(layers.length-2);
imgCanvas.remove();
canvas.context.putImageData(imgData, 0, 0);
return result;
}
});
$(window).bind('beforeunload', function(e) {
if(isOekakiDone){
return 'お絵かきの途中のようです。';
}
});
- Permalink
- このページへの個別リンクです。
- RAW
- 書かれたコードへの直接のリンクです。
- Packed
- 文字列が圧縮された書かれたコードへのリンクです。
- Userscript
- Greasemonkey 等で利用する場合の .user.js へのリンクです。
- Loader
- @require やソースコードが長い場合に多段ロードする Loader コミのコードへのリンクです。
- Metadata
- コード中にコメントで @xxx と書かれたメタデータの JSON です。