我尝试在我移动它们时围绕2个圆圈生成一条路径。我基于一个例子,我发现并构建了一个我期望实现的原型example
我已经开始在我的应用程序中包含这个内容,但出于某种原因,我似乎无法找到绕过正确位置的绿色路径,而我无法弄清楚原因。< / p>
我已经整理了一个代码示例来说明:
function generatePath(planet, moon, join) {
function distanceBetween(x1, y1, x2, y2) {
var a = (x2 - x1) * (x2 - x1);
var b = (y2 - y1) * (y2 - y1);
return Math.sqrt(a + b);
};
function circleYFromX(circle, x) {
return Math.sqrt(Math.pow(circle.r, 2) - Math.pow(x - circle.x, 2));
};
function calculateAngle(origin, point) {
var tan = (point.y - origin.y) / (point.x - origin.x);
var angle = Math.atan(tan) / Math.PI * 180 + 90;
if (point.x < origin.x) angle += 180;
return angle;
};
// Work out the distance between the moon and planet
var distance = distanceBetween(planet.x, planet.y, moon.x, moon.y);
var originDistance = planet.r - moon.r;
var distanceDiff = distance - originDistance;
if (distanceDiff < 1) {
distanceDiff = 1;
}
console.log(distance);
console.log(planet.r);
console.log(moon.r);
console.log(join.r);
console.log(planet.r + moon.r + 2 * join.r);
// Determine if the moon has moved out of the planet's gravitational pull
if (distance > 2 * join.r + planet.r + moon.r) {
return;
}
moon.h = 0;
moon.k = 0 - planet.r + moon.r - distanceDiff;
var triangleA = planet.r + join.r; // Side planet
var triangleB = moon.r + join.r; // Side moon
var triangleC = Math.abs(moon.k - 0); // Side c
var triangleP = (triangleA + triangleB + triangleC) / 2; // Triangle half perimeter
var triangleArea = Math.sqrt(triangleP * (triangleP - triangleA) * (triangleP - triangleB) * (triangleP - triangleC)); // Triangle area
var triangleH;
var triangleD;
if (triangleC >= triangleA) {
var triangleH = 2 * triangleArea / triangleC; // Triangle height
var triangleD = Math.sqrt(Math.pow(triangleA, 2) - Math.pow(triangleH, 2)); // Big circle bisection of triangleC
} else {
var triangleH = 2 * triangleArea / triangleA; // Triangle height
var triangleD = Math.sqrt(Math.pow(triangleC, 2) - Math.pow(triangleH, 2)); // Small circle bisection of triangleA
}
planet.tan = triangleH / triangleD;
planet.angle = Math.atan(planet.tan);
planet.sin = Math.sin(planet.angle);
planet.intersectX = planet.sin * planet.r;
planet.cos = Math.cos(planet.angle);
planet.intersectY = planet.cos * planet.r;
join.x = 0 + planet.sin * (planet.r + join.r);
join.y = 0 - planet.cos * (planet.r + join.r);
var coord1 = {
x: -planet.intersectX,
y: -planet.intersectY
};
var coord2 = {
x: planet.intersectX,
y: -planet.intersectY
}
moon.tan = (moon.k - join.y) / (moon.h - join.x);
moon.angle = Math.atan(moon.tan);
moon.intersectX = join.x - Math.cos(moon.angle) * (join.r);
moon.intersectY = join.y - Math.sin(moon.angle) * (join.r);
// If we have any bad values then just return no path
if (isNaN(coord1.x) || isNaN(coord1.y) || isNaN(coord2.x) || isNaN(coord2.y)) {
return;
}
var pathD = "M " + coord1.x + " " + coord1.y + " A " + planet.r + " " + planet.r + " 0 1 0 " + coord2.x + " " + coord2.y;
if (join.x - join.r <= 0 && moon.k < join.y) {
var crossOverY = circleYFromX(join, 0);
pathD += "A " + join.r + " " + join.r + " 0 0 1 0 " + (join.y + crossOverY);
pathD += "m 0 -" + (crossOverY * 2);
}
pathD += "A " + join.r + " " + join.r + " 0 0 1 " + moon.intersectX + " " + moon.intersectY;
var largeArcFlag = 1;
if (join.y < moon.k) {
largeArcFlag = 0;
}
pathD += "a " + moon.r + " " + moon.r + " 0 " + largeArcFlag + " 0 " + (moon.intersectX * -2) + " 0";
if (join.x - join.r <= 0 && moon.k < join.y) {
pathD += "A " + join.r + " " + join.r + " 0 0 1 0 " + (join.y - crossOverY);
pathD += "m 0 " + (crossOverY * 2);
}
pathD += "A " + join.r + " " + join.r + " 0 0 1 " + coord1.x + " " + coord1.y;
pathD += "A " + join.r + " " + join.r + " 0 0 1 " + coord1.x + " " + coord1.y;
return pathD;
};
var container = d3.select(".planet");
var moon = d3.select(".moon");
var tempPlanet = { x: -181.77581967381693, y: -144.9613789321555, r: 152 };
var tempMoon = { x: 0, y: 0, r: 32 };
var link = { r: 7.9 };
var pathD = generatePath(tempPlanet, tempMoon, { r: 31 });
if (pathD) {
moon.append("path")
.attr("d", pathD)
.attr("transform", "translate(" + [-181.77581967381693, 144.9613789321555] + ")")
.attr("class", "gravity")
.style("fill", "none")
.style("stroke", "red")
.style("stroke-linecap", "round")
.style("stroke-width", 2);
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<svg width="1680" height="523">
<g width="1680" height="523">
<g class="galaxy-main" width="1680" height="523">
<g class="planet selected" transform="translate(341,300) scale(0.5,0.5)">
<circle r="150" style="fill: rgb(72, 119, 159); stroke-dasharray: 944.477796076938px; stroke-dashoffset: 0px; stroke-width: 8px; stroke: rgb(255, 255, 255);"></circle>
<g class="moon" transform="translate(181.77581967381693,-144.96137893215555)">
<circle r="30" class="moon-circle" id="3" style="fill: rgb(72, 119, 159);"></circle>
</g>
</g>
</g>
</g>
</svg>
&#13;
我没有绘制绿色填充,而是正在绘制红色轮廓。你应该看到的是红色轮廓正确地围绕着较大的圆圈(行星),但是垂直向上而不是围绕较小的圆圈(月亮)。
看起来我们认为我们只是错过了一个轮换,但是我建造的原始原型并没有知道关于旋转,只是每个圆圈的中心。在这种情况下,这应该非常简单:
月亮
var tempMoon = { x: 0, y: 0, r: 32 };
始终位于(0,0),因为此圆位于将附加到路径的组的中心
行星
var tempPlanet = { x: -181.77581967381693, y: -144.9613789321555, r: 152 };
行星位于该群体的中心,该群体还包含月球群。因此,它的位置始终只是一个反向平移,它定位包含月亮的组
我相信这些位置是正确的(我已经尝试在月球层添加圆圈以确认它们位于正确的位置 - 它们是正确的)。我觉得这必须以某种方式归结为群体,但我仍然无法确定为什么这不能以正确的方向渲染。
答案 0 :(得分:0)
不幸的是,我似乎错过了代码中的translate
和rotate
,而我之前由于某种原因错过了该代码。包括这个使它按预期工作。