【问题标题】:How to step back in HTML5 Canvas history如何退回 HTML5 Canvas 历史
【发布时间】:2015-07-08 15:38:57
【问题描述】:

我有一个使用 Imgly HTML5 Canvas 插件的图像裁剪器。我需要能够为裁剪器设置历史堆栈,以便能够撤消裁剪操作。目前,我可以在单击按钮时清除画布,但我需要能够保留原始图像,并在裁剪步骤不正确的情况下返回画布中图像更改的历史记录。

我有以下内容可以简单地清除画布:

$("#renderButton").click(function() {
        var elem = $(".imgly-canvas");
        var canvas = elem.get(0);
        var context = canvas.getContext("2d");
        $('#file').val('');

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

插件在图像加载时创建画布元素:

Utils.getImageDataForImage = function(image) {
  var canvas, context;
  canvas = document.createElement("canvas");
  canvas.width = image.width;
  canvas.height = image.height;
  context = canvas.getContext("2d");
  context.drawImage(image, 0, 0);
  return context.getImageData(0, 0, image.width, image.height);
};

这用于调整大小:

    Utils.cloneImageData = function(imageData) {
  var i, newImageData, _i, _ref;
  newImageData = this.sharedContext.createImageData(imageData.width, imageData.height);
  for (i = _i = 0, _ref = imageData.data.length; 0 <= _ref ? _i < _ref : _i > _ref; i = 0 <= _ref ? ++_i : --_i) {
    newImageData.data[i] = imageData.data[i];
  }
  return newImageData;
};

/*
  @param {Object} dimensions
  @param {Integer} dimensions.width
  @param {Integer} dimensions.height
  @returns {HTMLCanvasElement}
*/


Utils.newCanvasWithDimensions = function(dimensions) {
  var canvas;
  canvas = document.createElement("canvas");
  canvas.width = dimensions.width;
  canvas.height = dimensions.height;
  return canvas;
};

/*
  @param {imageData} imageData
  @returns {HTMLCanvasElement}
*/


Utils.newCanvasFromImageData = function(imageData) {
  var canvas, context;
  canvas = document.createElement("canvas");
  canvas.width = imageData.width;
  canvas.height = imageData.height;
  context = canvas.getContext("2d");
  context.putImageData(imageData, 0, 0);
  return canvas;
};

所以我不确定如何构建一个调用堆栈来引用每个更改并返回到对画布中图像的修改历史。

【问题讨论】:

    标签: javascript jquery html canvas


    【解决方案1】:

    HTML5 画布很好地转换为 JSON,然后可用于重新加载画布。您可以将其存储在全局对象中。

    var myObj = window.myObj || {};
    
    myObj = {
        history: [],
        canvas: null
    };
    

    获取画布数据:

    myObj.canvas = document.getElementById('canvas-id');
    var ctx = myObj.canvas.getContext('2d');
    var data = JSON.stringify(ctx.getImageData(0, 0, myObj.canvas.width, myObj.canvas.height));
    
    myObj.history.push(data);
    

    重新加载数据:

    var reloadData = JSON.parse(myObj.history[someIndex]);
    var ctx = myObj.canvas.getContext('2d');
    ctx.putImageData(reloadData, 0, 0);
    

    一旦您可以存储/加载数据,棘手的部分就是管理myObj.history 数组。

    【讨论】:

      【解决方案2】:

      您应该查看command pattern。基本上,您需要为用户可以执行的每个操作编写一个函数。当他们单击按钮或加载图像时,不要立即调用该函数。相反,创建一个命令对象,其中包含执行命令所需的所有信息以及撤消命令所需的信息。

      命令应用于数据模型(图像和裁剪标记)。 “加载图像”命令需要记录新的和以前的图像 URL,以便您在浏览历史记录时可以加载正确的图像。

      对于裁剪命令,您需要存储旧的和新的裁剪矩形 - 如果您保留原始图像的副本。执行命令时,您将新的裁剪矩形应用于原始矩形并将其绘制在画布上。

      对于撤消,您使用原始图像和之前的裁剪矩形。

      因此,诀窍是定义一个数据模型,其中包含 UI 外观的所有信息(通常很难直接从 UI 获取 - 在将裁剪后的图像渲染到画布后,您无法获取裁剪信息) .然后这些命令会处理此状态(以便下一个命令可以保存它以供撤消)并更新 UI。

      【讨论】:

        猜你喜欢
        • 2014-11-07
        • 1970-01-01
        • 2017-11-25
        • 1970-01-01
        • 1970-01-01
        • 2015-09-19
        • 1970-01-01
        • 1970-01-01
        • 2012-05-21
        相关资源
        最近更新 更多