Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/411.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何将撤销功能添加到HTML5画布?_Javascript_Html_Canvas - Fatal编程技术网

Javascript 如何将撤销功能添加到HTML5画布?

Javascript 如何将撤销功能添加到HTML5画布?,javascript,html,canvas,Javascript,Html,Canvas,我有一个用HTML5和Javascript制作的素描应用程序,我想知道如何创建一个撤销按钮,这样你就可以撤销你最后画的东西。有什么想法吗?您必须将所有修改存储在数据结构中。然后,如果用户想要撤消最新的修改,您可以将其删除。然后重新绘制数据结构中的所有绘图操作。在上,我有一个使用canvas元素撤消的工作示例。进行修改时,可以向撤消管理器提供撤消和重做方法。撤消堆栈中的位置跟踪是自动完成的。源代码位于Github。如果需要操作对象,另一个选项是使用保留画布API的库将画布转换为SVG,以防止重写

我有一个用HTML5和Javascript制作的素描应用程序,我想知道如何创建一个撤销按钮,这样你就可以撤销你最后画的东西。有什么想法吗?

您必须将所有修改存储在数据结构中。然后,如果用户想要撤消最新的修改,您可以将其删除。然后重新绘制数据结构中的所有绘图操作。

在上,我有一个使用canvas元素撤消的工作示例。进行修改时,可以向撤消管理器提供撤消和重做方法。撤消堆栈中的位置跟踪是自动完成的。源代码位于Github。

如果需要操作对象,另一个选项是使用保留画布API的库将画布转换为SVG,以防止重写

目前(2011年11月)至少存在一个这样的库:


一旦有了SVG,就可以更轻松地删除对象和更多内容,而无需重新绘制整个画布。

这里有一个适合我的解决方案。我已经在最新版本的Firefox和Chrome中试用过,在这两种浏览器中效果非常好

var isFirefox = typeof InstallTrigger !== 'undefined';
var ctx = document.getElementById('myCanvas').getContext("2d");
var CanvasLogBook = function() {
    this.index = 0;
    this.logs = [];
    this.logDrawing();
};
CanvasLogBook.prototype.sliceAndPush = function(imageObject) {
    var array;
    if (this.index == this.logs.length-1) {
        this.logs.push(imageObject);
        array = this.logs;
    } else {
        var tempArray = this.logs.slice(0, this.index+1);
        tempArray.push(imageObject);
        array = tempArray;
    }
    if (array.length > 1) {
        this.index++;
    }
    return array;
};
CanvasLogBook.prototype.logDrawing = function() { 
    if (isFirefox) {
        var image = new Image();
        image.src = document.getElementById('myCanvas').toDataURL();
        this.logs = this.sliceAndPush(image);
    } else {
        var imageData = document.getElementById('myCanvas').toDataURL();
        this.logs = this.sliceAndPush(imageData);
    }
};
CanvasLogBook.prototype.undo = function() {
    ctx.clearRect(0, 0, $('#myCanvas').width(), $('#myCanvas').height());
    if (this.index > 0) {
        this.index--;
        this.showLogAtIndex(this.index);
    }
};
CanvasLogBook.prototype.redo = function() {
    if (this.index < this.logs.length-1) {
        ctx.clearRect(0, 0, $('#myCanvas').width(), $('#myCanvas').height());
        this.index++;
        this.showLogAtIndex(this.index);
    }
};
CanvasLogBook.prototype.showLogAtIndex = function(index) {
    ctx.clearRect(0, 0, $('#myCanvas').width(), $('#myCanvas').height());
    if (isFirefox) {
        var image = this.logs[index];
        ctx.drawImage(image, 0, 0);
    } else {
        var image = new Image();
        image.src = this.logs[index];
        ctx.drawImage(image, 0, 0);
    }
};
var canvasLogBook = new CanvasLogBook();
var isFirefox=typeof InstallTrigger!='未定义';
var ctx=document.getElementById('myCanvas').getContext(“2d”);
var CanvasLogBook=函数(){
该指数=0;
this.logs=[];
这是logDrawing();
};
CanvasLogBook.prototype.sliceAndPush=函数(imageObject){
变量数组;
if(this.index==this.logs.length-1){
this.logs.push(imageObject);
array=this.logs;
}否则{
var tempArray=this.logs.slice(0,this.index+1);
tempArray.push(imageObject);
数组=临时数组;
}
如果(array.length>1){
这个.index++;
}
返回数组;
};
CanvasLogBook.prototype.logDrawing=function(){
如果(iFirefox){
var image=新图像();
image.src=document.getElementById('myCanvas').toDataURL();
this.logs=this.sliceAndPush(图像);
}否则{
var imageData=document.getElementById('myCanvas').toDataURL();
this.logs=this.sliceAndPush(imageData);
}
};
CanvasLogBook.prototype.undo=函数(){
ctx.clearRect(0,0,$('#myCanvas').width(),$('#myCanvas').height());
如果(this.index>0){
本索引--;
this.showLogAtIndex(this.index);
}
};
CanvasLogBook.prototype.redo=函数(){
if(this.index

因此,每次绘制任何东西时,运行函数canvasLogBook.logDrawing()来存储画布的快照,然后可以调用canvasLogBook.undo()来撤消和canvasLogBook.redo()来恢复重做。

签出为什么标记中有java和objective-c?请参阅如何执行此操作的示例—在本例中,将表示画布信息的JSON数据结构存储在不可见的DIV元素中。(跟随页面上的链接至来源)@AaronWatters,此链接将我指向404。你有更新的链接吗?或者他可以只使用画布抽象库,比如能够以编程方式处理画布上的对象。非常好@kangax。我很好奇,你认为fabric.js在编辑具有数百个节点的画布中的对象时,在性能方面与SVGKit相比如何?我不确定它与SVGKit相比如何,但当涉及到大量对象时,canvas往往比SVG性能更好。看一看比较Raphael(基于SVG)和fabric(基于画布)的一些基准测试——感谢这些基准测试,但它们仅在静态图像上与Raphaël进行比较,而静态图像显然更倾向于画布。你和动画有什么比较基准吗?目前没有。我看看能不能做点什么。或者其他人会。我已经在演示中修复了几个小的绘图错误。这个演示在Chrome和Opera中绘制了各种颜色的圆圈,如果FF没有,在IE中绘制黑色。非常奇怪。修复后,我希望进行后续操作。我已更新了演示URL,使其指向最新版本。如果您不依赖jQuery,并且摆脱了
iFirefox
boolean:),这将是一个很好的答案。)