javascript - 使用 Raphaël JS 和 SVG 调整扇区路径大小的更优雅的方法?

标签 javascript svg raphael trigonometry

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

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

饼图尚未完成。 扇区可以重叠。请暂时忽略它。

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

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

虽然效果很好,但我还是有点怀疑。不旋转路径能解决这个问题吗?感谢任何帮助或指点。

最佳答案

不旋转路径能解决这个问题吗?

回答:是的,可以。您根本不必更改路径的旋转。除非我遗漏了什么,否则以下代码似乎与您在 fiddle 中的代码一样工作:

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

解释:为了解释,我将在 W3 SpecRaphael Reference Library .也就是说,当您使用 cxcyrotation 时,它们使用 rxryx-axis-rotation 分别。

简而言之,只要rx等于ry,那么x-axis-rotation就没有意义。

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

为什么?这是因为你有一个圆弧。无论你旋转多少圈,它仍然是同一个圆。例如,在你面前举起一个玻璃杯,使玻璃杯与地面水平,而你正直视玻璃杯下方。现在用手腕旋转/扭转玻璃杯。你看到你看到的圆形如何保持相同的圆形吗?现在将玻璃杯正常放置在 table 上(因此它是垂直的并且可以容纳液体)。现在把玻璃杯倒过来。您可以看到明显的视角变化;它是朝上的,但现在是平躺的。这就是 x-axis-rotation 所做的。

也许一个更好的例子就是使用前面提到的 SVG 文件。在最后的 path 元素的圆弧上使用 x-axis-rotation。您会看到圆弧在旋转。这就是 x-axis-rotation 所做的。

回到您的代码:因为您只处理圆形对象,所以 x-axis-rotation 对最终输出没有影响。只要您处理圆形对象,您就可以毫无顾虑地将它的值硬编码为零。您真正需要做的就是修改您已经正确完成的 Angular 。

性能:我尝试使用 JavaScript 在修改和不修改 x-axis-rotation 变量的情况下为您的 sector_update 函数计时。结果?我没有看到性能差异。大部分时间花在实际绘制 SVG 上,而不是花在确定它的值的数学上。事实上,您在 JavaScript 中真正做的就是更新代码以设置 path 元素中的值。在那个时间点,浏览器接管它的渲染引擎来实际绘制 SVG 对象。我想这是每个浏览器的问题,因为每个浏览器都有不同的渲染性能。但至于 x-axis-rotation 值是否有任何影响,我的猜测是没有。如果 性能受到影响(因为浏览器可能必须执行额外的浮点运算),那么它就毫无意义了,因为绝大多数时间都花在了绘制对象上,而不是计算它值。所以我会说不用担心。

希望对您有所帮助,如果我遗漏了什么或没有解释清楚,请告诉我。

关于javascript - 使用 Raphaël JS 和 SVG 调整扇区路径大小的更优雅的方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10910671/

相关文章:

html - 如何将一个 HTML 文件添加到另一个 HTML 文件的正文中?

CSS3 圆环图

javascript - jQuery 方法教程

javascript - toLocaleString 给出错误的 12 小时时间

javascript - 如何一次滚动绘制每个 SVG 路径(按时间顺序)?

javascript - 如何在 raphaeljs 中使用 rect 元素剪辑内容?

javascript - 选择正确的技术(SVG 与 Canvas)

javascript - 以编程方式创建表盘图像的最佳方式?

javascript - 函数中的变量范围

javascript - 测试 React Modal 组件