我正在尝试缓存用户为画布设置的不同状态,
事情是,当我稍后追加它时使用.push
和canvas.clone()
它的大小相同,但是白色;没有它显示的图像,
将canvas
存储在内存中的任何有效方法都可用吗?
- 编辑 -
这就是我尝试
的方式effectosFotos: function ($foto) {
var t;
var selector = '#'+$foto.attr('id');
var $foto = $(selector);
var $backup = $foto.clone();
var times = 0;
var cached = [];
$('.filters').show();
var img1 = document.createElement('img');
img1.onload = function () {
var width1 = $('.filters li').eq(0).width()/3;
var height1 = this.height*(width1/this.width);
console.log(width1, height1);
var canvas1 = document.createElement('canvas'),
ctx1 = canvas1.getContext('2d');
canvas1.width = width1;
canvas1.height = height1;
ctx1.drawImage(this, 0, 0, width1, height1);
var newUrl = canvas1.toDataURL('image/jpeg', 0.8);
$('.filters li a').each(function() {
$(this).append( '<img id="preview_'+$(this).data('id')+'" src="'+newUrl+'">' );
});
$('.filters li a').each(function(i) {
var $this = $(this);
t = setTimeout(function () {
var effect = $this.data('id');
var $img = $('#preview_'+effect);
//console.log('Item='+i +' About to render '+ effect +' and exists? ' + $img.length );
Caman('#preview_'+effect, function () {
this[effect]();
this.render(function(){
//console.log('rendered '+effect);
$this.parent().addClass('rendered');
});
});
}, 1*i)
});
}
img1.src = $foto.attr('src');
$('.filters').on('click', 'li:not(.active) a', function(e){
var start = new Date().getTime();
var $this = $(this).addClass('loading');
$this.parent().addClass('loading');
e.preventDefault();
var effect = $(this).data('id');
var parent = $(selector).parent();
//console.log('f'+$(selector).length, effect,times,$(selector).prop("tagName"),$backup.prop("tagName"));
/*if(times == 0){
$backup = $foto.clone();
}
times++;*/
$(selector).remove();
parent.append($backup);
console.log(cached);
var found = -1;
for ( var c = 0; c < cached.length; c++ ) {
var item = cached[c];
if ( item.effect == effect ) {
found = c;
}
}
if (effect == 'normal'){
$(selector).css('opacity',1);
$this.parent().addClass('active').removeClass('loading').siblings().removeClass('active');
} else if ( found > -1 ) {
console.log('Cargamos caché ' + effect + ' a '+width +'x'+height);
var canvas = document.getElementById($foto.attr('id'))
canvas.width = width;
canvas.height = height;
var ctx3 = canvas.getContext('2d');
ctx3.clearRect( 0, 0, width, height );
ctx3.drawImage( cached[found].canvas, 0, 0);
$this.parent().addClass('active').removeClass('loading').siblings().removeClass('active');
} else {
$(selector).remove();
parent.append($backup);
$(selector).css('opacity',0.3);
$('.takePictureHolder').addClass('caming');
Caman(selector, function () {
this[effect]();
this.render(function(){
$(selector).css('opacity',1);
$this.parent().addClass('active').removeClass('loading').siblings().removeClass('active');
$('.takePictureHolder').removeClass('caming');
if (found == -1) {
var canvas = document.getElementById($foto.attr('id'));
var clone = canvas.cloneNode(true);
clone.getContext('2d').drawImage(canvas, 0,0);
cached.push({ 'effect' :effect, "canvas":clone });
/*var ctx4 = document.getElementById($foto.attr('id')).getContext('2d');
console.log('Cacheamos ' + effect + ' a '+width +'x'+height);
cached.push({ 'effect' :effect, "canvas":ctx4.getImageData(0,0,width, height) });*/
}
var end = new Date().getTime();
var time = end - start;
console.log('Execution time: ' + time);
});
});
}
});
}
答案 0 :(得分:2)
您可以使用.getImageData()
保存画布的内容
并.putImageData()
用于恢复旧内容。
null
var data = [];
// store canvas/image
data.push(context.getImageData(0, 0, canvas.width, canvas.height));
// restore canvas/image
var oldData = data.pop();
canvas.width = oldData.width;
canvas.height = oldData.height;
context.clearRect(oldData, 0, 0, canvas.width, canvas.height);
context.putImageData(oldData, 0, 0);
var canvas = document.querySelector("canvas"),
context = canvas.getContext("2d"),
states = [],
img;
console.log("setup states...");
setupState();
function rndColor() {
var rgb = [];
for (var i = 0; i < 3; i++) {
rgb.push(Math.floor(Math.random() * 255));
}
return "rgb(" + rgb.join(",") + ")";
}
function setupState() {
canvas.width = 50 + Math.floor(Math.random() * 100);
canvas.height = 50 + Math.floor(Math.random() * 100);
context.fillStyle = rndColor();
context.fillRect(0, 0, canvas.width, canvas.height);
states.push(context.getImageData(0, 0, canvas.width, canvas.height));
if (states.length < 5) {
setTimeout(setupState, 1000);
} else {
console.log("restore states...");
setTimeout(restoreStates, 2000);
}
}
function restoreStates() {
var state = states.shift();
canvas.width = state.width;
canvas.height = state.height;
context.clearRect(0, 0, state.width, state.height);
context.putImageData(state, 0, 0);
if (states.length) {
setTimeout(restoreStates, 1000);
}
}
canvas { border: solid 5px blue }
.toDataUrl()
可以实现同样的目标
和.drawImage()
但这将是较慢的方法:jsperf(至少在chrome中)
<canvas></canvas>
var images = [];
// store canvas/image
var img = new Image();
img.src = canvas.toDataURL();
images.push(img);
// restore canvas/image
var oldImage = images.pop();
canvas.width = oldImage.width;
canvas.height = oldImage.height;
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(oldImage, 0, 0);
var canvas = document.querySelector("canvas"),
context = canvas.getContext("2d"),
states = [],
img;
console.log("setup states...");
setupState();
function rndColor() {
var rgb = [];
for (var i = 0; i < 3; i++) {
rgb.push(Math.floor(Math.random() * 255));
}
return "rgb(" + rgb.join(",") + ")";
}
function setupState() {
canvas.width = 50 + Math.floor(Math.random() * 100);
canvas.height = 50 + Math.floor(Math.random() * 100);
context.fillStyle = rndColor();
context.fillRect(0, 0, canvas.width, canvas.height);
img = new Image();
img.src = canvas.toDataURL();
states.push(img);
if (states.length < 5) {
setTimeout(setupState, 1000);
} else {
console.log("restore states...");
setTimeout(restoreStates, 2000);
}
}
function restoreStates() {
var state = states.shift();
canvas.width = state.width;
canvas.height = state.height;
context.clearRect(0, 0, canvas.width, canvas.height);
context.drawImage(state, 0, 0);
if (states.length) {
setTimeout(restoreStates, 1000);
}
}
canvas { border: solid 5px blue }
答案 1 :(得分:2)
比导出方法更简单,更有效的方法是使用clonedCtx.drawImage(canvas, 0,0)
在克隆上绘制待保存的画布。然后,您将能够将克隆的画布存储在数组中:
安德烈亚斯&#39;已修改代码的代码段:
var canvas = document.querySelector("canvas"),
context = canvas.getContext("2d"),
states = [];
console.log('setup states...');
setupState();
function rndColor() {
var rgb = [];
for (var i = 0; i < 3; i++) {
rgb.push(Math.floor(Math.random() * 255));
}
return "rgb(" + rgb.join(",") + ")";
}
function setupState() {
canvas.width = 50 + Math.floor(Math.random() * 100);
canvas.height = 50 + Math.floor(Math.random() * 100);
context.fillStyle = rndColor();
context.fillRect(0, 0, canvas.width, canvas.height);
var clone = canvas.cloneNode(true);
clone.getContext('2d').drawImage(canvas, 0,0);
states.push(clone)
if (states.length < 5) {
setTimeout(setupState, 1000);
} else {
console.log("restore states...");
setTimeout(restoreStates, 2000);
}
}
function restoreStates() {
var state = states.shift();
canvas.width = state.width;
canvas.height = state.height;
context.clearRect(0, 0, state.width, state.height);
context.drawImage(state, 0, 0);
if (states.length) {
setTimeout(restoreStates, 1000);
}
}
&#13;
canvas { border: solid 5px blue }
&#13;
<canvas></canvas>
&#13;
但是,正如@markE所指出的,如果您需要存储很多这些状态(例如,如果您想要实现撤消/重做功能),它可以快速填满您的所有记忆。
然后推荐的方法是保存所有绘图操作并重新应用它们。还在使用Andreas&#39;片段,最小的实现可能是:
var canvas = document.querySelector("canvas"),
context = canvas.getContext("2d"),
states = [];
console.log('setup states...');
setupState();
function rndColor() {
var rgb = [];
for (var i = 0; i < 3; i++) {
rgb.push(Math.floor(Math.random() * 255));
}
return "rgb(" + rgb.join(",") + ")";
}
function setupState() {
// create an object with all our states settings and operations
var state = {fillStyle: rndColor(), width: Math.floor(Math.random() * 100), height:Math.floor(Math.random() * 100)};
// save the operations in an array
state.operations = [{name:'fillRect',arguments: [0,0,state.width, state.height]}];
// save the state
states.push(state);
// parse it a first time;
parse(state);
if (states.length < 5) {
setTimeout(setupState, 1000);
} else {
console.log("restore states...");
setTimeout(restoreStates, 2000);
}
}
function parse(state){
// restore our canvas and context's properties
// this could be improved by creating canvas and context objects in our state and then restore the corresponding with a for(x in y) loop
canvas.width = state.width;
canvas.height = state.height;
context.fillStyle = state.fillStyle;
// retrieve the operations we applied
var op = state.operations;
// loop through them
for(var i=0; i<op.length; i++){
// check it actually exists as a function
if(typeof context[op[i].name]==='function')
// apply the saved arguments
context[op[i].name].apply(context, op[i].arguments);
}
}
function restoreStates() {
var state = states.shift();
parse(state);
if (states.length) {
setTimeout(restoreStates, 1000);
}
}
&#13;
canvas { border: solid 1px blue }
&#13;
<canvas></canvas>
&#13;