将物体放在另外两个之间
Place object between another two
我是 canvas 的新手,我想将我的 DOM (HTML+JS) 动画移动到 canvas。我试图在 Basic animations - Web API Interfaces | MDN and I managed to do it. Fiddle.
中模仿太阳系动画
我对 globalCompositeOperation
有疑问。在动画中,地球正在投射阴影(低不透明度矩形),而当月亮围绕这个黑暗区域运行时,月亮应该在阴影矩形下方。如果我使用
context.globalCompositeOperation = 'destination-over';
在 draw
函数的顶部,我得到了预期的结果 (fiddle),但随后月球和地球在轨道线下方旋转。我不想要那个。我希望地球和月球都在轨道线上方,而月球在阴影矩形下方。有没有办法做到这一点?如果没有,我将不得不摆脱阴影。
我没有在我的代码中使用 context.save()
和 context.restore()
,尽管它们在原始动画中使用过。我对他们不熟悉。可能跟我的问题有关...
var sun = {
radius : 80,
x : 0,
y : 0,
};
var earth = {
radius : 20,
x : sun.radius + 80,
y : 0,
angle : 0,
};
var moon = {
radius : 8,
x : 50,
y : 0,
angle : 0,
};
function draw() {
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
context.resetTransform();
context.clearRect(0, 0, canvas.width, canvas.height)
context.translate(canvas.width/2, canvas.height/2);
// sun
context.beginPath();
context.arc(0, 0, sun.radius, 0, 360 * Math.PI/180, false);
context.fillStyle = "yellow";
context.fill();
// sun orbit
context.beginPath();
context.arc(0, 0, earth.x, 0, Math.PI*2, false);
context.strokeStyle = "rgba(180,150,0,.25)";
context.stroke();
// earth
earth.angle += .2;
if (earth.angle == 360) {
earth.angle = 0;
}
context.globalCompositeOperation = 'source-over'; // earth is above the sun and its orbit
context.rotate(earth.angle * Math.PI/180);
context.translate(earth.x, 0);
context.beginPath();
context.arc(0, 0, earth.radius, 0, 360*(Math.PI/180), false);
context.fillStyle = "royalblue";
context.fill();
context.globalCompositeOperation = 'destination-over'; // earth's orbit and shadow are below the earth
// earth shadow
context.fillStyle = "rgba(0,0,0,0.1)";
context.fillRect(0, -earth.radius, earth.radius*16, earth.radius*2);
// earth orbit
context.beginPath();
context.arc(0, 0, moon.x, 0, Math.PI*2, false);
context.strokeStyle = "rgba(0,0,200,.2)";
context.stroke();
// moon
moon.angle += 1;
if (moon.angle == 360) {
moon.angle = 0;
}
context.globalCompositeOperation = 'source-over'; // moon is above the earth's orbit and shadow
context.rotate(moon.angle * Math.PI/180);
context.translate(moon.x, 0);
context.beginPath();
context.arc(0, 0, moon.radius, 0, 360 * Math.PI/180, false);
context.fillStyle = "silver";
context.fill();
requestAnimationFrame(draw);
}
draw();
html {
background: rgb(230,230,230);
}
canvas {
background: white;
border: 1px solid rgba(0,0,0,.2);
box-shadow: 0 0 5px rgba(0,0,0,.1);
}
<canvas id="canvas" width="640" height="480"></canvas>
您只需要稍微更改一下代码中的顺序 - 在这种情况下确实不需要复合模式:
- 所有静态元素,如太阳和地球轨道,都可以渲染一次并设置为元素的背景。
- 先画出月球轨道
- 画月亮秒
- 第三次画阴影
- 终于画出地球了。
在这次更新中我没有重新计算旋转等,而是使用了save/restore。
var sun = {
radius : 80,
x : 0,
y : 0,
};
var earth = {
radius : 20,
x : sun.radius + 80,
y : 0,
angle : 0,
};
var moon = {
radius : 8,
x : 50,
y : 0,
angle : 0,
};
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
context.setTransform(1,0,0,1,canvas.width/2, canvas.height/2);
// sun
context.beginPath();
context.arc(0, 0, sun.radius, 0, 360 * Math.PI/180, false);
context.fillStyle = "yellow";
context.fill();
// sun orbit
context.beginPath();
context.arc(0, 0, earth.x, 0, Math.PI*2, false);
context.strokeStyle = "rgba(180,150,0,.25)";
context.stroke();
canvas.style.backgroundImage = "url(" + canvas.toDataURL() + ")";
function draw() {
context.setTransform(1,0,0,1,0,0);
context.clearRect(0, 0, canvas.width, canvas.height)
context.setTransform(1,0,0,1,canvas.width/2, canvas.height/2);
// earth
earth.angle += .2;
if (earth.angle == 360) {
earth.angle = 0;
}
context.rotate(earth.angle * Math.PI/180);
context.translate(earth.x, 0);
// earth orbit
context.beginPath();
context.arc(0, 0, moon.x, 0, Math.PI*2, false);
context.strokeStyle = "rgba(0,0,200,.2)";
context.stroke();
// moon
context.save();
moon.angle += 1;
if (moon.angle == 360) {
moon.angle = 0;
}
context.rotate(moon.angle * Math.PI/180);
context.translate(moon.x, 0);
context.beginPath();
context.arc(0, 0, moon.radius, 0, 360 * Math.PI/180, false);
context.fillStyle = "silver";
context.fill();
context.restore();
// earth shadow
context.fillStyle = "rgba(0,0,0,0.1)";
context.fillRect(0, -earth.radius, earth.radius*16, earth.radius*2);
context.beginPath();
context.arc(0, 0, earth.radius, 0, 360*(Math.PI/180), false);
context.fillStyle = "royalblue";
context.fill();
requestAnimationFrame(draw);
}
draw();
html {
background: rgb(230,230,230);
}
canvas {
background: white;
border: 1px solid rgba(0,0,0,.2);
box-shadow: 0 0 5px rgba(0,0,0,.1);
}
<canvas id="canvas" width="640" height="480"></canvas>
我是 canvas 的新手,我想将我的 DOM (HTML+JS) 动画移动到 canvas。我试图在 Basic animations - Web API Interfaces | MDN and I managed to do it. Fiddle.
中模仿太阳系动画我对 globalCompositeOperation
有疑问。在动画中,地球正在投射阴影(低不透明度矩形),而当月亮围绕这个黑暗区域运行时,月亮应该在阴影矩形下方。如果我使用
context.globalCompositeOperation = 'destination-over';
在 draw
函数的顶部,我得到了预期的结果 (fiddle),但随后月球和地球在轨道线下方旋转。我不想要那个。我希望地球和月球都在轨道线上方,而月球在阴影矩形下方。有没有办法做到这一点?如果没有,我将不得不摆脱阴影。
我没有在我的代码中使用 context.save()
和 context.restore()
,尽管它们在原始动画中使用过。我对他们不熟悉。可能跟我的问题有关...
var sun = {
radius : 80,
x : 0,
y : 0,
};
var earth = {
radius : 20,
x : sun.radius + 80,
y : 0,
angle : 0,
};
var moon = {
radius : 8,
x : 50,
y : 0,
angle : 0,
};
function draw() {
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
context.resetTransform();
context.clearRect(0, 0, canvas.width, canvas.height)
context.translate(canvas.width/2, canvas.height/2);
// sun
context.beginPath();
context.arc(0, 0, sun.radius, 0, 360 * Math.PI/180, false);
context.fillStyle = "yellow";
context.fill();
// sun orbit
context.beginPath();
context.arc(0, 0, earth.x, 0, Math.PI*2, false);
context.strokeStyle = "rgba(180,150,0,.25)";
context.stroke();
// earth
earth.angle += .2;
if (earth.angle == 360) {
earth.angle = 0;
}
context.globalCompositeOperation = 'source-over'; // earth is above the sun and its orbit
context.rotate(earth.angle * Math.PI/180);
context.translate(earth.x, 0);
context.beginPath();
context.arc(0, 0, earth.radius, 0, 360*(Math.PI/180), false);
context.fillStyle = "royalblue";
context.fill();
context.globalCompositeOperation = 'destination-over'; // earth's orbit and shadow are below the earth
// earth shadow
context.fillStyle = "rgba(0,0,0,0.1)";
context.fillRect(0, -earth.radius, earth.radius*16, earth.radius*2);
// earth orbit
context.beginPath();
context.arc(0, 0, moon.x, 0, Math.PI*2, false);
context.strokeStyle = "rgba(0,0,200,.2)";
context.stroke();
// moon
moon.angle += 1;
if (moon.angle == 360) {
moon.angle = 0;
}
context.globalCompositeOperation = 'source-over'; // moon is above the earth's orbit and shadow
context.rotate(moon.angle * Math.PI/180);
context.translate(moon.x, 0);
context.beginPath();
context.arc(0, 0, moon.radius, 0, 360 * Math.PI/180, false);
context.fillStyle = "silver";
context.fill();
requestAnimationFrame(draw);
}
draw();
html {
background: rgb(230,230,230);
}
canvas {
background: white;
border: 1px solid rgba(0,0,0,.2);
box-shadow: 0 0 5px rgba(0,0,0,.1);
}
<canvas id="canvas" width="640" height="480"></canvas>
您只需要稍微更改一下代码中的顺序 - 在这种情况下确实不需要复合模式:
- 所有静态元素,如太阳和地球轨道,都可以渲染一次并设置为元素的背景。
- 先画出月球轨道
- 画月亮秒
- 第三次画阴影
- 终于画出地球了。
在这次更新中我没有重新计算旋转等,而是使用了save/restore。
var sun = {
radius : 80,
x : 0,
y : 0,
};
var earth = {
radius : 20,
x : sun.radius + 80,
y : 0,
angle : 0,
};
var moon = {
radius : 8,
x : 50,
y : 0,
angle : 0,
};
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
context.setTransform(1,0,0,1,canvas.width/2, canvas.height/2);
// sun
context.beginPath();
context.arc(0, 0, sun.radius, 0, 360 * Math.PI/180, false);
context.fillStyle = "yellow";
context.fill();
// sun orbit
context.beginPath();
context.arc(0, 0, earth.x, 0, Math.PI*2, false);
context.strokeStyle = "rgba(180,150,0,.25)";
context.stroke();
canvas.style.backgroundImage = "url(" + canvas.toDataURL() + ")";
function draw() {
context.setTransform(1,0,0,1,0,0);
context.clearRect(0, 0, canvas.width, canvas.height)
context.setTransform(1,0,0,1,canvas.width/2, canvas.height/2);
// earth
earth.angle += .2;
if (earth.angle == 360) {
earth.angle = 0;
}
context.rotate(earth.angle * Math.PI/180);
context.translate(earth.x, 0);
// earth orbit
context.beginPath();
context.arc(0, 0, moon.x, 0, Math.PI*2, false);
context.strokeStyle = "rgba(0,0,200,.2)";
context.stroke();
// moon
context.save();
moon.angle += 1;
if (moon.angle == 360) {
moon.angle = 0;
}
context.rotate(moon.angle * Math.PI/180);
context.translate(moon.x, 0);
context.beginPath();
context.arc(0, 0, moon.radius, 0, 360 * Math.PI/180, false);
context.fillStyle = "silver";
context.fill();
context.restore();
// earth shadow
context.fillStyle = "rgba(0,0,0,0.1)";
context.fillRect(0, -earth.radius, earth.radius*16, earth.radius*2);
context.beginPath();
context.arc(0, 0, earth.radius, 0, 360*(Math.PI/180), false);
context.fillStyle = "royalblue";
context.fill();
requestAnimationFrame(draw);
}
draw();
html {
background: rgb(230,230,230);
}
canvas {
background: white;
border: 1px solid rgba(0,0,0,.2);
box-shadow: 0 0 5px rgba(0,0,0,.1);
}
<canvas id="canvas" width="640" height="480"></canvas>