2016-05-10 2 views
0

Я делаю очень простую программу «покраска» с использованием HTML5/Canvas. Я хотел бы дать пользователю возможность вернуться в «историю», например панель «История» в программах Photoshop/Adobe.Создание «панели истории» для программы рисования

В принципе, это будет кнопка отмены, но вы сможете вернуться к началу ваших действий, а также будет вести журнал, в котором будут показаны детали каждого действия.

Возможно ли это? Как я могу начать хранить эти данные?

Сколько памяти доступно в браузере Chrome, чтобы разрешить это на одной странице? - (Извините, если это глупо спросить, но совершенно новый для Javascript и работает в браузере.)

Я читал this undo button Question, что похоже, но я хотел бы сделать информацию о сохраненных данных.

Благодарю вас за помощь, которую вы можете дать!

ответ

1

Вам понадобится создать простой стоп-кадр с отменой повтора. Затем вам нужно решить, будете ли вы хранить векторные данные или данные изображения. Последний более эффективен, но может также занимать гораздо больше памяти. У вас могут быть случаи, когда вы хотите хранить оба типа данных (путь поверх изображений).

метод был бы в простых шагов:

  • магазин начальное состояние для нового документа. Держите указатель стека, указывающий на следующий свободный слот (например, используя массив).
  • При ударе мыши (или какая-либо другая операция, которая приведет к изменению) переместите указатель стека вперед.
  • Когда кнопка мыши отпущена, сделайте снимок, создайте эскиз и т. Д. Это зависит от вас, если вы хотите сохранить рисунок как точки или как растровое изображение. Если данные растровых изображений вы можете обойти в пространстве для хранения, сжимая его, например, zip. Переместите указатель стека вперед. Если в стеке есть моментальные снимки, удалите их.
  • Когда вам нужно отменить, просто откройте предыдущий сохраненный шаг и переместите указатель стека назад. Сохраняя моментальные снимки, вы можете сделать повтор, перемещая указатель стека вперед и перерисовывая моментальный снимок, если таковой имеется.
  • И, наконец, чтобы визуализировать стопку отмены, вы можете просто визуализировать каждый снимок на отдельном холсте по шкале и извлекать его как изображение, которое вы помещаете в список.

Примечание: при создании состояния отмены важно очистить любые снимки после позиции указателя нового стека. Это связано с тем, что если отменено использование, повторное использование можно использовать, если никаких изменений. Однако, если был отменен и добавлен новый чертеж, это приведет к недействительности следующих состояний, поэтому их нужно будет удалить.

Что касается памяти браузера, это будет зависеть от системы пользователя. У некоторых есть несколько гигабайт, у других - много. Невозможно узнать. Вам нужно будет выбрать стратегию UX, подходящую для вашего сценария, а также для целевой аудитории.

Пример

Это не выполняет логистики для обработки синхронизации миниатюр, но имеет большинство других частей. Я оставлю остальных в качестве упражнения.

var ctx = c.getContext("2d"), 
 
    stack = [],     // undo-redo stack 
 
    sp = 0,      // stack pointer 
 
    isDown = false;    // for drawing (demo) 
 

 
capture();      // create an initial undo capture (blank) 
 

 
ctx.lineCap = "round";   // setup line for demo 
 
ctx.lineWidth = 4; 
 

 
// simple draw mechanism 
 
c.onmousedown = function(e) { 
 
    sp++;       // on mouse down, move stack pointer to next slot 
 
    isDown = true;     // NOTE: clear any snapshots after this point (not shown) 
 
    var pos = getXY(e);   // start drawing some line - how you draw is up to you 
 
    ctx.beginPath(); 
 
    ctx.moveTo(pos.x, pos.y); 
 
} 
 

 
window.onmousemove = function(e) { 
 
    if (!isDown) return;   // only for drawing 
 
    var pos = getXY(e); 
 
    ctx.lineTo(pos.x, pos.y); 
 
    ctx.stroke(); 
 
    ctx.beginPath(); 
 
    ctx.moveTo(pos.x, pos.y); 
 
} 
 

 
window.onmouseup = function() { 
 
    if (!isDown) return; 
 
    isDown = false; 
 
    capture();      // capture an undo state 
 
    makeThumb();     // create and insert a thumbnail of state 
 
}; 
 

 
function capture() { 
 
    stack[sp] = c.toDataURL();  // one way, you could use getImageData, 
 
           // or store points instead.. it's up to you 
 
} 
 

 
// Creates a thumbnail of current canvas and insert into visible undo stack 
 
function makeThumb() { 
 
    var canvas = document.createElement("canvas"); 
 
    canvas.width = canvas.height = 64; 
 
    var ctxTmp = canvas.getContext("2d"); 
 
    ctxTmp.drawImage(c, 0, 0, canvas.width, canvas.height); 
 
    undos.appendChild(canvas); 
 
} 
 

 
// UNDO button clicked 
 
undo.onclick = function() { 
 
    var img = new Image;   // restore previous state/snapshot 
 
    img.onload = function() { 
 
    ctx.clearRect(0, 0, c.width, c.height); 
 
    ctx.drawImage(this, 0, 0); 
 
    } 
 
    
 
    // move stack pointer back and get previous snapshot 
 
    if (sp > 0) img.src = stack[--sp]; 
 
}; 
 

 
// REDO button clicked 
 
redo.onclick = function() { 
 
    
 
    // anything we can redo? 
 
    if (sp < stack.length) { 
 
    var img = new Image; 
 
    img.onload = function() { 
 
     ctx.clearRect(0, 0, c.width, c.height); 
 
     ctx.drawImage(this, 0, 0); 
 
    } 
 
    
 
    // move stack pointer forward and get next snapshot 
 
    img.src = stack[++sp]; 
 
    } 
 
}; 
 

 
function getXY(e) { 
 
    var r = c.getBoundingClientRect(); 
 
    return {x: e.clientX - r.left, y: e.clientY - r.top} 
 
}
#c {background:#ccc}
<button id=undo>Undo</button> 
 
<button id=redo>Redo</button><br> 
 
<canvas id=c width=500 height=500></canvas> 
 
<div id=undos></div>

+0

Святое дерьмо. Большое вам спасибо ... вы поняли причину, по которой я так люблю! ☆ 彡 ☆ 彡 ☆ 彡 ☆ ☆ –

+0

@ K3N, Хорошее использование превью! – markE

1

Вы можете копировать текущий холст на отдельный каждый раз при выполнении действия. Простое отображение старых холстов может служить журналом действий.

Вы можете отправить холст drawImage непосредственно:

destContext.drawImage(srcCanvas, 0, 0); 

Если такой подход потребляет слишком много памяти, альтернатива хранить все команды в стеке, удалить последний элемент, когда погубил, и перерисовывать все с нуля.

+0

Спасибо так много! Awesome, чтобы начать обертывать мою голову вокруг, как это будет работать ... –

Смежные вопросы