SVG路径似乎没有正确定位自己

时间:2015-02-25 13:42:19

标签: javascript svg d3.js

我尝试在我移动它们时围绕2个圆圈生成一条路径。我基于一个例子,我发现并构建了一个我期望实现的原型example

enter image description here

我已经开始在我的应用程序中包含这个内容,但出于某种原因,我似乎无法找到绕过正确位置的绿色路径,而我无法弄清楚原因。< / p>

我已经整理了一个代码示例来说明:

&#13;
&#13;
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;
&#13;
&#13;

我没有绘制绿色填充,而是正在绘制红色轮廓。你应该看到的是红色轮廓正确地围绕着较大的圆圈(行星),但是垂直向上而不是围绕较小的圆圈(月亮)。

enter image description here

看起来我们认为我们只是错过了一个轮换,但是我建造的原始原型并没有知道关于旋转,只是每个圆圈的中心。在这种情况下,这应该非常简单:

月亮

var tempMoon = { x: 0, y: 0, r: 32 }; 

始终位于(0,0),因为此圆位于将附加到路径的组的中心

行星

var tempPlanet = { x: -181.77581967381693, y: -144.9613789321555, r: 152 }; 

行星位于该群体的中心,该群体还包含月球群。因此,它的位置始终只是一个反向平移,它定位包含月亮的组

我相信这些位置是正确的(我已经尝试在月球层添加圆圈以确认它们位于正确的位置 - 它们是正确的)。我觉得这必须以某种方式归结为群体,但我仍然无法确定为什么这不能以正确的方向渲染。

1 个答案:

答案 0 :(得分:0)

不幸的是,我似乎错过了代码中的translaterotate,而我之前由于某种原因错过了该代码。包括这个使它按预期工作。