【问题标题】:SVG path doesn't seem to orientate itself correctlySVG 路径似乎没有正确定位自身
【发布时间】:2015-04-02 20:36:17
【问题描述】:

我正在尝试围绕 2 个圆圈生成一条路径,当我移动它们时应该跟随它们。我以我找到的一个示例为基础,并构建了一个我期望实现的原型example

我已经开始在我的应用程序中包含它,但由于某种原因,我似乎无法获得围绕正确位置绘制的绿色路径,而且我不知道为什么。

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

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);
}
<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>

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

似乎我们只是缺少一个旋转,但我构建的原始原型不知道旋转,只是每个圆的中心。在这种情况下,这应该非常简单:

月亮

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

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

行星

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

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

我相信这些位置是正确的(我尝试在月球层上添加圆圈以确认它们在正确的位置 - 它们是)。我觉得这必须以某种方式归结为小组,但我仍然无法确定为什么这没有以正确的方向呈现。

【问题讨论】:

  • 一目了然,我注意到的一件事是该示例绘制了路径并将其旋转以包围“月亮”。你不做这个轮换。在here 中添加它可以改善您的问题,但角度似乎因月球半径而异。
  • @Mark:你知道吗,我一直很愚蠢。你是对的,它确实翻译了它,而我只是以某种方式错过了它。不过,这是一个有趣的第一步,我也许能够弄清楚为什么它会偏离那个偏移量。

标签: javascript svg d3.js


【解决方案1】:

不幸的是,由于某种原因,我在代码末尾似乎遗漏了 translaterotate。将其包含在内使其按预期工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-22
    • 1970-01-01
    • 2020-05-03
    • 2011-08-09
    • 2014-12-30
    • 1970-01-01
    相关资源
    最近更新 更多