围绕一个圆圈移动阴影

Moving a shadow around a circle

我有一个每 10 秒绕一圈的圆。我正在尝试投射一个与轨道原点(光源)成一定角度的阴影,同时也考虑到相机角度。

阴影适用于某些角度,但随着相机的边缘越来越多或自上而下,它开始看起来不太准确,我不知道如何纠正它 - 这似乎是一个复杂的数学问题,我正在努力想办法解决。

这是动画:http://jsfiddle.net/8y2bm88w/

我的阴影绘制代码:

ctx.beginPath();

//rotate shadow with the planet
ctx.translate(originX + obj[i].x, originY + obj[i].y);
ctx.rotate(obj[i].angle); //rotate around origin
ctx.translate(-(originX + obj[i].x), -(originY + obj[i].y));


var offsetX = -(10 * Math.sin(obj[0].angle)); //i feel this is the issue
var offsetY = 0; //this too

ctx.rect(originX + obj[i].x + offsetX, originY + obj[i].y + offsetY - 10, 20, 20);
ctx.fillStyle = 'rgba(213,0,0,0.9)'; //red shadow - easier to see
ctx.fill();

代码通过 JSFiddle 更有意义,因为它将代码置于更多上下文中。

所以我认为这与 offsetXoffsetY 变量的数学运算有关,因为用户改变相机角度时偏移量需要适应和改变阴影移动的方式.但是,这真是令人困惑如何解决。

你打这个是因为你的obj[i].angle是基于椭圆坐标而不是x-y坐标自上而下的视图(这实际上是您从中生成其他所有内容的视图,因此我们不需要为其进行计算)。

您将需要两个角度,因此我为另一个角度添加了第二个 属性。上下文的旋转需要椭圆角,因此您可以从原点垂直于矢量。新角度用于计算。您可以将其视为非 2D 映射版本。

obj[i].trueAngle = angle;

现在我们有了可以使用的值,我建议为 "dark side" 绘制一个半圆,然后根据需要使用您选择的曲线添加或剪切该区域以完成阴影, 例如

// centre on planet
ctx.translate(originX + obj[i].x, originY + obj[i].y);
ctx.rotate(obj[i].angle - Math.PI / 2);
// semicircle dark side
ctx.arc(0, 0, 12, 0, Math.PI, false);
// path along terminator
var offset_terminator = -20 * Math.sin(obj[0].trueAngle) * (1 - camera.angle);
ctx.bezierCurveTo(-7, offset_terminator, 7, offset_terminator, 12, 0);
//fill
ctx.fillStyle = 'rgba(213,0,0,0.9)'; //red shadow - easier to see
ctx.fill();

这里我也把阴影做的比星球大了几个px,我只是玩弄数字,直到找到一些看起来不错的数字。

请注意,我设置了旋转,因此 0, 0 是行星的中心,x 轴 沿着终止符

移动

DEMO