You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

154 lines
3.4 KiB

2 years ago
<html>
<head>
<meta charset="utf8">
<title>moon orbit</title>
<link href="../examples/resources/threejs-tutorials.css" rel="stylesheet" />
<style>
body {
margin: 0px;
background: white;
}
canvas {
width: 100%;
height: 100%;
display: block;
}
p {
position: relative;
}
#c {
position: absolute;
left: 0px;
top: 0px;
z-index: 2;
background-color: transparent;
}
@media (prefers-color-scheme: dark) {
canvas {
background: #444;
}
}
</style>
</head>
<body>
<p><canvas id="orbit"></canvas>
<canvas id="c"></canvas></p>
</body>
<script src="../examples/resources/lessons-helper.js"></script>
<script src="../examples/resources/threejs-utils.js"></script>
<script src="canvas-wrapper.js"></script>
<script>
'use strict'; // eslint-disable-line
/* global wrapCanvasRenderingContext2D, threejsUtils */
function main() {
const root = {
name: 'sun',
translation: [0, 0],
color: 'yellow',
radius: 30,
speed: 1,
children: [
{
name: 'earth',
translation: [-5, 1],
color: 'blue',
radius: 10,
speed: 2,
children: [
{
name: 'moon',
translation: [-1, 1],
color: 'gray',
drawOrbit: true,
radius: 5,
speed: 36.13,
children: [
],
},
],
},
],
};
const canvas = document.getElementById('c');
const ctx = wrapCanvasRenderingContext2D(canvas.getContext('2d'));
const orbitCtx = document.getElementById('orbit').getContext('2d');
const spread = 16;
function updateTranslation(node) {
node.translation[0] *= spread;
node.translation[1] *= spread;
node.rotation = 0;
node.children.forEach(updateTranslation);
}
updateTranslation(root);
let clock = 0;
const maxHistory = 400;
let curHistory = 0;
const history = [];
function drawTrail(ctx, pos, radius) {
ctx.beginPath();
ctx.arc(pos[0], pos[1], radius, 0, Math.PI * 2, false);
ctx.fill();
}
function drawNode(node) {
ctx.save();
ctx.rotate(node.speed * clock);
ctx.translate(node.translation[0], node.translation[1]);
ctx.fillStyle = node.color;
ctx.strokeStyle = 'black';
ctx.beginPath();
ctx.arc(0, 0, node.radius, 0, Math.PI * 2, false);
ctx.fill();
ctx.stroke();
if (node.drawOrbit) {
const mat = ctx.currentTransform;
const point = [mat.e, mat.f];
const old = history[curHistory];
if (old) {
orbitCtx.save();
orbitCtx.globalCompositeOperation = 'destination-out';
orbitCtx.fillStyle = 'rgba(255,255,255,1)';
drawTrail(orbitCtx, old, 2);
orbitCtx.restore();
}
history[curHistory] = point;
curHistory = (curHistory + 1) % maxHistory;
orbitCtx.fillStyle = 'rgba(255, 0, 0, 1)';
drawTrail(orbitCtx, point, 1);
}
node.children.forEach(drawNode);
ctx.restore();
}
function drawScene() {
threejsUtils.resizeCanvasToDisplaySize(ctx.canvas);
threejsUtils.resizeCanvasToDisplaySize(orbitCtx.canvas);
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
ctx.save();
ctx.translate(ctx.canvas.width / 2, ctx.canvas.height / 2);
drawNode(root);
ctx.restore();
}
function render() {
clock += 1 / 60 * 0.25;
drawScene();
requestAnimationFrame(render, canvas);
}
requestAnimationFrame(render, canvas);
}
main();
</script>
</html>