Javascript 无法从其他函数还原画布上下文

Javascript 无法从其他函数还原画布上下文,javascript,html,canvas,Javascript,Html,Canvas,恐怕我很难理解javascript中的canvas.getContext(“2d”).save()end restore()函数 我希望这个例子能解释这个问题。应该发生的是,画布上下文在创建时保存,当您在不同的工具之间更改时,保存的状态应该恢复,以便每次重置上下文 但是,如果您使用铅笔,然后选择橡皮擦,然后返回铅笔,所发生的是上下文。globalCompositeOperation继续是“destination out”:本质上铅笔继续擦除 任何未硬设置的上下文参数似乎都不会被更改,即保存的上下

恐怕我很难理解javascript中的canvas.getContext(“2d”).save()end restore()函数

我希望这个例子能解释这个问题。应该发生的是,画布上下文在创建时保存,当您在不同的工具之间更改时,保存的状态应该恢复,以便每次重置上下文

但是,如果您使用铅笔,然后选择橡皮擦,然后返回铅笔,所发生的是上下文。globalCompositeOperation继续是“destination out”:本质上铅笔继续擦除

任何未硬设置的上下文参数似乎都不会被更改,即保存的上下文不会被还原

你们这些善良的人能帮我理解我错在哪里吗

document.querySelector(“img”).addEventListener(“单击”),函数(事件){
/*创建新的画布元素以编辑图像*/
var canvas=document.createElement(“canvas”);
canvas.width=event.target.offsetWidth;
canvas.height=event.target.offsetHeight;
canvas.innerHTML=event.target.alt;
canvas.getContext(“2d”).drawImage(event.target,0,0);
/*这里是我们保存上下文状态的地方*/
canvas.getContext(“2d”).save();
/*用canvas替换img元素*/
event.target.parentNode.replaceChild(画布,event.target);
});
/*\
\*/
document.querySelector(“旁白”).addEventListener(“更改”,函数(事件){
var canvas=document.querySelector(“canvas”);
如果(!画布){
返回;
}
var context=canvas.getContext(“2d”);
/*还原画布状态以重置上下文*/
restore();
开关(event.target.value){
“铅笔”盒:
context.lineJoin=“round”;
context.lineCap=“round”;
context.lineWidth=“6”;
context.strokeStyle=“rgb(0,0,0)”;
打破
案例“橡皮擦”:
context.globalCompositeOperation=“目标输出”;
context.lineJoin=“round”;
context.lineCap=“round”;
context.lineWidth=“20”;
打破
}
canvas.onmousedown=函数(事件){
context.beginPath();
moveTo(event.offsetX,event.offsetY);
canvas.onmousemove=函数(事件){
lineTo(event.offsetX,event.offsetY);
stroke();
}
document.querySelector(“main”).onmouseup=函数(事件){
canvas.onmousemove=null;
this.onmouseup=null;
}
}
});
正文{
显示器:flex;
}
主要{
边缘:0.5em;
}
主要img,
主画布{
显示:内联块;
宽度:200px;
高度:200px;
文本对齐:居中;
颜色:rgb(200200);
背景色:rgb(250250);
光标:指针;
}
旁白{
边缘:0.5em;
}
旁侧输入[type='radio']{
显示:无;
}
旁侧输入[type='radio']+标签{
显示:块;
保证金:0自动;
框大小:边框框;
线高:1.5em;
文本对齐:居中;
填充:0.5em;
边框样式:实心;
边框宽度:1px;
边框颜色:rgb(127127);
边界半径:0.25em;
背景:rgb(245);
光标:指针;
}
旁侧输入[type='radio']:选中+标签{
背景:rgb(240240);
}

铅笔
橡皮擦
  • 单击图像以创建画布元素
  • 选择要绘制的铅笔或橡皮擦

  • 在内部,
    保存
    恢复
    共享一个通用的状态堆栈,您可以将其视为一个数组

    每次调用
    save
    ,上下文的所有当前默认属性都会推送到该堆栈中。
    每次调用
    restore
    ,最后一个状态都会从堆栈中弹出,其所有保存的属性都设置为上下文

    这意味着每个保存的状态只能恢复一次

    在代码中,在init时只调用一次
    save
    。然后在第一次输入的
    change
    事件中恢复此状态,同时删除此初始状态。所有后续对
    restore
    的调用都将无效,因为保存的状态堆栈中不再有任何内容

    一般来说,我建议在这种情况下不要使用保存和恢复,而是在每次需要时设置和重置每个属性;但是,由于问题是关于这些方法的,因此有一种方法可以使代码正常工作:

    在每个更改事件中进行恢复,然后立即保存。这样,您将始终从默认属性开始

    document.querySelector(“img”).addEventListener(“单击”),函数(事件){
    /*创建新的画布元素以编辑图像*/
    var canvas=document.createElement(“canvas”);
    canvas.width=event.target.offsetWidth;
    canvas.height=event.target.offsetHeight;
    canvas.innerHTML=event.target.alt;
    canvas.getContext(“2d”).drawImage(event.target,0,0);
    /*用canvas替换img元素*/
    event.target.parentNode.replaceChild(画布,event.target);
    });
    document.querySelector(“旁白”).addEventListener(“更改”,函数(事件){
    var canvas=document.querySelector(“canvas”);
    如果(!画布){
    返回;
    }
    var context=canvas.getContext(“2d”);
    /*还原画布状态以重置上下文*/
    restore();
    /*现在保存为默认值*/
    context.save();
    开关(event.target.value){
    “铅笔”盒:
    context.lineJoin=“round”;
    context.lineCap=“round”;
    context.lineWidth=“6”;
    context.strokeStyle=“rgb(0,0,0)”;
    打破
    案例“橡皮擦”:
    context.globalCompositeOperation=“目标输出”;
    context.lineJoin=“round”;
    context.lineCap=“round”;
    context.lineWidth=“20”;
    打破
    }
    canvas.onmousedown=函数(事件){
    context.beginPath();
    context.moveTo(event.offsetX,event.offsetY);
    canvas.onmousemove=函数(事件){
    //请注意,由于未清除画布,
    //实际上,你在自己身上画了很多像素,
    //创建巨大的抗锯齿伪影。
    context.lineTo(event.offsetX,