使用RaphaëlJS和SVG调整扇区路径的更优雅的方法是什么?

时间:2012-06-06 08:27:00

标签: javascript svg raphael trigonometry

我第一次使用Raphaël只有很少的svg经验,我需要一个真正了解这两个人的人来帮助我。

我创建了一个包含动态扇区的饼图。可以通过拖动圆形按钮来调整扇区的大小。见this fiddle。我只在Chrome和Safari中测试过,这是唯一需要的浏览器。

饼图尚未完成。 部门可以重叠。请暂时忽略这一点。

当扇区的起始角度大于结束角度时,我遇到了问题。当结束角度超过0/360°标记时就是这种情况。为了解决这个问题,我使用了路径 - 旋转 - 参数。我向前移动扇区,同时向后移动角度,直到结束角度为360.你可以在这个函数的小提琴中看到这个:

function sector_update(cx, cy, r, startAngle, endAngle, sec) {
    var x1 = cx + r * Math.cos(-startAngle * rad),
        x2 = cx + r * Math.cos(-endAngle * rad),
        y1 = cy + r * Math.sin(-startAngle * rad),
        y2 = cy + r * Math.sin(-endAngle * rad);


    var rotation = 0;

    // This is the part that I have the feeling could be improved.
    // Remove the entire if-clause and let "rotation" equal 0 to see what happens
    if (startAngle > endAngle) {
        rotation = endAngle;
        startAngle = startAngle - endAngle;
        endAngle = 360;
    }

    sec.attr('path', ["M", cx, cy, "L", x1, y1, "A", r, r, rotation, 
    +(endAngle - startAngle > 180), 0, x2, y2, "z"]);
}

虽然效果很好,但我有点怀疑。这可以在没有路径旋转的情况下解决吗?我感谢任何帮助或指示。

1 个答案:

答案 0 :(得分:2)

Can this be solved without the rotation of the path?

答案:是的,可以。您根本不必更改路径的旋转。除非我遗漏了某些内容,否则以下代码的效果与您在小提琴中的代码相同:

function sector_update(cx, cy, r, startAngle, endAngle, sec) {
    var x1 = cx + r * Math.cos(-startAngle * rad),
        x2 = cx + r * Math.cos(-endAngle * rad),
        y1 = cy + r * Math.sin(-startAngle * rad),
        y2 = cy + r * Math.sin(-endAngle * rad);

    //notice there is no "roation" variable
    if (startAngle > endAngle) {
        startAngle -= endAngle;
        endAngle = 360;
    }

    sec.attr('path', ["M", cx, cy, "L", x1, y1, "A", r, r, 0, 
    +(endAngle - startAngle > 180), 0, x2, y2, "z"]);
}

说明:对于我的解释,我将在中使用SVG术语 W3 SpecRaphael Reference Library。也就是说,当您使用cxcyrotation时,它们分别使用rxryx-axis-rotation

简而言之,只要rx等于ryx-axis-rotation就毫无意义。

看看this SVG。使用浏览器的开发工具,或将SVG保存到计算机并使用文件编辑器进行编辑。具体来说,查看最后一个path元素,其中包含四个弧。尝试修改每个弧上的x-axis-rotation值。你会注意到第一个弧(rxry都是“25”)在更新x-axis-rotation值时永远不会改变。

为什么?这是因为你有一个圆弧。无论你旋转多少圈,它仍然是同一个圆圈。例如,在你面前拿一块玻璃,使玻璃与地面保持水平,然后直接向下看玻璃。现在用手腕旋转/扭转玻璃。你看到你看到的圆形形状是如何保持相同的圆形吗?现在将玻璃正常放在桌子上(因此它是垂直的并且可以保持液体)。现在把杯子翻过来。你可以看到明显的视角变化;它指向上方,但现在它正在平放。这就是x-axis-rotation的作用。

也许更好的例子就是玩上述SVG文件。在x-axis-rotation元素的最后一个弧上使用path进行游戏。你会看到弧线在旋转。这就是x-axis-rotation的作用。

返回您的代码:因为您只处理圆形对象,x-axis-rotation对最终输出没有任何影响。只要你处理循环对象,你就可以将它的值硬编码为零而不用担心。你真正需要做的就是修改你已经正确完成的角度。

效果:我尝试使用JavaScript为sector_update函数计时,无论是否修改x-axis-rotation变量。结果?我发现性能没有差别。花费的大部分时间是实际绘制SVG,而不是确定其值的数学。实际上,您在JavaScript中所做的只是更新代码以设置path元素中的值。在那个时间点,浏览器接管它的渲染引擎来实际绘制SVG对象。我想那时它是每个浏览器的问题,因为每个浏览器都有不同的渲染性能。但至于x-axis-rotation值是否有效,我的猜测是否定的。如果 性能命中(因为浏览器可能需要进行额外的浮点操作),那就太难以理解,因为绝大部分时间都花在绘制对象上,而不是计算它值。所以我想说不要担心。

我希望有所帮助,如果我遗漏了某些内容或者没有充分解释,请告诉我。