如何使用数组添加撤消列表?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何使用数组添加撤消列表?相关的知识,希望对你有一定的参考价值。

我正在尝试用javascript制作一个绘图程序,我想要包含一个undo-function(不是橡皮擦)。如何将所有事件添加到数组中,然后逐个删除它们?

我有一个工具下拉列表(到目前为止只有四个工作)。我添加了一个带id的撤消按钮。我已经尝试了几个小时(实际上是几天)来了解如何做到这一点。我找到了一些例子,我想我必须同时使用push和一个空数组来进一步发展?

这是工具选择和按钮的代码

<label>
  Object type:
    <select id="selectTool">
        <option value="line">Linje</option>
        <option value="pencil">Blyant</option>
        <option value="rect">Rektangel</option>
        <option value="circle">Sirkel</option>
        <option value="oval">Oval</option>
        <option value="polygon">Polygon</option>
    </select>

  Shape drawn:
    <select id="shapeDrawn">
        <option value=""></option>
    </select>   

  <input type="button" id="cmbDelete" value="Undo last action">

</label>

撤消功能可能是这样的,但这个功能

var shapes = [];
shapes.push(newShape);


 function cmbDeleteClick()
  if(shapes.length > 0)
    var selectedShapeIndex = selectShape.selectedIndex;
    shapes.splice(selectedShapeIndex,1);
    selectShape.options.remove(selectedShapeIndex);
    selectShape.selectedIndex = selectShape.options.length - 1;
  
    cmbDelete = document.getElementById("cmbDelete");
    cmbDelete.addEventListener("click",cmbDeleteClick, false);
    fillSelectShapeTypes();
    drawCanvas(); 

理想情况下,画布上绘制的所有内容都会添加到下拉菜单中,并且可以通过单击按钮将其删除(撤消)。这是代码JS Bin的“工作”版本

答案

您当前的实现不使用shapes数组,并且无法在创建它们之后重绘它们。

因此,最简单的方法是将每个操作存储为位图。所以你需要一个位图数组,让我们调用它:

var history = [];

绘制完东西之后,我们创建当前画布的快照并将其存储在该数组中:

history.push(contextTmp.getImageData(0,0,canvasTmp.width,canvasTmp.height))

如果要撤消操作,请弹出历史记录并在画布上绘制最后一个位图:

function cmbDeleteClick()
    history.pop()
    contextTmp.putImageData(history[history.length-1],0,0)

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Paint</title>
	<style type="text/css">
		#content  position: relative; 
		#cvs  border: 1px solid #c00; 
		#cvsTmp  position: absolute; top: 1px; left: 1px; 
    </style>
</head>
<body>
<p>
		
<label>
Object type:
	<select id="selectTool">
		<option value="line">Linje</option>
		<option value="pencil">Blyant</option>
		<option value="rect">Rektangel</option>
		<option value="circle">Sirkel</option>
		<option value="oval">Oval</option>
		<option value="polygon">Polygon</option>
	</select>
	
Shape drawn:
	<select id="shapeDrawn">
		<option value=""></option>
	</select>	
	
History:
	<select id="historySelect">
	</select>	
  
<input type="button" id="cmbDelete" value="Undo last action">

</label>

</p>
	
<div id="content">
	<canvas id="cvs" width="1024" height="512"></canvas>
</div>

