Tôi có một ứng dụng Sketching được thực hiện trong tất cả HTML5 và Javascript, và tôi đã tự hỏi làm thế nào tôi sẽ tạo ra một nút Undo, vì vậy bạn có thể hoàn tác điều cuối cùng bạn đã vẽ. Bất kỳ ý tưởng?Làm cách nào để thêm chức năng hoàn tác vào HTML5 Canvas?
Trả lời
Bạn phải lưu trữ tất cả các sửa đổi trong cơ sở dữ liệu. Sau đó, bạn có thể xóa sửa đổi mới nhất nếu người dùng muốn hoàn tác nó. Sau đó, bạn vẽ lại tất cả các hoạt động vẽ từ cơ sở dữ liệu của bạn một lần nữa.
Vui lòng xem http://whiffdoc.appspot.com/tests/schema/diagram để biết ví dụ về cách thực hiện việc này - trong trường hợp này bằng cách lưu trữ cấu trúc dữ liệu JSON biểu thị thông tin canvas trong phần tử DIV ẩn. (theo liên kết trên trang đến nguồn) –
@AaronWatters, liên kết này hướng dẫn tôi đến 404. Bạn có liên kết được cập nhật không? – link2pk
Trên http://arthurclemens.github.io/Javascript-Undo-Manager/ Tôi có ví dụ hoạt động hoàn tác với phần tử canvas. Khi bạn thực hiện một sửa đổi, bạn cung cấp cho trình quản lý hoàn tác các phương thức hoàn tác và làm lại. Theo dõi vị trí trong ngăn hoàn tác được thực hiện tự động. Mã nguồn là Github.
ví dụ của bạn có vẻ tốt! Cảm ơn bạn đã chia sẻ –
có vẻ tốt trong Chrome, nhưng không hoạt động trong Firefox – waspinator
Tôi đã khắc phục một số lỗi bản vẽ nhỏ trong bản trình diễn. –
Tùy chọn khác, nếu bạn cần thao tác các đối tượng là chuyển đổi canvas thành SVG bằng cách sử dụng thư viện để duy trì Canvas API ngăn không cho viết lại.
Ít nhất một thư viện như vậy tồn tại vào thời điểm này (tháng 11 năm 2011): SVGKit
Một khi bạn đã SVG, nó là dễ dàng hơn nhiều để loại bỏ các đối tượng và nhiều hơn nữa mà không cần phải vẽ lại toàn bộ vải.
Hoặc anh ta chỉ có thể sử dụng thư viện trừu tượng canvas, như [fabric.js] (http://kangax.github.com/fabric.js/) để có thể làm việc với các đối tượng trên canvas theo lập trình. – kangax
Tuyệt vời @kangax. Tôi tò mò, làm thế nào để bạn nghĩ fabric.js sẽ so sánh với SVGKit về hiệu suất khi nói đến chỉnh sửa đối tượng trong canvas với hàng trăm nút? –
Tôi không chắc nó so sánh với SVGKit như thế nào, nhưng khi nói đến số lượng lớn các đối tượng canvas có xu hướng hiệu quả hơn SVG. Hãy xem xét một số điểm chuẩn so sánh Raphael (dựa trên SVG) và vải (canvas-based) - http://fabricjs.com/benchmarks/ – kangax
Đây là giải pháp phù hợp với tôi. Tôi đã thử nó trong các phiên bản mới nhất của Firefox và Chrome và nó hoạt động thực sự tốt trong hai trình duyệt đó.
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();
Vì vậy, mỗi khi bạn vẽ bất cứ điều gì bạn sẽ có sau khi chức năng chạy canvasLogBook.logDrawing() để lưu ảnh chụp nhanh của khung hình và sau đó bạn có thể gọi canvasLogBook.undo() để hoàn tác và canvasLogBook.redo() làm lại.
Đây sẽ là một câu trả lời hay nếu bạn không phụ thuộc vào jQuery và nếu bạn loại bỏ boolean 'isFirefox' :) – A1rPun
Thanh toán [mẫu lệnh] (http://en.wikipedia.org/wiki/Command_pattern) – Anurag
tại sao bạn có thẻ java và target-c trong thẻ? –