看来我终于把它修好了。请测试!我制作了两个 jsbin 版本:
1) 使用未修改的 Raphael 库的非固定版本:jsbin.com/oqojan/33。
2) 修改 path2curve() 函数的 FIXED 版本:jsbin.com/oqojan/32。
在这两个版本中都有黑色(原始)和白色(标准化)路径。如果一切正常,您不应该在黑色路径下方看到白色路径。如果你看到白色的路径,则 lib 代码有一个错误(请参阅下面的一些轻微闪烁的解释)。
请在输入字段上按住 ENTER 大约一分钟。只要 ENTER 关闭,代码就会重复生成随机路径。更改属性var list = "mlcqahvstz";
以更改随机化的基本字母。
这里是我对 lib 代码所做的解释。在原始 Raphaël 2.1.0 lib 代码中有一个函数 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;
当我将它们更改为:
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;
该功能按预期工作(即尊重每个可能的路径命令组合中的原始路径形状)。pcom
variable 指的是 ORIGINAL 路径的前一段,我还必须添加一种获取方法pcom
,这很容易,因为对于除 A 之外的所有其他路径命令,从原始路径段类型到三次曲线 (C) 的转换只产生一个立方命令。在 A 的情况下,该函数可能会产生多个 C 命令(短角度产生一个或几个 C 段,而较大的角度产生更多)。
唯一轻微的不一致来自 Z 命令,因为 Raphaël 将每个 Z 转换为 C。这会影响路径开始(或结束)的视觉外观,但差异并不大。我假设它将 Z 转换为 C 以使路径具有动画效果。如果不需要动画,那么您可以考虑编辑函数以使 Z:s 不转换,在这种情况下转换保真度非常好。
我很惊讶所有路径命令都可以如此可靠地表示为三次曲线!
我希望这个错误在 Raphaël 的未来版本中得到修复。
编辑:也为路径动画制作了测试平台:
1)非固定:http: //jsbin.com/oqojan/44
2)固定:http: //jsbin.com/oqojan/42
在对非动画路径和动画路径进行彻底测试后,我可以确认我对 path2curve 函数的修复是稳定的,并且可以在生产代码中实现。如果您想确定,请使用上述测试平台。