<script type="text/javascript">

	
if(window.addEventListener) 
window.addEventListener('load', function () 
  var canvas;
  var context;
  var canvasTmp;
  var contextTmp;

  var tool;
  var toolDefault = 'line';
	
  var cmbDelete = null;
  var shapes = [];
  var history = [];
  var historySelect;

// Canvas and temp. canvas
	
function init () 
    canvasTmp = document.getElementById('cvs');
	  if (!canvasTmp) 
		  return;
	   if (!canvasTmp.getContext) 
      return;
    
    
    historySelect = document.getElementById('historySelect')
    historySelect.addEventListener('change', ()=>
      restoreHistoryAction(historySelect.value)
    )

    contextTmp = canvasTmp.getContext('2d');
	  if (!contextTmp) 
		  return;
	  

    // Add the temporary canvas.
    var content = canvasTmp.parentNode;
    canvas = document.createElement('canvas');
    if (!canvas) 
      return;
    

    canvas.id     = 'cvsTmp';
    canvas.width  = canvasTmp.width;
    canvas.height = canvasTmp.height;
    content.appendChild(canvas);

    context = canvas.getContext('2d');
  

    // Get the tool select input.
    var toolSelect = document.getElementById('selectTool');
    if (!toolSelect) 
      return;
    
    toolSelect.addEventListener('change', ev_tool_change, false);

    // Activate the default tool.
    if (tools[toolDefault]) 
      tool = new tools[toolDefault]();
      toolSelect.value = toolDefault;
    

    // Attach the mousedown, mousemove and mouseup event listeners.
    canvas.addEventListener('mousedown', evMouse, false);
    canvas.addEventListener('mousemove', evMouse, false);
    canvas.addEventListener('mouseup',   evMouse, false);
  
    drawCanvas()
  

function evMouse (ev) 
    if (ev.layerX || ev.layerX == 0) 
      ev._x = ev.layerX;
      ev._y = ev.layerY;
    
	var evHandler = tool[ev.type];
	if (evHandler) 
		evHandler(ev);
	

	
  // The event handler for any changes made to the tool selector.
  function toolChange (ev) 
    if (tools[this.value]) 
      tool = new tools[this.value]();
    
  	
	
	
  // Updates Canvas on interval timeout
function drawCanvas() 
	contextTmp.drawImage(canvas, 0, 0);
    history.push(contextTmp.getImageData(0,0,canvasTmp.width,canvasTmp.height))
    updateHistorySelection()
	context.clearRect(0, 0, canvas.width, canvas.height);

	
  function ev_tool_change (ev) 
    if (tools[this.value]) 
      tool = new tools[this.value]();
    
  

  // Get excact position for mouse coordinates in canvas
  function mouseAction (ev) 
    if (ev.layerX || ev.layerX == 0) 
      ev._x = ev.layerX;
      ev._y = ev.layerY;
    

    // Call the event handler of the tool.
    var func = tool[ev.type];
    if (func) 
      func(ev);
    
  


  function selectShapeChange()
    drawCanvas();
  
	
	

	
	
 var tools = ;

  // The drawing pencil.
  tools.pencil = function () 
    var tool = this;
    this.started = false;

    this.mousedown = function (ev) 
        context.beginPath();
        context.moveTo(ev._x, ev._y);
        tool.started = true;
    ;

    this.mousemove = function (ev) 
      if (tool.started) 
        context.lineTo(ev._x, ev._y);
        context.stroke();
      
    ;

    this.mouseup = function (ev) 
      if (tool.started) 
        tool.mousemove(ev);
        tool.started = false;
        drawCanvas();
      
    ;
  ;
	
// The rectangle tool.
  tools.rect = function () 
    var tool = this;
    this.started = false;

    this.mousedown = function (ev) 
      tool.started = true;
      tool.x0 = ev._x;
      tool.y0 = ev._y;
    ;

    this.mousemove = function (ev) 
      if (!tool.started) 
        return;
      

      var x = Math.min(ev._x,  tool.x0),
          y = Math.min(ev._y,  tool.y0),
          w = Math.abs(ev._x - tool.x0),
          h = Math.abs(ev._y - tool.y0);

      context.clearRect(0, 0, canvas.width, canvas.height);

      if (!w || !h) 
        return;
      
      context.fillRect(x, y, w, h);
		context.fillStyle = 'hsl(' + 360 * Math.random() + ', 50%, 50%)';
    ;

    this.mouseup = function (ev) 
      if (tool.started) 
        tool.mousemove(ev);
        tool.started = false;
        drawCanvas();
      
    ;
  ;

  // The line tool.
  tools.line = function () 
    var tool = this;
    this.started = false;

    this.mousedown = function (ev) 
      tool.started = true;
      tool.x0 = ev._x;
      tool.y0 = ev._y;
    ;

    this.mousemove = function (ev) 
      if (!tool.started) 
        return;
      

      context.clearRect(0, 0, canvas.width, canvas.height);

      context.beginPath();
      context.moveTo(tool.x0, tool.y0);
      context.lineTo(ev._x,   ev._y);
      context.stroke();
      context.closePath();
    ;

    this.mouseup = function (ev) 
      if (tool.started) 
        tool.mousemo

以上是关于如何使用数组添加撤消列表?的主要内容,如果未能解决你的问题,请参考以下文章

如何撤消添加版本应用程序而不还原

如何撤消strip - 即将符号添加回剥离的二进制文件

如何在提交之前撤消“git add”?

如何撤消和/或清除添加到 UIView 的 UIImageView?

撤消或反向 argsort(),python

如何撤消 Mercurial 中所有添加的文件