目次
はじめに
前々からCanvasにペイントツールのような「戻る」や「進む」の機能が欲しいなと思っていました。
という訳で作ってみました!
作ってみる
■HTML
<canvas id="canvassample" width="500" height="300"></canvas> <div> <button type="button" onclick="prevCanvas()">戻る</button> <button type="button" onclick="nextCanvas()">進む</button> </div>
■CSS
canvas { position: relative; border:3px solid #000; } div#img-box{ border:3px solid #000; width:500px; } div#btn-box{ position: fixed; bottom :0px; }
■JavaScript
var canvas = document.getElementById('canvassample'), ctx = canvas.getContext('2d'), moveflg = 0, Xpoint, Ypoint, temp = []; //初期値(サイズ、色、アルファ値)の決定 var defSize = 7, defColor = "#555"; // ストレージの初期化 var myStorage = localStorage; window.onload = initLocalStorage(); // PC対応 canvas.addEventListener('mousedown', startPoint, false); canvas.addEventListener('mousemove', movePoint, false); canvas.addEventListener('mouseup', endPoint, false); // スマホ対応 canvas.addEventListener('touchstart', startPoint, false); canvas.addEventListener('touchmove', movePoint, false); canvas.addEventListener('touchend', endPoint, false); function startPoint(e){ e.preventDefault(); ctx.beginPath(); console.log(e.clientX); // 矢印の先っぽから始まるように調整 Xpoint = e.clientX-8; Ypoint = e.clientY-8; ctx.moveTo(Xpoint, Ypoint); } function movePoint(e){ if(e.buttons === 1 || e.witch === 1 || e.type == 'touchmove') { Xpoint = e.pageX-8; Ypoint = e.pageY-8; moveflg = 1; ctx.lineTo(Xpoint, Ypoint); ctx.lineCap = "round"; ctx.lineWidth = defSize * 2; ctx.strokeStyle = defColor; ctx.stroke(); } } function endPoint(e) { if(moveflg === 0) { ctx.lineTo(Xpoint-1, Ypoint-1); ctx.lineCap = "round"; ctx.lineWidth = defSize * 2; ctx.strokeStyle = defColor; ctx.stroke(); } moveflg = 0; setLocalStoreage(); } function resetCanvas() { ctx.clearRect(0, 0, ctx.canvas.clientWidth, ctx.canvas.clientHeight); } function initLocalStorage(){ myStorage.setItem("__log", JSON.stringify([])); } function setLocalStoreage(){ var png = canvas.toDataURL(); var logs = JSON.parse(myStorage.getItem("__log")); setTimeout(function(){ logs.unshift({png:png}); myStorage.setItem("__log", JSON.stringify(logs)); temp = []; }, 0); } function prevCanvas(){ var logs = JSON.parse(myStorage.getItem("__log")); if(logs.length > 0) { temp.unshift(logs.shift()); setTimeout(function(){ myStorage.setItem("__log", JSON.stringify(logs)); resetCanvas(); draw(logs[0]['png']); }, 0); } } function nextCanvas(){ var logs = JSON.parse(myStorage.getItem("__log")); if(temp.length > 0) { logs.unshift(temp.shift()); setTimeout(function(){ myStorage.setItem("__log", JSON.stringify(logs)); resetCanvas(); draw(logs[0]['png']); }, 0); } } function draw(src) { var img = new Image(); img.src = src; img.onload = function() { ctx.drawImage(img, 0, 0); } }
■デモ
See the Pen Canvas to go back and forward by カバの樹 (@kabanoki) on CodePen.0
解説
動作の流れをざっくり説明すると、以下になります。
- Canvasに文字を書く
- Canvasを画像化する
- 画像を配列に格納してローカルストレージに保存
- ローカルストレージの配列から画像を取得
- Canvasに反映する
Canvasに文字を書く
過去のこの記事を参考
-
参考Canvasを使って手書きの署名機能を実装する
ルート営業を行うクライアントから、タブレットの契約書に手書きで署名できる機能が欲しいと言われました。
アプリで作ろうか悩みましたが、試しにHTML5で実装したものを提案してみました。続きを見る
Canvasを画像化する
過去のこの記事を参考
-
参考Canvasで書いたものを画像に変換する
Canvasで署名したものを画像に変換します。そして、書いたものを消せるように消しゴム機能も実装しました。
続きを見る
画像を配列に格納してローカルストレージに保存
まず下記設定でローカルストレージを呼び出しつつ、初期化します。
// ストレージの呼び出し var myStorage = localStorage; // ストレージの初期化 window.onload = initLocalStorage(); function initLocalStorage(){ myStorage.setItem("__log", JSON.stringify([])); }
次に、画像を配列に格納して、ローカルストレージに保存します。
function setLocalStoreage() { // 履歴データ保存用の変数 // これは履歴を戻った時に、戻る前の画像データを一時確保しておく為のもの var temp = [] // 画像化する var png = canvas.toDataURL(); // ローカルストレージから配列を取得 var logs = JSON.parse(myStorage.getItem("__log")); setTimeout(function(){ // 配列に画像を格納 logs.unshift({png}); // ローカルストレージに配列を保存 myStorage.setItem("__log", JSON.stringify(logs)); // 履歴を初期化 temp = []; }, 0); }
ローカルストレージの配列から画像を取得
ローカルストレージに保存されている配列を利用して、Canvasを戻したり進めたりする機能を実装する。
// Canvasを戻す function prevCanvas(){ var logs = JSON.parse(myStorage.getItem("__log")); if(logs.length > 0) { temp.unshift(logs.shift()); setTimeout(function(){ myStorage.setItem("__log", JSON.stringify(logs)); //Canvasを初期化する resetCanvas(); //画像を描写する draw(logs[0]['png']); }, 0); } } // Canvasを進める function nextCanvas(){ var logs = JSON.parse(myStorage.getItem("__log")); if(temp.length > 0) { logs.unshift(temp.shift()); setTimeout(function(){ myStorage.setItem("__log", JSON.stringify(logs)); //Canvasを初期化する resetCanvas(); //画像を描写する draw(logs[0]['png']); }, 0); } }
Canvasに反映
Canvasに画像を描写します。
function draw(src) { var img = new Image(); img.src = src; img.onload = function() { ctx.drawImage(img, 0, 0); } }
いかがでしょうか?
今日はこの辺でー