在raphael js中绘制居中的弧线

use*_*699 25 bezier vector-graphics raphael geometric-arc

我需要使用raphael.js绘制各种大小的同心弧.我试图理解http://raphaeljs.com/polar-clock.html背后的代码,这与我想要的非常相似,但是,如果没有评论,就很难理解.

理想情况下,我需要一个函数来创建一条距离某个中心点给定距离的路径,从某个角度开始,以某个其他角度结束.

gen*_*abs 53

答案还可以,但不能动画.我为你敲了极点时钟的重要东西.这是一个激发成长的红色弧线.请享用.

// Custom Arc Attribute, position x&y, value portion of total, total value, Radius
var archtype = Raphael("canvas", 200, 100);
archtype.customAttributes.arc = function (xloc, yloc, value, total, R) {
    var alpha = 360 / total * value,
        a = (90 - alpha) * Math.PI / 180,
        x = xloc + R * Math.cos(a),
        y = yloc - R * Math.sin(a),
        path;
    if (total == value) {
        path = [
            ["M", xloc, yloc - R],
            ["A", R, R, 0, 1, 1, xloc - 0.01, yloc - R]
        ];
    } else {
        path = [
            ["M", xloc, yloc - R],
            ["A", R, R, 0, +(alpha > 180), 1, x, y]
        ];
    }
    return {
        path: path
    };
};

//make an arc at 50,50 with a radius of 30 that grows from 0 to 40 of 100 with a bounce
var my_arc = archtype.path().attr({
    "stroke": "#f00",
    "stroke-width": 14,
    arc: [50, 50, 0, 100, 30]
});

my_arc.animate({
    arc: [50, 50, 40, 100, 30]
}, 1500, "bounce");
Run Code Online (Sandbox Code Playgroud)

  • 为方便起见,这里的答案是一个jsfiddle,您可以输入要绘制的圆圈:http://jsfiddle.net/Bzdnm/2/ (9认同)
  • @Francisc - 如果你看看你上面两行的评论,你可以看到daxiang28问了完全相同的问题.更有趣的是,如果您查看以下行,即问题上方,距离不超过1厘米,您可以找到您问的问题的答案. (6认同)

Tom*_*m P 10

这是我如何做到的.以下代码允许您指定开始和结束角度以及内半径和外半径(用于执行那些时尚的甜甜圈样式饼图).解决方案不依赖于使用线段近似曲线,并且可以根据原始问题中提到的时钟示例进行动画处理.

首先创建你的Raphael绘图区; 以下假设您的HTML文件中包含id为"raphael_paper"的div:

var paper = Raphael("raphael_paper", 800, 800);
Run Code Online (Sandbox Code Playgroud)

对于这个Raphael对象,我们添加了一个自定义arc属性,一个取圆圈中心(x和y坐标),起始角度,结束角度,内半径和外半径的函数:

paper.customAttributes.arc = function (centerX, centerY, startAngle, endAngle, innerR, outerR) {
    var radians = Math.PI / 180,
        largeArc = +(endAngle - startAngle > 180);
        // calculate the start and end points for both inner and outer edges of the arc segment
        // the -90s are about starting the angle measurement from the top get rid of these if this doesn't suit your needs
        outerX1 = centerX + outerR * Math.cos((startAngle-90) * radians),
        outerY1 = centerY + outerR * Math.sin((startAngle-90) * radians),
        outerX2 = centerX + outerR * Math.cos((endAngle-90) * radians),
        outerY2 = centerY + outerR * Math.sin((endAngle-90) * radians),
        innerX1 = centerX + innerR * Math.cos((endAngle-90) * radians),
        innerY1 = centerY + innerR * Math.sin((endAngle-90) * radians),
        innerX2 = centerX + innerR * Math.cos((startAngle-90) * radians),
        innerY2 = centerY + innerR * Math.sin((startAngle-90) * radians);

    // build the path array
    var path = [
        ["M", outerX1, outerY1], //move to the start point
        ["A", outerR, outerR, 0, largeArc, 1, outerX2, outerY2], //draw the outer edge of the arc
        ["L", innerX1, innerY1], //draw a line inwards to the start of the inner edge of the arc
        ["A", innerR, innerR, 0, largeArc, 0, innerX2, innerY2], //draw the inner arc
        ["z"] //close the path
    ];                   
    return {path: path};
};
Run Code Online (Sandbox Code Playgroud)

现在我们可以使用它来绘制指定厚度的弧,开始和结束我们想要的地方,例如.

var redParams = {stroke: "#f00", "stroke-width": 1, fill:"#eee"},
    greenParams = {stroke: "#0f0", "stroke-width": 1, fill:"#eee"},
    blueParams = {stroke: "#00f", "stroke-width": 1, fill:"#eee"},
    cx = 300, cy = 300, innerRadius = 100, outerRadius = 250,

var red = paper.path().attr(redParams).attr({arc: [cx, cy, 0, 90, innerRadius, outerRadius]}); 
var green = paper.path().attr(greenParams).attr({arc: [cx, cy, 270, 320, innerRadius, outerRadius]}); 
var blue = paper.path().attr(blueParams).attr({arc: [cx, cy, 95, 220, innerRadius, outerRadius]});
Run Code Online (Sandbox Code Playgroud)

这应该会产生三个带有红色,蓝色和绿色1px边框的灰色弧段.


use*_*699 7

其实我自己找到了答案.我首先想到了一些涉及bezier曲线的奇特,但这只是有效的.

- >使用SVG路径语法创建路径,该路径与raphael一样

function arc(center, radius, startAngle, endAngle) {
    angle = startAngle;
    coords = toCoords(center, radius, angle);
    path = "M " + coords[0] + " " + coords[1];
    while(angle<=endAngle) {
        coords = toCoords(center, radius, angle);
        path += " L " + coords[0] + " " + coords[1];
        angle += 1;
    }
    return path;
}

function toCoords(center, radius, angle) {
    var radians = (angle/180) * Math.PI;
    var x = center[0] + Math.cos(radians) * radius;
    var y = center[1] + Math.sin(radians) * radius;
    return [x, y];
}
Run Code Online (Sandbox Code Playgroud)


nop*_*ole 7

只是为了从user592699的答案中删除一些猜测,这是完整的代码:

<script src="raphael.js"></script>
<script>

  var paper = Raphael(20, 20, 320, 320);

  function arc(center, radius, startAngle, endAngle) {
      angle = startAngle;
      coords = toCoords(center, radius, angle);
      path = "M " + coords[0] + " " + coords[1];
      while(angle<=endAngle) {
          coords = toCoords(center, radius, angle);
          path += " L " + coords[0] + " " + coords[1];
          angle += 1;
      }
      return path;
  }

  function toCoords(center, radius, angle) {
      var radians = (angle/180) * Math.PI;
      var x = center[0] + Math.cos(radians) * radius;
      var y = center[1] + Math.sin(radians) * radius;
      return [x, y];
  }

  paper.path(arc([100, 100], 80, 0, 270));  // draw an arc 
                                            // centered at (100, 100),
                                            // radius 80, starting at degree 0,
                                            // beginning at coordinate (80, 0)
                                            //   which is relative to the center
                                            //   of the circle,
                                            // going clockwise, until 270 degree

</script>
Run Code Online (Sandbox Code Playgroud)