下面是我制作模拟时钟的初步Javascript代码。我的主要问题是我不知道如何清除时钟表面上的“先前的第二行”:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<script>
setInterval(timing, 1000);
var canvas1 = document.createElement("canvas");
canvas1.id = "canvas-1";
document.body.appendChild(canvas1);
canvas1.width = 500;
canvas1.height = 500;
canvas1.style.backgroundColor = "#3d3d3b";
var radius = (canvas1.height/2) * 0.9;
var ctx = canvas1.getContext("2d");
ctx.beginPath();
ctx.arc(250,250,radius,0,2*Math.PI);
ctx.fillStyle = "white";
ctx.fill();
ctx.beginPath();
ctx.arc(250, 250, radius * 0.1, 0, 2 * Math.PI);
ctx.fillStyle = '#333';
ctx.fill();
ctx.beginPath();
ctx.lineWidth = radius * 0.05;
ctx.stroke();
ctx.font = "40px Georgia"
ctx.textBaseline="middle";
ctx.textAlign="center";
for (i=1;i<13;i++){
ctx.fillText(i.toString(), 250+(Math.sin(i*Math.PI/6)*radius*0.8), 250-Math.cos(i*Math.PI/6)*radius*0.8);
}
function timing(){
const d = new Date();
ctx.beginPath();
ctx.moveTo(250,250);
ctx.lineWidth = radius*0.01;
ctx.lineTo(250+(Math.sin(d.getSeconds()*Math.PI/30)*radius*0.85), 250-Math.cos(d.getSeconds()*Math.PI/30)*radius*0.85);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(250,250);
ctx.lineWidth = radius*0.03;
ctx.lineTo(250+(Math.sin(d.getMinutes()*Math.PI/30)*radius*0.78), 250-Math.cos(d.getMinutes()*Math.PI/30)*radius*0.78);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(250,250);
ctx.lineWidth = radius*0.05;
ctx.lineTo(250+(Math.sin(d.getHours()*Math.PI/6)*radius*0.7), 250-Math.cos(d.getHours()*Math.PI/6)*radius*0.7);
ctx.stroke();
}
</script>
</body>
</html>
我试过使用"ctx.globalCompositeOperation =“目的-over”;“但是没有成功:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<script>
setInterval(timing, 1000);
var canvas1 = document.createElement("canvas");
canvas1.id = "canvas-1";
document.body.appendChild(canvas1);
canvas1.width = 500;
canvas1.height = 500;
canvas1.style.backgroundColor = "#3d3d3b";
var radius = (canvas1.height/2) * 0.9;
var ctx = canvas1.getContext("2d");
ctx.beginPath();
ctx.arc(250,250,radius,0,2*Math.PI);
ctx.fillStyle = "white";
ctx.fill();
ctx.beginPath();
ctx.arc(250, 250, radius * 0.1, 0, 2 * Math.PI);
ctx.fillStyle = '#333';
ctx.fill();
ctx.beginPath();
ctx.lineWidth = radius * 0.05;
ctx.stroke();
ctx.font = "40px Georgia"
ctx.textBaseline="middle";
ctx.textAlign="center";
for (i=1;i<13;i++){
ctx.fillText(i.toString(), 250+(Math.sin(i*Math.PI/6)*radius*0.8), 250-Math.cos(i*Math.PI/6)*radius*0.8);
}
function timing(){
const d = new Date();
ctx.beginPath();
ctx.arc(250,250,radius,0,2*Math.PI);
ctx.fillStyle = "white";
ctx.fill();
ctx.globalCompositeOperation = "destination-over";
ctx.beginPath();
ctx.moveTo(250,250);
ctx.lineTo(250+(Math.sin((d.getSeconds()-1)*Math.PI/30)*radius*0.85), 250-Math.cos((d.getSeconds()-1)*Math.PI/30)*radius*0.85);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(250,250);
ctx.lineWidth = radius*0.01;
ctx.lineTo(250+(Math.sin(d.getSeconds()*Math.PI/30)*radius*0.85), 250-Math.cos(d.getSeconds()*Math.PI/30)*radius*0.85);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(250,250);
ctx.lineWidth = radius*0.03;
ctx.lineTo(250+(Math.sin(d.getMinutes()*Math.PI/30)*radius*0.78), 250-Math.cos(d.getMinutes()*Math.PI/30)*radius*0.78);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(250,250);
ctx.lineWidth = radius*0.05;
ctx.lineTo(250+(Math.sin(d.getHours()*Math.PI/6)*radius*0.7), 250-Math.cos(d.getHours()*Math.PI/6)*radius*0.7);
ctx.stroke();
}
</script>
</body>
</html>
你能告诉我如何使用globalCompositeOperation清除这些“先前的第二行”,如果这个函数在我的情况下真的可以做到的话?谢谢。
我之所以相信可以通过globalCompositeOperation进行测试,是因为我已经尝试了如下一些测试:
<html>
<body>
<canvas id="myCanvas" width="300" height="150" style="border:1px solid #d3d3d3;">
</canvas>
<button onclick="myFunction()">Click me</button>
<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
ctx.beginPath();
ctx.arc(50, 50, 50, 0, 2*Math.PI);
ctx.fillStyle = 'red';
ctx.fill();
ctx.beginPath();
ctx.moveTo(50,50);
ctx.lineTo(90,90);
ctx.stroke();
function myFunction() {
ctx.beginPath();
ctx.arc(50, 50, 50, 0, 2*Math.PI);
ctx.fillStyle = 'red';
ctx.fill();
ctx.globalCompositeOperation = "destination-over";
ctx.beginPath();
ctx.moveTo(50,50);
ctx.lineTo(90,90);
ctx.stroke();}
</script>
</body>
</html>
发布于 2022-08-25 12:15:09
globalCompositeOperation属性不能真正用于此目的。
但是,您可以这样做:
position: absolute)。它是透明的,所以另一个画布将通过它看到。ctx)切换到第二个画布,以便timing函数只处理覆盖的画布。timing函数中,从清除覆盖画布开始
setInterval(timing, 1000);
// Create second canvas that will overlay the first
var canvas2 = document.createElement("canvas");
canvas2.width = 500;
canvas2.height = 500;
canvas2.style.position = "absolute";
document.body.appendChild(canvas2);
var canvas1 = document.createElement("canvas");
canvas1.id = "canvas-1";
document.body.appendChild(canvas1);
canvas1.width = 500;
canvas1.height = 500;
canvas1.style.backgroundColor = "#3d3d3b";
var radius = (canvas1.height/2) * 0.9;
var ctx = canvas1.getContext("2d");
ctx.beginPath();
ctx.arc(250,250,radius,0,2*Math.PI);
ctx.fillStyle = "white";
ctx.fill();
ctx.beginPath();
ctx.arc(250, 250, radius * 0.1, 0, 2 * Math.PI);
ctx.fillStyle = '#333';
ctx.fill();
ctx.beginPath();
ctx.lineWidth = radius * 0.05;
ctx.stroke();
ctx.font = "40px Georgia"
ctx.textBaseline="middle";
ctx.textAlign="center";
for (i=1;i<13;i++){
ctx.fillText(i.toString(), 250+(Math.sin(i*Math.PI/6)*radius*0.8), 250-Math.cos(i*Math.PI/6)*radius*0.8);
}
// Switch the context to the overlayed canvas
ctx = canvas2.getContext("2d");
function timing(){
// Clear the second canvas (only)
ctx.clearRect(0, 0, 500, 500);
const d = new Date();
ctx.beginPath();
ctx.moveTo(250,250);
ctx.lineWidth = radius*0.01;
ctx.lineTo(250+(Math.sin(d.getSeconds()*Math.PI/30)*radius*0.85), 250-Math.cos(d.getSeconds()*Math.PI/30)*radius*0.85);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(250,250);
ctx.lineWidth = radius*0.03;
ctx.lineTo(250+(Math.sin(d.getMinutes()*Math.PI/30)*radius*0.78), 250-Math.cos(d.getMinutes()*Math.PI/30)*radius*0.78);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(250,250);
ctx.lineWidth = radius*0.05;
ctx.lineTo(250+(Math.sin(d.getHours()*Math.PI/6)*radius*0.7), 250-Math.cos(d.getHours()*Math.PI/6)*radius*0.7);
ctx.stroke();
}
发布于 2022-08-25 07:16:22
在这里重绘背景的典型例子,不错的小程序:)
setInterval(timing, 1000);
var canvas1 = document.createElement("canvas");
canvas1.id = "canvas-1";
document.body.appendChild(canvas1);
var radius = (canvas1.height/2) * 0.9;
var ctx = canvas1.getContext("2d");
function timing(){
canvas1.width = 500;
canvas1.height = 500;
canvas1.style.backgroundColor = "#3d3d3b";
ctx.beginPath();
ctx.arc(250,250,radius,0,2*Math.PI);
ctx.fillStyle = "white";
ctx.fill();
ctx.beginPath();
ctx.arc(250, 250, radius * 0.1, 0, 2 * Math.PI);
ctx.fillStyle = '#333';
ctx.fill();
ctx.beginPath();
ctx.lineWidth = radius * 0.05;
ctx.stroke();
ctx.font = "40px Georgia"
ctx.textBaseline="middle";
ctx.textAlign="center";
for (i=1;i<13;i++){
ctx.fillText(i.toString(), 250+(Math.sin(i*Math.PI/6)*radius*0.8), 250-Math.cos(i*Math.PI/6)*radius*0.8);
}
const d = new Date();
ctx.beginPath();
ctx.moveTo(250,250);
ctx.lineWidth = radius*0.01;
ctx.lineTo(250+(Math.sin(d.getSeconds()*Math.PI/30)*radius*0.85), 250-Math.cos(d.getSeconds()*Math.PI/30)*radius*0.85);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(250,250);
ctx.lineWidth = radius*0.03;
ctx.lineTo(250+(Math.sin(d.getMinutes()*Math.PI/30)*radius*0.78), 250-Math.cos(d.getMinutes()*Math.PI/30)*radius*0.78);
ctx.stroke();
ctx.beginPath();
ctx.moveTo(250,250);
ctx.lineWidth = radius*0.05;
ctx.lineTo(250+(Math.sin(d.getHours()*Math.PI/6)*radius*0.7), 250-Math.cos(d.getHours()*Math.PI/6)*radius*0.7);
ctx.stroke();
}//timing
我刚重读了你的帖子,你问了关于globalCompositeOperation的事
如果您真的不想重新绘制背景,并使用globalCompositeOperation,
globalCompositeOperation似乎只在充满的区域运行(不包括线路)
你必须为每一只手存储你的画坐标,在旧位置重画每一只手--移除它,然后计算出新的绘制坐标,绘制和保存。
但是看看这个
var canvas = document.createElement("canvas");
document.body.appendChild(canvas);
canvas.width=500;
canvas.height=500;
var ctx = canvas.getContext("2d");
ctx.globalCompositeOperation = 'xor';
ctx.beginPath();
ctx.moveTo(50,50);
ctx.lineWidth = 1;
ctx.lineTo(250,250);
ctx.strokeStyle = '#ff0000'
ctx.stroke();
ctx.beginPath();
ctx.moveTo(50,250);
ctx.lineWidth = 1;
ctx.lineTo(250,50);
ctx.strokeStyle = '#ff0000'
ctx.stroke();
ctx.fillStyle='blue';
ctx.fillRect(20,20,60,60);
似乎表明它不适合你的时钟手
发布于 2022-08-25 07:26:37
你可能应该重新绘制每一个新的日期,你的时钟面。我把它分解成不同的部分,并使用承诺,但肯定这些都不是绝对必要的。
(() => {
let cnvs;
let ctxt;
let radius;
const buildcanvas = () => new Promise((resolve, reject) => {
cnvs = document.createElement("canvas");
cnvs.id = "canvas-1";
cnvs.width = 500;
cnvs.height = 500;
cnvs.style.backgroundColor = "#3d3d3b";
document.body.appendChild(cnvs);
resolve(true)
});
const buildclockface = () => new Promise((resolve, reject) => {
radius = (cnvs.height / 2) * 0.9;
ctxt = cnvs.getContext("2d");
ctxt.beginPath();
ctxt.arc(250, 250, radius, 0, 2 * Math.PI);
ctxt.fillStyle = "white";
ctxt.fill();
ctxt.beginPath();
ctxt.arc(250, 250, radius * 0.1, 0, 2 * Math.PI);
ctxt.fillStyle = '#333';
ctxt.fill();
ctxt.beginPath();
ctxt.lineWidth = radius * 0.05;
ctxt.stroke();
ctxt.font = "40px Georgia"
ctxt.textBaseline = "middle";
ctxt.textAlign = "center";
for (i = 1; i < 13; i++) {
ctxt.fillText(
i.toString(),
250 + (Math.sin(i * Math.PI / 6) * radius * 0.8),
250 - (Math.cos(i * Math.PI / 6) * radius * 0.8)
);
}
resolve(true)
});
const showtime = (d) => new Promise((resolve, reject) => {
let d = new Date();
buildclockface();
secondhand(d);
minutehand(d);
hourhand(d);
});
const secondhand = (d) => {
ctxt.beginPath();
ctxt.moveTo(250, 250);
ctxt.lineWidth = radius * 0.01;
ctxt.lineTo(250 + (Math.sin(d.getSeconds() * Math.PI / 30) * radius * 0.85), 250 - Math.cos(d.getSeconds() * Math.PI / 30) * radius * 0.85);
ctxt.stroke();
}
const minutehand = (d) => {
ctxt.beginPath();
ctxt.moveTo(250, 250);
ctxt.lineWidth = radius * 0.03;
ctxt.lineTo(250 + (Math.sin(d.getMinutes() * Math.PI / 30) * radius * 0.78), 250 - Math.cos(d.getMinutes() * Math.PI / 30) * radius * 0.78);
ctxt.stroke();
}
const hourhand = (d) => {
ctxt.beginPath();
ctxt.moveTo(250, 250);
ctxt.lineWidth = radius * 0.05;
ctxt.lineTo(250 + (Math.sin(d.getHours() * Math.PI / 6) * radius * 0.7), 250 - Math.cos(d.getHours() * Math.PI / 6) * radius * 0.7);
ctxt.stroke();
}
buildcanvas()
.then(bool => setInterval(showtime, 1000))
.catch(err => alert(err))
})();
https://stackoverflow.com/questions/73483028
复制相似问题