2016-10-13 21 views
0

シンプルなキャンバス要素があり、それに複雑なリソース集約的な画像を描画するとします。私は絵の上にいくつかの単純な線を描きます。キャンバスの状態を(線が描画される前に)「保存」してから、それ以上の変更を消去するために状態を再描画する方法がありますか?私はsave()restore()でこれを試してみましたが、私はその状態がキャンバス上の現在の図形を含んでいるとは思いません。私のデモを下に見てください。変更後のキャンバスを元に戻す

var canvas = document.getElementById("canvas"); 
 
var context = canvas.getContext('2d'); 
 

 
function init() { 
 
    // This is some computationally intensive drawing we don't want to repeat 
 
    context.fillStyle = "rgb(150,29,28)"; 
 
    context.fillRect(40, 40, 255, 200); 
 
    context.fillStyle = "rgb(150,83,28)"; 
 
    context.fillRect(10, 10, 50, 50); 
 
    context.fillStyle = "rgb(17,90,90)"; 
 
    context.fillRect(5, 100, 200, 120); 
 
    context.fillStyle = "rgb(22,120,22)"; 
 
    context.fillRect(200, 200, 90, 90); 
 
    // Now we save the state so we can return to it 
 
    saveState(); 
 
} 
 

 
function lines() { 
 
    // This is some drawing we will do and then want to get rid of 
 
    context.beginPath(); 
 
    context.moveTo(125, 125); 
 
    context.lineTo(150, 45); 
 
    context.lineTo(200, 200); 
 
    context.closePath(); 
 
    context.stroke(); 
 
} 
 

 
function saveState() { 
 
    //copy the data into some variable 
 
} 
 

 
function loadState() { 
 
    //load the data from the variable and apply to canvas 
 
} 
 

 
init();
#canvas { 
 
    border: 1px solid #000; 
 
}
<canvas id="canvas" width="300" height="300"></canvas> 
 
<button onClick="lines()">Draw over image</button> 
 
<button onClick="loadState()">Restore</button>

+0

キャンバス上のピクセルにすべてがマージされている間に、各状態を追跡する必要があります。単純なアンドゥー・アンド・リドゥ・スタックを作成してください(https://github.com/epistemex/undo- redo)。 – K3N

答えて

4

キャンバスを新しいキャンバスに簡単にコピーできます。

// canvas is the canvas you want to copy. 
var canvasBack = document.createElement("canvas"); 
canvasBack.width = canvas.width; 
canvasBack.height = canvas.height; 
canvasBack.ctx = canvasBack.getContext("2d"); 
canvasBack.ctx.drawImage(canvas,0,0); 

それは別の画像であるので、リアルタイムで簡単に何度あたりを行うことができ、ハードウェアで実行された画像をレンダリング

ctx.drawImage(canvasBack,0,0); 

で元にそれをコピーすることができますかのようにあなたが新しいキャンバスを扱いますフレーム。このため、キャンバスをレイヤーとして扱うことができ(Photoshopなど)、globalCompositeOperationを使用することで幅広い調整可能なFXを作成できます。

dataURLに変換することはできますが、それは処理がはるかに遅く、リアルタイムレンダリングには十分速くはありません。また、DataURL文字列のコピーを保持し、それをイメージにデコードすると、キャンバスコピーを作成するだけでなく、4バイトごとに3バイト(24ビット)のエンコードが行われます。JS文字は16ビット長のデータBASE64で

代替(24ビットを格納するために使用されるメモリの64-ビット)は、非常に非効率的であるctx.getImageDataと型付き配列としてキャンバスを格納することであるが、これも非常に遅く、リアルタイムのニーズを扱うことができない。

+0

良い答え。質問者の疑惑について:はい、 'context.save&restore'が影響しますコンテキストプロパティ - キャンバスのコンテンツ(図面)を保存/復元しません。 – markE

0

あなたはsaveState(), use context.clearRect()to clearキャンバス, context.drawImage()to restore saved canvas`で元canvasを保存するためにcanvas.toDataURL()を呼び出し、<img>要素を作成することができます

var canvas = document.getElementById("canvas"); 
 
var context = canvas.getContext('2d'); 
 
var _canvas; 
 
var img = new Image; 
 
img.width = canvas.width; 
 
img.height = canvas.height; 
 

 
function init() { 
 
    // This is some computationally intensive drawing we don't want to repeat 
 
    context.fillStyle = "rgb(150,29,28)"; 
 
    context.fillRect(40, 40, 255, 200); 
 
    context.fillStyle = "rgb(150,83,28)"; 
 
    context.fillRect(10, 10, 50, 50); 
 
    context.fillStyle = "rgb(17,90,90)"; 
 
    context.fillRect(5, 100, 200, 120); 
 
    context.fillStyle = "rgb(22,120,22)"; 
 
    context.fillRect(200, 200, 90, 90); 
 
    // Now we save the state so we can return to it 
 
    saveState(canvas); 
 
} 
 

 
function lines() { 
 
    // This is some drawing we will do and then want to get rid of 
 
    context.beginPath(); 
 
    context.moveTo(125, 125); 
 
    context.lineTo(150, 45); 
 
    context.lineTo(200, 200); 
 
    context.closePath(); 
 
    context.stroke(); 
 
} 
 

 
function saveState(c) { 
 
    _canvas = c.toDataURL(); 
 
    //copy the data into some variable 
 
} 
 

 
function loadState() { 
 
    //load the data from the variable and apply to canvas 
 
    context.clearRect(0, 0, canvas.width, canvas.height); 
 
    img.onload = function() { 
 
    context.drawImage(img, 0, 0); 
 
    } 
 
    img.src = _canvas; 
 
} 
 

 

 
init();
#canvas { 
 
    border: 1px solid #000; 
 
}
<canvas id="canvas" width="300" height="300"></canvas> 
 
<button onClick="lines()">Draw over image</button> 
 
<button onClick="loadState()">Restore</button>

関連する問題