0

我遇到了一个大问题,我花了将近一个星期的时间试图让它工作,所以我真的很感激任何帮助 - 我正在尝试在 html5 中创建一个简单的图像编辑器,所以我上传了一张图片,将它加载到画布中然后绘画在上面 -

我还希望能够放大和缩小-只是我不知道应该如何保存画布状态-对于绘制鼠标事件,我正在使用一个保存canvas.toDataUrl的数组,但是这个只会保存它在画布中可见的内容,只是缩放图像的一部分,而不是整个图像 -

如果有人知道如何将画布与上面的绘画一起取消缩放并将其保存在堆栈中,我可以从中检索它以用于其他绘画活动,我将不胜感激!谢谢

4

1 回答 1

0

保存状态

画布'save()并且restore()根本与画布中的像素无关。Save()仅保存当前笔颜色、填充颜色、变换、缩放、旋转等 - 仅参数值,而不是实际像素数据。

因此,restore()只会将这些参数值恢复到以前的值。

canvas 元素是被动的,这意味着它只保存您在屏幕上看到的像素。它不会保留任何内容的备份,因此如果您更改其大小、重新调整浏览器窗口大小或在浏览器中打开导致其清除的对话框,您将需要自己更新画布。

这也适用于更改参数值(例如比例)时。画布上的任何内容都不会更改设置新值。唯一发生的事情是您的下一次绘制将使用这些参数值进行绘制(换句话说:如果您应用旋转,则不会旋转,但您绘制的下一个将旋转)。

在现有图像上绘图

由于您需要维护内容,这也意味着您需要存储绘制的图像以及绘制的内容。

例如,当您绘制线条时,您需要将每个笔划记录到数组中。当画布需要更新(即缩放)时,您首先以新的比例重绘原始图像,然后用线条遍历数组并重新渲染它们。

点,矩形,圆和你有什么都是一样的。

将画布视为您在其他地方存储的内容(图像对象、数组、对象)的快照。画布只是该数据的视口。

我建议这样存储:

var backgroundImage;  //reference to your uploaded image

var renderStack = []; //stores all drawing objects (see below)

//example generic object to hold strokes, shapes etc.
function renderObject() {
    this.type = 'stroke';  //or rectangle, or circle, or dot, ...
    this.x1;
    this.y1;
    this.x2;
    this.y2;
    this.radius;
    this.penWidth;
    this.penColor;
    this.fillColor;
    this.points = [];
    //...  extend as you need or use separate object for each type
}

然后当您绘制笔画(伪)时:

var currentRenderObject;

function mouseDown(e) {

    //get a new render object for new shape/line etc.
    currentRenderObject = new renderObject();

     //get type from your selected tool
    currentRenderObject.type = 'stroke'; //for example

    //do the normal draw operations, mouse position etc.
    x =..., y = ...
}

function mouseMove(e) {

    //get mouse positions, draw as normal
    x = ..., y = ...

    //store the points to the array, here:
    //we have a line or stroke, so we push the
    //values to ourpoint-array in the renderObject
    currentRenderObject.points.push(x);
    currentRenderObject.points.push(y);

}
function mouseUp(e) {

    //when paint is done, push the current renderObject
    //to our render stack
    renderStack.push(currentRenderObject);
}

现在您可以进行重绘功能:

function redraw() {

    clearCanvas();

    drawBackgroundImage();

    for(var i = 0, ro; ro = renderStack[i]; i++) {

        switch(ro.type) {
            case 'stroke':
                //... parse through point list
                break;
            case 'rectangle':
                //... draw rectangle
                break;
            ...
        }
    } 
}

function zoom(factor) {
    //set new zoom, position (scale/translate if you don't
    //want to do it manually). Remember that mouse coords need
    //to be recalculated as well to match the zoom factor.

    redraw();
}

//when canvas is scaled for some reason, or the window
canvas.onresize = windows.onresize = redraw;

这样做的好处是您也可以将渲染堆栈用作撤消/重做堆栈...

希望这有助于更好地理解画布是如何工作的。

于 2013-06-18T02:30:41.470 回答