使用 canvas 绘制时钟。查询关于 save()
Using canvas to draw a clock. Query about the save()
我知道 save() 和 restore() 的功能,它们保存和恢复当前 canvas 状态。但对这些还没有深刻的认识。当程序调用绘制时钟的函数时,在重新绘制之前已经清除了所有的canvas。为什么还应在此处添加 save() 。谁能解释一下?谢谢。
window.onload=function(){
var oCan=document.getElementById('clock');
var oCanPen=oCan.getContext('2d');
drawClock();
setInterval(function(){
drawClock();
},1000);
function drawClock(){
// oCanPen.save();
oCanPen.clearRect(0,0,oCan.width,oCan.height);
var time=new Date();
var second=time.getSeconds();
var minute=time.getMinutes();
var hour=time.getHours()+minute/60;
oCanPen.save();
oCanPen.beginPath();
oCanPen.arc(200,200,100,0,360*Math.PI/180,false);
oCanPen.closePath();
oCanPen.stroke();
oCanPen.beginPath();
for (var i = 0; i < 60; i++) {
oCanPen.moveTo(200,200);
oCanPen.arc(200,200,100,i*6*Math.PI/180,i*6*Math.PI/180,false);
}
oCanPen.closePath();
oCanPen.stroke();
oCanPen.beginPath();
oCanPen.fillStyle='#fff';
oCanPen.arc(200,200,90,0,360*Math.PI/180,false);
oCanPen.closePath();
oCanPen.fill();
oCanPen.beginPath();
for (var i = 0; i < 12; i++) {
oCanPen.moveTo(200,200);
oCanPen.arc(200,200,100,i*30*Math.PI/180,i*30*Math.PI/180,false);
}
oCanPen.closePath();
oCanPen.stroke();
oCanPen.beginPath();
oCanPen.fillStyle='#fff';
oCanPen.arc(200,200,80,0,360*Math.PI/180,false);
oCanPen.closePath();
oCanPen.fill();
oCanPen.beginPath();
oCanPen.strokeStyle='red';
var iSecond=(-90+second*6)*Math.PI/180;
oCanPen.moveTo(200,200);
oCanPen.arc(200,200,85,iSecond,iSecond,false);
oCanPen.closePath();
oCanPen.stroke();
oCanPen.beginPath();
oCanPen.lineWidth=4;
oCanPen.strokeStyle='blue';
var iMinute=(-90+minute*6)*Math.PI/180;
oCanPen.moveTo(200,200);
oCanPen.arc(200,200,60,iMinute,iMinute,false);
oCanPen.closePath();
oCanPen.stroke();
oCanPen.beginPath();
oCanPen.lineWidth=6;
var iHour=(-90+hour*30)*Math.PI/180;
oCanPen.strokeStyle='black';
oCanPen.moveTo(200,200);
oCanPen.arc(200,200,40,iHour,iHour,false);
oCanPen.closePath();
oCanPen.stroke();
oCanPen.restore();
}
};
body{
background: #333;
}
canvas{
background: #f2f2f2;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title></title>
</head>
<body>
<canvas id="clock" width="400" height="400"></canvas>
</body>
</html>
保存和恢复不受位图内容的影响 - 它们只是按照您所说的那样处理状态,或者"settings"例如颜色样式、线宽、当前字体等
当您清除 canvas 时,状态保持不变。反之亦然,恢复状态时不会影响 canvas.
上的任何现有内容
典型用法是,如果您有自己喜欢的状态,但需要临时更改转换、样式等内容。绘制,然后恢复,这样您就可以恢复到原来的状态,而无需重置这些值。
在您的情况下,您可以更改 lineWidth 和 strokeStyles,而不必担心这些。
另一方面,如果您能够跟踪所有更改的状态值,则可以避免 save/restore。这在很多情况下比 save/restore 快,因为后者保存完整状态,而不仅仅是样式和线宽。
在你的情况下,你可以简单地删除 save/restore 并使用这行新代码来避免它:
..
var hour=time.getHours()+minute/60;
oCanPen.lineWidth = 1;
oCanPen.beginPath();
..
window.onload=function(){
var oCan=document.getElementById('clock');
var oCanPen=oCan.getContext('2d');
drawClock();
setInterval(function(){
drawClock();
},1000);
function drawClock(){
// oCanPen.save();
oCanPen.clearRect(0,0,oCan.width,oCan.height);
var time=new Date();
var second=time.getSeconds();
var minute=time.getMinutes();
var hour=time.getHours()+minute/60;
oCanPen.lineWidth = 1;
oCanPen.beginPath();
oCanPen.arc(200,200,100,0,360*Math.PI/180,false);
oCanPen.closePath();
oCanPen.stroke();
oCanPen.beginPath();
for (var i = 0; i < 60; i++) {
oCanPen.moveTo(200,200);
oCanPen.arc(200,200,100,i*6*Math.PI/180,i*6*Math.PI/180,false);
}
oCanPen.closePath();
oCanPen.stroke();
oCanPen.beginPath();
oCanPen.fillStyle='#fff';
oCanPen.arc(200,200,90,0,360*Math.PI/180,false);
oCanPen.closePath();
oCanPen.fill();
oCanPen.beginPath();
for (var i = 0; i < 12; i++) {
oCanPen.moveTo(200,200);
oCanPen.arc(200,200,100,i*30*Math.PI/180,i*30*Math.PI/180,false);
}
oCanPen.closePath();
oCanPen.stroke();
oCanPen.beginPath();
oCanPen.fillStyle='#fff';
oCanPen.arc(200,200,80,0,360*Math.PI/180,false);
oCanPen.closePath();
oCanPen.fill();
oCanPen.beginPath();
oCanPen.strokeStyle='red';
var iSecond=(-90+second*6)*Math.PI/180;
oCanPen.moveTo(200,200);
oCanPen.arc(200,200,85,iSecond,iSecond,false);
oCanPen.closePath();
oCanPen.stroke();
oCanPen.beginPath();
oCanPen.lineWidth=4;
oCanPen.strokeStyle='blue';
var iMinute=(-90+minute*6)*Math.PI/180;
oCanPen.moveTo(200,200);
oCanPen.arc(200,200,60,iMinute,iMinute,false);
oCanPen.closePath();
oCanPen.stroke();
oCanPen.beginPath();
oCanPen.lineWidth=6;
var iHour=(-90+hour*30)*Math.PI/180;
oCanPen.strokeStyle='black';
oCanPen.moveTo(200,200);
oCanPen.arc(200,200,40,iHour,iHour,false);
oCanPen.closePath();
oCanPen.stroke();
}
};
body{
background: #333;
}
canvas{
background: #f2f2f2;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title></title>
</head>
<body>
<canvas id="clock" width="400" height="400"></canvas>
</body>
</html>
我知道 save() 和 restore() 的功能,它们保存和恢复当前 canvas 状态。但对这些还没有深刻的认识。当程序调用绘制时钟的函数时,在重新绘制之前已经清除了所有的canvas。为什么还应在此处添加 save() 。谁能解释一下?谢谢。
window.onload=function(){
var oCan=document.getElementById('clock');
var oCanPen=oCan.getContext('2d');
drawClock();
setInterval(function(){
drawClock();
},1000);
function drawClock(){
// oCanPen.save();
oCanPen.clearRect(0,0,oCan.width,oCan.height);
var time=new Date();
var second=time.getSeconds();
var minute=time.getMinutes();
var hour=time.getHours()+minute/60;
oCanPen.save();
oCanPen.beginPath();
oCanPen.arc(200,200,100,0,360*Math.PI/180,false);
oCanPen.closePath();
oCanPen.stroke();
oCanPen.beginPath();
for (var i = 0; i < 60; i++) {
oCanPen.moveTo(200,200);
oCanPen.arc(200,200,100,i*6*Math.PI/180,i*6*Math.PI/180,false);
}
oCanPen.closePath();
oCanPen.stroke();
oCanPen.beginPath();
oCanPen.fillStyle='#fff';
oCanPen.arc(200,200,90,0,360*Math.PI/180,false);
oCanPen.closePath();
oCanPen.fill();
oCanPen.beginPath();
for (var i = 0; i < 12; i++) {
oCanPen.moveTo(200,200);
oCanPen.arc(200,200,100,i*30*Math.PI/180,i*30*Math.PI/180,false);
}
oCanPen.closePath();
oCanPen.stroke();
oCanPen.beginPath();
oCanPen.fillStyle='#fff';
oCanPen.arc(200,200,80,0,360*Math.PI/180,false);
oCanPen.closePath();
oCanPen.fill();
oCanPen.beginPath();
oCanPen.strokeStyle='red';
var iSecond=(-90+second*6)*Math.PI/180;
oCanPen.moveTo(200,200);
oCanPen.arc(200,200,85,iSecond,iSecond,false);
oCanPen.closePath();
oCanPen.stroke();
oCanPen.beginPath();
oCanPen.lineWidth=4;
oCanPen.strokeStyle='blue';
var iMinute=(-90+minute*6)*Math.PI/180;
oCanPen.moveTo(200,200);
oCanPen.arc(200,200,60,iMinute,iMinute,false);
oCanPen.closePath();
oCanPen.stroke();
oCanPen.beginPath();
oCanPen.lineWidth=6;
var iHour=(-90+hour*30)*Math.PI/180;
oCanPen.strokeStyle='black';
oCanPen.moveTo(200,200);
oCanPen.arc(200,200,40,iHour,iHour,false);
oCanPen.closePath();
oCanPen.stroke();
oCanPen.restore();
}
};
body{
background: #333;
}
canvas{
background: #f2f2f2;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title></title>
</head>
<body>
<canvas id="clock" width="400" height="400"></canvas>
</body>
</html>
保存和恢复不受位图内容的影响 - 它们只是按照您所说的那样处理状态,或者"settings"例如颜色样式、线宽、当前字体等
当您清除 canvas 时,状态保持不变。反之亦然,恢复状态时不会影响 canvas.
上的任何现有内容典型用法是,如果您有自己喜欢的状态,但需要临时更改转换、样式等内容。绘制,然后恢复,这样您就可以恢复到原来的状态,而无需重置这些值。
在您的情况下,您可以更改 lineWidth 和 strokeStyles,而不必担心这些。
另一方面,如果您能够跟踪所有更改的状态值,则可以避免 save/restore。这在很多情况下比 save/restore 快,因为后者保存完整状态,而不仅仅是样式和线宽。
在你的情况下,你可以简单地删除 save/restore 并使用这行新代码来避免它:
..
var hour=time.getHours()+minute/60;
oCanPen.lineWidth = 1;
oCanPen.beginPath();
..
window.onload=function(){
var oCan=document.getElementById('clock');
var oCanPen=oCan.getContext('2d');
drawClock();
setInterval(function(){
drawClock();
},1000);
function drawClock(){
// oCanPen.save();
oCanPen.clearRect(0,0,oCan.width,oCan.height);
var time=new Date();
var second=time.getSeconds();
var minute=time.getMinutes();
var hour=time.getHours()+minute/60;
oCanPen.lineWidth = 1;
oCanPen.beginPath();
oCanPen.arc(200,200,100,0,360*Math.PI/180,false);
oCanPen.closePath();
oCanPen.stroke();
oCanPen.beginPath();
for (var i = 0; i < 60; i++) {
oCanPen.moveTo(200,200);
oCanPen.arc(200,200,100,i*6*Math.PI/180,i*6*Math.PI/180,false);
}
oCanPen.closePath();
oCanPen.stroke();
oCanPen.beginPath();
oCanPen.fillStyle='#fff';
oCanPen.arc(200,200,90,0,360*Math.PI/180,false);
oCanPen.closePath();
oCanPen.fill();
oCanPen.beginPath();
for (var i = 0; i < 12; i++) {
oCanPen.moveTo(200,200);
oCanPen.arc(200,200,100,i*30*Math.PI/180,i*30*Math.PI/180,false);
}
oCanPen.closePath();
oCanPen.stroke();
oCanPen.beginPath();
oCanPen.fillStyle='#fff';
oCanPen.arc(200,200,80,0,360*Math.PI/180,false);
oCanPen.closePath();
oCanPen.fill();
oCanPen.beginPath();
oCanPen.strokeStyle='red';
var iSecond=(-90+second*6)*Math.PI/180;
oCanPen.moveTo(200,200);
oCanPen.arc(200,200,85,iSecond,iSecond,false);
oCanPen.closePath();
oCanPen.stroke();
oCanPen.beginPath();
oCanPen.lineWidth=4;
oCanPen.strokeStyle='blue';
var iMinute=(-90+minute*6)*Math.PI/180;
oCanPen.moveTo(200,200);
oCanPen.arc(200,200,60,iMinute,iMinute,false);
oCanPen.closePath();
oCanPen.stroke();
oCanPen.beginPath();
oCanPen.lineWidth=6;
var iHour=(-90+hour*30)*Math.PI/180;
oCanPen.strokeStyle='black';
oCanPen.moveTo(200,200);
oCanPen.arc(200,200,40,iHour,iHour,false);
oCanPen.closePath();
oCanPen.stroke();
}
};
body{
background: #333;
}
canvas{
background: #f2f2f2;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title></title>
</head>
<body>
<canvas id="clock" width="400" height="400"></canvas>
</body>
</html>