计算SVG弧的中心 [英] Calculate center of SVG arc

查看:93
本文介绍了计算SVG弧的中心的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下信息:


  • radiusX(rx)

  • radiusY(ry)

  • x1

  • y1

  • x2

  • y2

  • radiusX (rx)
  • radiusY (ry)
  • x1
  • y1
  • x2
  • y2

SVG规范允许您通过指定弧的半径,起点和终点来定义弧。还有其他选项,如 large-arc-flag sweep-flag ,这有助于定义你想要的开始 - 达到终点的点。 此处提供更多详情

The SVG spec allows you to define an arc by specifying its radius, and start and end points. There are other options such as large-arc-flag and sweep-flag which help to define how you want the start-point to reach the end-point. More details here.

我不是数学上的倾向,所以要理解所有这些几乎不可能。

I am not mathematically inclined, so understanding all of this is near impossible.

我想我正在寻找一个简单的等式,让我知道 centerX centerY 给出SVG的arc命令接受的所有参数的值。

I guess I am looking for a simple equation that results in me knowing the centerX and centerY values given all the arguments accepted by SVG's arc command.

感谢任何帮助。

我搜索stackoverflow并且没有一个答案似乎用简单的英语解释解决方案。

I've search stackoverflow and none of the answers seem to explain the solution in plain english.

推荐答案

您可以使用此javascript函数进行计算。

You can use this javascript function to calculate.

// svg : [A | a] (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+

function  radian( ux, uy, vx, vy ) {
    var  dot = ux * vx + uy * vy;
    var  mod = Math.sqrt( ( ux * ux + uy * uy ) * ( vx * vx + vy * vy ) );
    var  rad = Math.acos( dot / mod );
    if( ux * vy - uy * vx < 0.0 ) {
        rad = -rad;
    }
    return rad;
}
//conversion_from_endpoint_to_center_parameterization
//sample :  svgArcToCenterParam(200,200,50,50,0,1,1,300,200)
// x1 y1 rx ry φ fA fS x2 y2
function svgArcToCenterParam(x1, y1, rx, ry, phi, fA, fS, x2, y2) {
    var cx, cy, startAngle, deltaAngle, endAngle;
    var PIx2 = Math.PI * 2.0;

    if (rx < 0) {
        rx = -rx;
    }
    if (ry < 0) {
        ry = -ry;
    }
    if (rx == 0.0 || ry == 0.0) { // invalid arguments
        throw Error('rx and ry can not be 0');
    }

    var s_phi = Math.sin(phi);
    var c_phi = Math.cos(phi);
    var hd_x = (x1 - x2) / 2.0; // half diff of x
    var hd_y = (y1 - y2) / 2.0; // half diff of y
    var hs_x = (x1 + x2) / 2.0; // half sum of x
    var hs_y = (y1 + y2) / 2.0; // half sum of y

    // F6.5.1
    var x1_ = c_phi * hd_x + s_phi * hd_y;
    var y1_ = c_phi * hd_y - s_phi * hd_x;

    // F.6.6 Correction of out-of-range radii
    //   Step 3: Ensure radii are large enough
    var lambda = (x1_ * x1_) / (rx * rx) + (y1_ * y1_) / (ry * ry);
    if (lambda > 1) {
        rx = rx * Math.sqrt(lambda);
        ry = ry * Math.sqrt(lambda);
    }

    var rxry = rx * ry;
    var rxy1_ = rx * y1_;
    var ryx1_ = ry * x1_;
    var sum_of_sq = rxy1_ * rxy1_ + ryx1_ * ryx1_; // sum of square
    if (!sum_of_sq) {
        throw Error('start point can not be same as end point');
    }
    var coe = Math.sqrt(Math.abs((rxry * rxry - sum_of_sq) / sum_of_sq));
    if (fA == fS) { coe = -coe; }

    // F6.5.2
    var cx_ = coe * rxy1_ / ry;
    var cy_ = -coe * ryx1_ / rx;

    // F6.5.3
    cx = c_phi * cx_ - s_phi * cy_ + hs_x;
    cy = s_phi * cx_ + c_phi * cy_ + hs_y;

    var xcr1 = (x1_ - cx_) / rx;
    var xcr2 = (x1_ + cx_) / rx;
    var ycr1 = (y1_ - cy_) / ry;
    var ycr2 = (y1_ + cy_) / ry;

    // F6.5.5
    startAngle = radian(1.0, 0.0, xcr1, ycr1);

    // F6.5.6
    deltaAngle = radian(xcr1, ycr1, -xcr2, -ycr2);
    while (deltaAngle > PIx2) { deltaAngle -= PIx2; }
    while (deltaAngle < 0.0) { deltaAngle += PIx2; }
    if (fS == false || fS == 0) { deltaAngle -= PIx2; }
    endAngle = startAngle + deltaAngle;
    while (endAngle > PIx2) { endAngle -= PIx2; }
    while (endAngle < 0.0) { endAngle += PIx2; }

    var outputObj = { /* cx, cy, startAngle, deltaAngle */
        cx: cx,
        cy: cy,
        startAngle: startAngle,
        deltaAngle: deltaAngle,
        endAngle: endAngle,
        clockwise: (fS == true || fS == 1)
    }

    return outputObj;
}

用法示例:

svg

svg

<path d="M 0 100 A 60 60 0 0 0 100 0"/>

js

var result = svgArcToCenterParam(0, 100, 60, 60, 0, 0, 0, 100, 0);
console.log(result);
/* will output:
{
    cx: 49.99999938964844,
    cy: 49.99999938964844,
    startAngle: 2.356194477985314,
    deltaAngle: -3.141592627780225,
    endAngle: 5.497787157384675,
    clockwise: false
}
*/

这篇关于计算SVG弧的中心的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