🗂

Chromeで別小窓に手書きメモを表示するブックマークレット

17 min read

同じようなネタばかり、書いていますが、シロウトなので単にITリテラシーが無いからです…

0.初めに

  • 以前にマウス、タッチパネル両対応の手書きメモみたいなJavaScriptアプリをCodePenで見つけた

    A Pen by flavio

  • 記憶があいまいだが、多分、JavaScriptアプリを少し直して、メモの画像保存、UNDO、REDO、線の太さ変更を、できるようにして、使っていた

  • Chromeでウェブサイトを見ながらメモ帳にメモすることがたまにある

  • タッチパネル対応PCも増えたので、手書きしたいこともある

  • メモを保存したいときもある

    ⇒こんな感じにしたかった

  • というわけで、簡単に手書きメモできるChromeの小窓が欲しかった

    ⇒こんな感じにしたかった

  • ブックマークレットなら簡単そうだったので作った

    ブックマークレット/Bookmarkletの作り方 - catch.jp-wiki

1.作ったもの、使ったもの

  • 元々のJavaScript
    ⇒このやり方だとDOMContentLoadedが発火せず、少しいじりました
    ⇒長すぎるとブックマーク同期がうまく行かないのでCSSを外部ファイルにしました
var hhh='<html>'+
'<!doctype html>'+
'<html>'+
'<head>'+
'    <title>Sketch Pad</title>'+
'    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0, user-scalable=0" />'+
'    <link rel="stylesheet" href="https://laboratory.main.jp/fcss/a.css">'+
'<script type="text/javascript">'+
'var ctx, color = "#000";	'+
''+
'function newCanvas(){'+
'    document.getElementById("content").style.height = window.innerHeight-90;'+
'    var canvas = \'<canvas id="canvas" width="\'+window.innerWidth+\'" height="\'+(window.innerHeight-90)+\'"></canvas>\';'+
'	document.getElementById("content").innerHTML = canvas;'+
'	ctx=document.getElementById("canvas").getContext("2d");'+
'	ctx.strokeStyle = color;'+
'	ctx.lineWidth = 5;	'+
'        beforeDraw();'+
'    drawTouch();'+
'    drawPointer();'+
'	drawMouse();'+
'}'+
''+
'function saveCanvas(){'+
'    let canvas = document.getElementById("canvas");'+
'    let link = document.createElement("a");'+
'    link.href = canvas.toDataURL("image/png");'+
'    link.download = "noname.png";'+
'    link.click();'+
'}'+
'        '+
'function selectColor(el){'+
'    for(var i=0;i<document.getElementsByClassName("palette").length;i++){'+
'        document.getElementsByClassName("palette")[i].style.borderColor = "#777";'+
'        document.getElementsByClassName("palette")[i].style.borderStyle = "solid";'+
'    }'+
'    el.style.borderColor = "#fff";'+
'    el.style.borderStyle = "dashed";'+
'    color = window.getComputedStyle(el).backgroundColor;'+
'    ctx.beginPath();'+
'    ctx.strokeStyle = color;'+
'}'+
''+
'var drawTouch = function() {'+
'	var start = function(e) {'+
'		ctx.beginPath();'+
'		x = e.changedTouches[0].pageX;'+
'		y = e.changedTouches[0].pageY-44;'+
'                beforeDraw();'+
'		ctx.moveTo(x,y);'+
'	};'+
'	var move = function(e) {'+
'		e.preventDefault();'+
'		x = e.changedTouches[0].pageX;'+
'		y = e.changedTouches[0].pageY-44;'+
'		ctx.lineTo(x,y);'+
'		ctx.stroke();'+
'	};'+
'    document.getElementById("canvas").addEventListener("touchstart", start, false);'+
'	document.getElementById("canvas").addEventListener("touchmove", move, false);'+
'}; '+
'    '+
'var drawPointer = function() {'+
'	var start = function(e) {'+
'        e = e.originalEvent;'+
'		ctx.beginPath();'+
'		x = e.pageX;'+
'		y = e.pageY-44;'+
'                beforeDraw();'+
'		ctx.moveTo(x,y);'+
'	};'+
'	var move = function(e) {'+
'		e.preventDefault();'+
'        e = e.originalEvent;'+
'		x = e.pageX;'+
'		y = e.pageY-44;'+
'		ctx.lineTo(x,y);'+
'		ctx.stroke();'+
'    };'+
'    document.getElementById("canvas").addEventListener("MSPointerDown", start, false);'+
'	document.getElementById("canvas").addEventListener("MSPointerMove", move, false);'+
'};        '+
''+
'var drawMouse = function() {'+
'	var clicked = 0;'+
'	var start = function(e) {'+
'		clicked = 1;'+
'		ctx.beginPath();'+
'		x = e.pageX;'+
'		y = e.pageY-44;'+
'                beforeDraw();'+
'		ctx.moveTo(x,y);'+
'	};'+
'	var move = function(e) {'+
'		if(clicked){'+
'			x = e.pageX;'+
'			y = e.pageY-44;'+
'			ctx.lineTo(x,y);'+
'			ctx.stroke();'+
'		}'+
'	};'+
'	var stop = function(e) {'+
'		clicked = 0;'+
'	};'+
'    document.getElementById("canvas").addEventListener("mousedown", start, false);'+
'	document.getElementById("canvas").addEventListener("mousemove", move, false);'+
'	document.addEventListener("mouseup", stop, false);'+
'};'+
'	</script>'+
'</head>'+
'<body>'+
'<div id="page">'+
'    <div class="header">'+
'		<a id="new" class="navbtn" onclick="newCanvas()">New</a>'+
'		<a id="save" class="navbtn" onclick="saveCanvas()">Save</a>'+
'		<a id="undo" class="navbtn" onclick="undo()">Undo</a>'+
'		<a id="redo" class="navbtn" onclick="redo()">Redo</a>'+
'<select id="aaa" name="linewidth">'+
'<option value="2">細い</option>'+
'<option value="5" selected>普通</option>'+
'<option value="8">太い</option>'+
'<option value="11">極太</option>'+
'<option value="14">超太</option>'+
'</select>'+
'        <div class="title">Sketch Pad</div>'+
'    </div>'+
'    <div id="content"><p style="text-align:center">NEWボタンを押してください...</p></div>'+
'    <div class="footer">'+
'		<div class="palette-case">'+
'			<div class="palette-box">'+
'				<div class="palette white" onclick="selectColor(this)"></div>'+
'			</div>	'+
'			<div class="palette-box">'+
'				<div class="palette red" onclick="selectColor(this)"></div>'+
'			</div>'+
'			<div class="palette-box">'+
'				<div class="palette blue" onclick="selectColor(this)"></div>'+
'			</div>'+
'			<div class="palette-box">'+
'				<div class="palette green" onclick="selectColor(this)"></div>'+
'			</div>'+
'			<div class="palette-box">'+
'				<div class="palette black" onclick="selectColor(this)"></div>'+
'			</div>		'+
'			<div style="clear:both"></div>'+
'		</div>'+
'    </div>'+
'</div>'+
''+
'<script>'+
''+
'function linew() {'+
'   ctx.lineWidth = document.getElementById("aaa").value;'+
'}'+
''+
'var el1 = document.getElementById(\'aaa\');'+
'el1.addEventListener(\'change\', linew, false);'+
''+
'const STACK_MAX_SIZE = 5;'+
'let undoDataStack = [];'+
'let redoDataStack = [];'+
''+
'function beforeDraw() {'+
'    redoDataStack = [];'+
'    if (undoDataStack.length >= STACK_MAX_SIZE) {'+
'        undoDataStack.pop();'+
'    }'+
'    var w=document.getElementById(\'canvas\').width;'+
'    var h=document.getElementById(\'canvas\').height;'+
'    undoDataStack.unshift(ctx.getImageData(0, 0, w, h));'+
'}'+
''+
'function undo () {'+
'    if (undoDataStack.length <= 0) return;'+
'    var w=document.getElementById(\'canvas\').width;'+
'    var h=document.getElementById(\'canvas\').height;'+
'    redoDataStack.unshift(ctx.getImageData(0, 0, w, h));'+
'    var imageData = undoDataStack.shift();'+
'    ctx.putImageData(imageData, 0, 0);'+
'}'+
''+
'function redo () {'+
'    if (redoDataStack.length <= 0) return;'+
'    var w=document.getElementById(\'canvas\').width;'+
'    var h=document.getElementById(\'canvas\').height;'+
'    undoDataStack.unshift(ctx.getImageData(0, 0, w, h));'+
'    var imageData = redoDataStack.shift();'+
'    ctx.putImageData(imageData, 0, 0);'+
'}'+
'</script>'+
'</body>'+
'</html> ';
var win = window.open('','','width=560,height=440');
win.document.write(hhh);
javascript:var%20hhh%3D'%3Chtml%3E'%2B%20'%3C!doctype%20html%3E'%2B%20'%3Chtml%3E'%2B%20'%3Chead%3E'%2B%20'%20%3Ctitle%3ESketch%20Pad%3C%2Ftitle%3E'%2B%20'%20%3Cmeta%20name%3D%22viewport%22%20content%3D%22width%3Ddevice-width%2Cinitial-scale%3D1.0%2Cmaximum-scale%3D1.0%2Cminimum-scale%3D1.0%2Cuser-scalable%3D0%22%20%2F%3E'%2B%20'%20%3Clink%20rel%3D%22stylesheet%22%20href%3D%22https%3A%2F%2Flaboratory.main.jp%2Ffcss%2Fa.css%22%3E'%2B%20'%3Cscript%20type%3D%22text%2Fjavascript%22%3E'%2B%20'var%20ctx%2Ccolor%3D%22%23000%22%3B'%2B%20''%2B%20'function%20newCanvas()%7B'%2B%20'%20document.getElementById(%22content%22).style.height%3Dwindow.innerHeight-90%3B'%2B%20'%20var%20canvas%3D%5C'%3Ccanvas%20id%3D%22canvas%22%20width%3D%22%5C'%2Bwindow.innerWidth%2B%5C'%22%20height%3D%22%5C'%2B(window.innerHeight-90)%2B%5C'%22%3E%3C%2Fcanvas%3E%5C'%3B'%2B%20'%20document.getElementById(%22content%22).innerHTML%3Dcanvas%3B'%2B%20'%20ctx%3Ddocument.getElementById(%22canvas%22).getContext(%222d%22)%3B'%2B%20'%20ctx.strokeStyle%3Dcolor%3B'%2B%20'%20ctx.lineWidth%3D5%3B'%2B%20'%20beforeDraw()%3B'%2B%20'%20drawTouch()%3B'%2B%20'%20drawPointer()%3B'%2B%20'%20drawMouse()%3B'%2B%20'%7D'%2B%20''%2B%20'function%20saveCanvas()%7B'%2B%20'%20let%20canvas%3Ddocument.getElementById(%22canvas%22)%3B'%2B%20'%20let%20link%3Ddocument.createElement(%22a%22)%3B'%2B%20'%20link.href%3Dcanvas.toDataURL(%22image%2Fpng%22)%3B'%2B%20'%20link.download%3D%22noname.png%22%3B'%2B%20'%20link.click()%3B'%2B%20'%7D'%2B%20'%20'%2B%20'function%20selectColor(el)%7B'%2B%20'%20for(var%20i%3D0%3Bi%3Cdocument.getElementsByClassName(%22palette%22).length%3Bi%2B%2B)%7B'%2B%20'%20document.getElementsByClassName(%22palette%22)%5Bi%5D.style.borderColor%3D%22%23777%22%3B'%2B%20'%20document.getElementsByClassName(%22palette%22)%5Bi%5D.style.borderStyle%3D%22solid%22%3B'%2B%20'%7D'%2B%20'%20el.style.borderColor%3D%22%23fff%22%3B'%2B%20'%20el.style.borderStyle%3D%22dashed%22%3B'%2B%20'%20color%3Dwindow.getComputedStyle(el).backgroundColor%3B'%2B%20'%20ctx.beginPath()%3B'%2B%20'%20ctx.strokeStyle%3Dcolor%3B'%2B%20'%7D'%2B%20''%2B%20'var%20drawTouch%3Dfunction()%7B'%2B%20'%20var%20start%3Dfunction(e)%7B'%2B%20'%20ctx.beginPath()%3B'%2B%20'%20x%3De.changedTouches%5B0%5D.pageX%3B'%2B%20'%20y%3De.changedTouches%5B0%5D.pageY-44%3B'%2B%20'%20beforeDraw()%3B'%2B%20'%20ctx.moveTo(x%2Cy)%3B'%2B%20'%7D%3B'%2B%20'%20var%20move%3Dfunction(e)%7B'%2B%20'%20e.preventDefault()%3B'%2B%20'%20x%3De.changedTouches%5B0%5D.pageX%3B'%2B%20'%20y%3De.changedTouches%5B0%5D.pageY-44%3B'%2B%20'%20ctx.lineTo(x%2Cy)%3B'%2B%20'%20ctx.stroke()%3B'%2B%20'%7D%3B'%2B%20'%20document.getElementById(%22canvas%22).addEventListener(%22touchstart%22%2Cstart%2Cfalse)%3B'%2B%20'%20document.getElementById(%22canvas%22).addEventListener(%22touchmove%22%2Cmove%2Cfalse)%3B'%2B%20'%7D%3B'%2B%20'%20'%2B%20'var%20drawPointer%3Dfunction()%7B'%2B%20'%20var%20start%3Dfunction(e)%7B'%2B%20'%20e%3De.originalEvent%3B'%2B%20'%20ctx.beginPath()%3B'%2B%20'%20x%3De.pageX%3B'%2B%20'%20y%3De.pageY-44%3B'%2B%20'%20beforeDraw()%3B'%2B%20'%20ctx.moveTo(x%2Cy)%3B'%2B%20'%7D%3B'%2B%20'%20var%20move%3Dfunction(e)%7B'%2B%20'%20e.preventDefault()%3B'%2B%20'%20e%3De.originalEvent%3B'%2B%20'%20x%3De.pageX%3B'%2B%20'%20y%3De.pageY-44%3B'%2B%20'%20ctx.lineTo(x%2Cy)%3B'%2B%20'%20ctx.stroke()%3B'%2B%20'%7D%3B'%2B%20'%20document.getElementById(%22canvas%22).addEventListener(%22MSPointerDown%22%2Cstart%2Cfalse)%3B'%2B%20'%20document.getElementById(%22canvas%22).addEventListener(%22MSPointerMove%22%2Cmove%2Cfalse)%3B'%2B%20'%7D%3B'%2B%20''%2B%20'var%20drawMouse%3Dfunction()%7B'%2B%20'%20var%20clicked%3D0%3B'%2B%20'%20var%20start%3Dfunction(e)%7B'%2B%20'%20clicked%3D1%3B'%2B%20'%20ctx.beginPath()%3B'%2B%20'%20x%3De.pageX%3B'%2B%20'%20y%3De.pageY-44%3B'%2B%20'%20beforeDraw()%3B'%2B%20'%20ctx.moveTo(x%2Cy)%3B'%2B%20'%7D%3B'%2B%20'%20var%20move%3Dfunction(e)%7B'%2B%20'%20if(clicked)%7B'%2B%20'%20x%3De.pageX%3B'%2B%20'%20y%3De.pageY-44%3B'%2B%20'%20ctx.lineTo(x%2Cy)%3B'%2B%20'%20ctx.stroke()%3B'%2B%20'%7D'%2B%20'%7D%3B'%2B%20'%20var%20stop%3Dfunction(e)%7B'%2B%20'%20clicked%3D0%3B'%2B%20'%7D%3B'%2B%20'%20document.getElementById(%22canvas%22).addEventListener(%22mousedown%22%2Cstart%2Cfalse)%3B'%2B%20'%20document.getElementById(%22canvas%22).addEventListener(%22mousemove%22%2Cmove%2Cfalse)%3B'%2B%20'%20document.addEventListener(%22mouseup%22%2Cstop%2Cfalse)%3B'%2B%20'%7D%3B'%2B%20'%20%3C%2Fscript%3E'%2B%20'%3C%2Fhead%3E'%2B%20'%3Cbody%3E'%2B%20'%3Cdiv%20id%3D%22page%22%3E'%2B%20'%20%3Cdiv%20class%3D%22header%22%3E'%2B%20'%20%3Ca%20id%3D%22new%22%20class%3D%22navbtn%22%20onclick%3D%22newCanvas()%22%3ENew%3C%2Fa%3E'%2B%20'%20%3Ca%20id%3D%22save%22%20class%3D%22navbtn%22%20onclick%3D%22saveCanvas()%22%3ESave%3C%2Fa%3E'%2B%20'%20%3Ca%20id%3D%22undo%22%20class%3D%22navbtn%22%20onclick%3D%22undo()%22%3EUndo%3C%2Fa%3E'%2B%20'%20%3Ca%20id%3D%22redo%22%20class%3D%22navbtn%22%20onclick%3D%22redo()%22%3ERedo%3C%2Fa%3E'%2B%20'%3Cselect%20id%3D%22aaa%22%20name%3D%22linewidth%22%3E'%2B%20'%3Coption%20value%3D%222%22%3E%E7%B4%B0%E3%81%84%3C%2Foption%3E'%2B%20'%3Coption%20value%3D%225%22%20selected%3E%E6%99%AE%E9%80%9A%3C%2Foption%3E'%2B%20'%3Coption%20value%3D%228%22%3E%E5%A4%AA%E3%81%84%3C%2Foption%3E'%2B%20'%3Coption%20value%3D%2211%22%3E%E6%A5%B5%E5%A4%AA%3C%2Foption%3E'%2B%20'%3Coption%20value%3D%2214%22%3E%E8%B6%85%E5%A4%AA%3C%2Foption%3E'%2B%20'%3C%2Fselect%3E'%2B%20'%20%3Cdiv%20class%3D%22title%22%3ESketch%20Pad%3C%2Fdiv%3E'%2B%20'%20%3C%2Fdiv%3E'%2B%20'%20%3Cdiv%20id%3D%22content%22%3E%3Cp%20style%3D%22text-align%3Acenter%22%3ENEW%E3%83%9C%E3%82%BF%E3%83%B3%E3%82%92%E6%8A%BC%E3%81%97%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84...%3C%2Fp%3E%3C%2Fdiv%3E'%2B%20'%20%3Cdiv%20class%3D%22footer%22%3E'%2B%20'%20%3Cdiv%20class%3D%22palette-case%22%3E'%2B%20'%20%3Cdiv%20class%3D%22palette-box%22%3E'%2B%20'%20%3Cdiv%20class%3D%22palette%20white%22%20onclick%3D%22selectColor(this)%22%3E%3C%2Fdiv%3E'%2B%20'%20%3C%2Fdiv%3E%20'%2B%20'%20%3Cdiv%20class%3D%22palette-box%22%3E'%2B%20'%20%3Cdiv%20class%3D%22palette%20red%22%20onclick%3D%22selectColor(this)%22%3E%3C%2Fdiv%3E'%2B%20'%20%3C%2Fdiv%3E'%2B%20'%20%3Cdiv%20class%3D%22palette-box%22%3E'%2B%20'%20%3Cdiv%20class%3D%22palette%20blue%22%20onclick%3D%22selectColor(this)%22%3E%3C%2Fdiv%3E'%2B%20'%20%3C%2Fdiv%3E'%2B%20'%20%3Cdiv%20class%3D%22palette-box%22%3E'%2B%20'%20%3Cdiv%20class%3D%22palette%20green%22%20onclick%3D%22selectColor(this)%22%3E%3C%2Fdiv%3E'%2B%20'%20%3C%2Fdiv%3E'%2B%20'%20%3Cdiv%20class%3D%22palette-box%22%3E'%2B%20'%20%3Cdiv%20class%3D%22palette%20black%22%20onclick%3D%22selectColor(this)%22%3E%3C%2Fdiv%3E'%2B%20'%20%3C%2Fdiv%3E%20'%2B%20'%20%3Cdiv%20style%3D%22clear%3Aboth%22%3E%3C%2Fdiv%3E'%2B%20'%20%3C%2Fdiv%3E'%2B%20'%20%3C%2Fdiv%3E'%2B%20'%3C%2Fdiv%3E'%2B%20''%2B%20'%3Cscript%3E'%2B%20''%2B%20'function%20linew()%7B'%2B%20'%20ctx.lineWidth%3Ddocument.getElementById(%22aaa%22).value%3B'%2B%20'%7D'%2B%20''%2B%20'var%20el1%3Ddocument.getElementById(%5C'aaa%5C')%3B'%2B%20'el1.addEventListener(%5C'change%5C'%2Clinew%2Cfalse)%3B'%2B%20''%2B%20'const%20STACK_MAX_SIZE%3D5%3B'%2B%20'let%20undoDataStack%3D%5B%5D%3B'%2B%20'let%20redoDataStack%3D%5B%5D%3B'%2B%20''%2B%20'function%20beforeDraw()%7B'%2B%20'%20redoDataStack%3D%5B%5D%3B'%2B%20'%20if(undoDataStack.length%20%3E%3DSTACK_MAX_SIZE)%7B'%2B%20'%20undoDataStack.pop()%3B'%2B%20'%7D'%2B%20'%20var%20w%3Ddocument.getElementById(%5C'canvas%5C').width%3B'%2B%20'%20var%20h%3Ddocument.getElementById(%5C'canvas%5C').height%3B'%2B%20'%20undoDataStack.unshift(ctx.getImageData(0%2C0%2Cw%2Ch))%3B'%2B%20'%7D'%2B%20''%2B%20'function%20undo()%7B'%2B%20'%20if(undoDataStack.length%20%3C%3D0)return%3B'%2B%20'%20var%20w%3Ddocument.getElementById(%5C'canvas%5C').width%3B'%2B%20'%20var%20h%3Ddocument.getElementById(%5C'canvas%5C').height%3B'%2B%20'%20redoDataStack.unshift(ctx.getImageData(0%2C0%2Cw%2Ch))%3B'%2B%20'%20var%20imageData%3DundoDataStack.shift()%3B'%2B%20'%20ctx.putImageData(imageData%2C0%2C0)%3B'%2B%20'%7D'%2B%20''%2B%20'function%20redo()%7B'%2B%20'%20if(redoDataStack.length%20%3C%3D0)return%3B'%2B%20'%20var%20w%3Ddocument.getElementById(%5C'canvas%5C').width%3B'%2B%20'%20var%20h%3Ddocument.getElementById(%5C'canvas%5C').height%3B'%2B%20'%20undoDataStack.unshift(ctx.getImageData(0%2C0%2Cw%2Ch))%3B'%2B%20'%20var%20imageData%3DredoDataStack.shift()%3B'%2B%20'%20ctx.putImageData(imageData%2C0%2C0)%3B'%2B%20'%7D'%2B%20'%3C%2Fscript%3E'%2B%20'%3C%2Fbody%3E'%2B%20'%3C%2Fhtml%3E%20'%3Bvar%20win%3Dwindow.open(''%2C''%2C'width%3D560%2Cheight%3D440')%3Bwin.document.write(hhh)%3Bvoid(0);

2.終わりに

  1. 結構長いHTML+CSS+JSなのに動いてビックリ!
  2. ブックマークレットは簡単で初心者でも作れる
  3. ブラウザで同期されるので、他のPCでもすぐ使える
  4. 中身がわかるので、セキュリティの心配もない
  5. Chromeのタブで開いているサイト側設定の為に、上手く動かない場合もあります

とても便利だと思います

おしまい