18

我正在为一个必须在几周内开始的项目收集一些信息。该项目包含一个基于浏览器的绘图工具,用户可以在其中添加预定义的形状或自己形成形状。形状必须是可选择的、可自由缩放的并且可以使用类似 Illustrator 的转换工具(手柄)进行旋转。我们想到的预定义形状是:矩形、椭圆、半椭圆和(等腰)三角形。

到目前为止一切顺利,为了实现这一点,我在考虑 RaphaelJS 或 FabricJS,但是......每个形状(多边形/路径)都必须用一定的圆角半径绘制。并且在缩放时必须保持圆角半径,所以不会发生失真。用户可以通过输入指定舍入。

有一些障碍/问题:

  • 是否有一些统一的数学公式可以将角半径应用于我提到的形状?还是必须将每个形状本身都视为一个小型项目?我想将它作为路径或多边形返回,因此可以使用 SVG 或画布绘制。
  • 通过拖动变换手柄,每个缩放或旋转操作都会导致(大量)计算以检索我认为的更新形状。矩形是最容易实现的,除了椭圆之外,所有其他形状都更难计算。有什么方法可以加快这个过程吗?

我找到了一个网站,用户可以在其中绘制流程图并在提供的几乎所有形状上应用圆角半径。它工作得如此顺利,我无法确定他们是如何做到的。链接:https ://www.lucidchart.com/ (尝试按钮)

现在,我有点无能为力,我猜数学平庸。也许有人可以将我推向正确的方向并分享一些经验?

提前致谢。

顺便提一句。性能是这个项目的关键。绘图的输出必须是 SVG 格式。

4

3 回答 3

44

我最终遇到了类似的问题,但无法找到简单的解决方案。我最终基于 Adob​​e Illustrator 的操作编写了一个相当通用的圆角函数。它使用贝塞尔曲线而不是弧线,但我认为结果相当不错。

它支持以 SVG 图像的坐标空间中给定的半径或作为角与其相邻角之间距离的一部分进行舍入。

要使用它,请在您的项目中包含 rounding.js 并调用该函数:

roundPathCorners(pathString, radius, useFractionalRadius)

代码和一些测试路径在这里:http ://embed.plnkr.co/kGnGGyoOCKil02k04snu/preview

这就是 Plnkr 中的示例呈现方式:

SVG 路径舍入示例

于 2014-11-20T04:39:13.850 回答
2

尽管这个问题已经存在了一段时间,但有些人可能会停下来尝试这个解决方案:

var BORDER_RADIUS = 20;

function roundedPath( /* x1, y1, x2, y2, ..., xN, yN */ ){
    context.beginPath();
    if (!arguments.length) return;

    //compute the middle of the first line as start-stop-point:
    var deltaY = (arguments[3] - arguments[1]);
    var deltaX = (arguments[2] - arguments[0]);
    var xPerY = deltaY / deltaX;
    var startX = arguments[0] + deltaX / 2;
    var startY = arguments[1] + xPerY * deltaX / 2;

    //walk around using arcTo:
    context.moveTo(startX, startY);
    var x1, y1, x2, y2;
    x2 = arguments[2];
    y2 = arguments[3];
    for (var i = 4; i < arguments.length; i += 2) {
        x1 = x2;
        y1 = y2;
        x2 = arguments[i];
        y2 = arguments[i + 1];
        context.arcTo(x1, y1, x2, y2, BORDER_RADIUS);
    }

    //finally, close the path:
    context.arcTo(x2, y2, arguments[0], arguments[1], BORDER_RADIUS);
    context.arcTo(arguments[0], arguments[1], startX, startY, BORDER_RADIUS);
    context.closePath();
}

诀窍是在第一行的中间开始(和停止),然后使用这里arcTo很好描述的函数。

现在您“只是”必须找到一种方法将所有形状表示为多边形。

于 2015-01-21T15:29:16.847 回答
2

起点可以是using-svg-curves-to-imitate-rounded-corners。原理是用速记相对三次(s)转换每个角。此示例非常基本,仅适用于两种可能的极端情况。

我认为用速记相对立方来扩展这个像角落替换一样可以扩展以覆盖其他路径段。每个段都有一个曲线上的坐标点,必须用s段替换。数学可能是这个解决方案的有趣部分。

于 2013-10-23T12:22:48.180 回答