Raphael.path2curve不尊重原始路径

Tim*_*nen 2 javascript raphael

我有Raphael.path2curve()的问题.该函数修改SVG路径字符串,以便将所有路径命令转换为绝对立方曲线(C).该函数支持所有路径命令(mlcqahvstMLCQAHVST参见SVG SPEC).

Raphael.path2curve()可以在很多情况下处理好路径,例如.它甚至可以将弧转换为正确的立方体,这不是一个简单的计算.我做了很多测试,并意识到由命令组成的路径QT,CSHT转换得很好.以下也没有问题:MS, HS, VS, LS, TC, TH, TL, TV, QA, TA.

但它无法处理命令QS, TS, AS, TT(按此顺序).

如果我们例如.有这样的路径,转换失败:

M 0 0  T 205.4 112.9  S 260.8 23.36 82.45 72.86 
Run Code Online (Sandbox Code Playgroud)

但这转换正确:

M 0 0  S 211.9 54.20 52.14 144.4  T 98.85 44.45 
Run Code Online (Sandbox Code Playgroud)

所以,MTS不行,但MST是.有问题的是S和T,因为当事情失败时,它们总是存在问题.

我制作了一个随机路径生成器(慢,但使用jsbin来提高速度),在那里你可以获得随机路径并使用Raphael.path2curve()将其转换为Cubic命令.在小提琴中单击SVG或在输入字段上按Enter键以获取新的随机路径.重复,直到找到不正确的一个.在jsfiddle中,HTML窗口是一个参数var list = "st";,您可以在其中设置要随机化的路径命令.

这是一个示例图像.蓝色是原始路径,红色是转换路径.它们应该完全相同.

路径

我应该怎么做Raphael代码才能使转换正确?

(我做了一个错误报告,但现在试图解决这个问题几个小时没有运气.

Tim*_*nen 7

似乎我终于解决了这个问题.请测试!我制作了两个jsbin版本:

1)使用未经修改的Raphael lib的NON-FIXED版本:jsbin.com/oqojan/33.
2)修改了path2curve()函数的FIXED版本:jsbin.com/oqojan/32.

在两个版本中都有黑色(原始)和白色(标准化)路径.如果一切正常,你不应该看到黑色路径下面的白色路径.如果您看到白色路径,则lib代码有一个错误(请参阅下面的一些轻微闪烁的解释).

请在输入字段上按住ENTER一分钟左右.只要ENTER关闭,代码就会重复生成随机路径.更改属性var list = "mlcqahvstz";以更改随机化的基本字母.

以下是我对lib代码所做的解释.在最初的 Raphaël2.1.0lib 代码中有一个函数path2curve(),它有以下几行:

case "S":
    nx = d.x + (d.x - (d.bx || d.x));
    ny = d.y + (d.y - (d.by || d.y));
    path = ["C", nx, ny][concat](path.slice(1));
    break;
case "T":
    d.qx = d.x + (d.x - (d.qx || d.x));
    d.qy = d.y + (d.y - (d.qy || d.y));
    path = ["C"][concat](q2c(d.x, d.y, d.qx, d.qy, path[1], path[2]));
    break;
Run Code Online (Sandbox Code Playgroud)

当我把它们改为:

case "S":
    if (pcom == "C" || pcom == "S") { // In "S" case we have to take into
                                      // account, if the previous command
                                      // is C/S.
        nx = d.x * 2 - d.bx;          // And reflect the previous 
        ny = d.y * 2 - d.by;          // command's control point relative
                                      // to the current point.  
    }
    else {                            // or some else or nothing
        nx = d.x;
        ny = d.y;
    }
    path = ["C", nx, ny][concat](path.slice(1));
    break;
case "T":
    if (pcom == "Q" || pcom == "T") { // In "T" case we have to take
                                      // into account, if the
                                      // previous command is Q/T.
        d.qx = d.x * 2 - d.qx;        // And make a reflection similar 
        d.qy = d.y * 2 - d.qy;        // to case "S".
    }
    else {                            // or something else or nothing
        d.qx = d.x;
        d.qy = d.y;
    }
    path = ["C"][concat](q2c(d.x, d.y, d.qx, d.qy, path[1], path[2]));
    break;
Run Code Online (Sandbox Code Playgroud)

该功能按预期工作(即在每个可能的路径命令组合中遵循原始路径形状).pcom变量是指ORIGINAL路径的前一段,我还必须添加一种获取方式pcom,这很容易,因为对于除A之外的所有其他路径命令,从原始路径段类型到三次曲线(C)的转换只产生一个立方指令.在A的情况下,该函数可以产生多于一个C命令(短角度产生一个或几个C段并且更大的角度产生更多).

唯一的轻微不一致来自Z命令,因为Raphaël将每个Z转换为C.这会影响路径开始(或结束)的视觉外观,但差异并不大.我假设它将Z转换为C以使路径可动画.如果不需要动画,那么您可以考虑编辑该函数以使Z:s未转换,在这种情况下转换保真度非常好.

令我惊讶的是,所有路径命令都可以如此可靠地表示为立方曲线!

我希望在未来的Raphaël版本中修复这个bug.

编辑:制作测试平台也用于路径动画:
1)未修复:http://jsbin.com/oqojan/44
2)固定:http://jsbin.com/oqojan/42

在使用非动画和动画路径进行全面测试后,我可以确认我对path2curve函数的修复是稳定的,并且可以在生产代码中实现.如果您想确定,请使用上述测试平台.