拉斐尔三角形的中心

center of Raphael triangle

假设我需要在三角形区域的中间放置一个文本。 我可以使用 getBBox():

计算三角形中心的坐标
var triangle = "M0,0 L100,0 100,50 z";
var BBox = paper.path(triangle).getBBox();
var middle;
middle.x = BBox.x + BBox.width/2;
middle.y = BBox.y + BBox.height/2;

这导致坐标 (50, 25) 始终位于三角形的长边。 我怎样才能确保计算出的 "middle" 在 内部 三角形?

正确的坐标应该大约是:(75, 25).

代码当然应该独立于这个特定的例子,它应该适用于任何形状。

此代码段将通过平均顶点计算任何多边形的中心。

var paper = Raphael(0,0, 320, 200);

var triangle = "M0,0 L100,0 100,50 z";
var tri = paper.path(triangle);
tri.attr('fill', 'blue');

var center = raphaelPathCenter( tri );
var circle = paper.circle( center.x, center.y, 5);
circle.attr("fill", "#f00");
circle.attr("stroke", "#fff");


function raphaelPathCenter( path ) {
 
  path.getBBox(); // forces path to be traced so realPath is not null.
  
  var vertices = parseSVGVertices( path.realPath );
  
  var center = vertices.reduce( function(prev,cur) {
      return { x: prev.x + cur.x, y: prev.y + cur.y }
    }, {x:0, y:0} );
  
  center.x /= vertices.length;
  center.y /= vertices.length;

  return center;
}

function parseSVGVertices( svgPath )
{
  var vertices = [];
  for ( var i = 0; i < svgPath.length; i ++ )
  {    
    var vertex = svgPath[i];
    
    if ( "ML".indexOf( vertex[0] ) > -1 ) // check SVG command
        vertices.push( { x: vertex[1], y: vertex[2] } );
  }  
  return vertices;
}
<script src="https://raw.githubusercontent.com/DmitryBaranovskiy/raphael/master/raphael-min.js"></script>
<canvas id='canvas'></canvas>
<pre id='output'></pre>

不过有a few more triangle centers可以选择。

我对该主题进行了更多研究,并根据另一个列表中的建议来到这里: https://en.wikipedia.org/wiki/Centroid

那里有一个计算不规则多边形质心的算法,我把它翻译成了这个代码:

function getCentroid(path) {
    var x = new Array(11);
    var y = new Array(11);
    var asum = 0, cxsum = 0, cysum = 0;
    var totlength = path.getTotalLength();
    for (var i = 0; i < 11; i++) {
        var location = path.getPointAtLength(i*totlength/10);
        x[i] = location.x;
        y[i] = location.y;

        if (i > 0) {
            asum += x[i - 1]*y[i] - x[i]*y[i - 1];
            cxsum += (x[i - 1] + x[i])*(x[i - 1]*y[i] - x[i]*y[i - 1]);
            cysum += (y[i - 1] + y[i])*(x[i - 1]*y[i] - x[i]*y[i - 1]);
        }
    }

    return({x: (1/(3*asum))*cxsum, y: (1/(3*asum))*cysum});

}

基本上是任意路径的10个点的近似(第11个等于起点),函数returns,对于那个三角形,坐标:

Object {x: 65.32077336966377, y: 16.33111549955705}

我用很多其他形状测试过它,效果很好。

希望对大家有所帮助。