Javascript 将分割三次贝塞尔外推到1,1
我需要这里提供的解决方案的帮助 我需要修改它,以便在拆分后将返回的left和rights外推到Javascript 将分割三次贝塞尔外推到1,1,javascript,css-transitions,bezier,cubic,Javascript,Css Transitions,Bezier,Cubic,我需要这里提供的解决方案的帮助 我需要修改它,以便在拆分后将返回的left和rights外推到1,1。这是因为如果我不外推,我不能使用返回的分割立方贝塞尔作为css转换 这就是我做的测试。请提供帮助,因为real与mike way不匹配:(我认为问题是我需要将结果推断为1,1。我不能简单地将值加倍,尽管我非常确定 真实的 ease-in-out是cubic-bezier(.42,0,58,1)图形上是 前半部分是ease in,它是三次贝塞尔(.42,0,1,1),图形上是 seoncd的
1,1
。这是因为如果我不外推,我不能使用返回的分割立方贝塞尔作为css转换
这就是我做的测试。请提供帮助,因为real与mike way不匹配:(我认为问题是我需要将结果推断为1,1。我不能简单地将值加倍,尽管我非常确定
- 真实的
是ease-in-out
图形上是cubic-bezier(.42,0,58,1)
- 前半部分是
,它是ease in
,图形上是三次贝塞尔(.42,0,1,1)
- seoncd的一半是
,它是ease out
,grpahilly是cubic bezier(0,0,58,1)
- 上面发布的函数返回以下内容
与这一起点相同ease-in-out
- 左上半部分为
,图形显示为三次贝塞尔(0.21,0,0.355,0.25)
- 返回的代码:
左:[0,0,0.21,0,0.355,0.25,0.5,0.5]
- 返回的代码:
- 右下半部分为
,图形为三次贝塞尔(0.645,0.75,0.79,1)
- 返回的代码
右侧:[0.5,0.5,0.645,0.75,0.79,1,1,1]
- 返回的代码
var result = split({
z: .5,
x: [0, 0.42, 0.58, 1],
y: [0, 0, 1, 1]
});
alert(result.toSource());
前半部分是易用性,其中是立方贝塞尔(.42,0,1,1),图形上是
请验证此假设。(曲线原始终点为a中的0,0和1,1)
贝塞尔曲线的前半部分[0,0,42,0,58,1,1,1]不应为[0,0.42,0,1,1,1]
端点是正确的(在缩放到1,1后),但在那里失去了连续性
Mike算法返回的值是正确的
来解释为什么你的假设可能是错误的
您用于拆分的算法是一种众所周知的算法,称为de Casteljau算法。此方法可以用非常简单的方式进行几何表示。请查看有关如何在任意点拆分的动画演示
但是,您可能很快就会遇到一个问题,即尝试正确缩放贝塞尔曲线的分割部分以适合单位正方形,端点固定在0,0和1,1。这可能您可以在纸上很容易地尝试。最简单的方法可能是线性缩放贝塞尔曲线的控制点,但在大多数情况下,您会得到一条挤压的曲线。我创建了一个修改版的Mike分割函数,使其适合单位平方:)它使用hkrish的指针进行坐标标准化 只需将参数
fitUnitCell
设置为true.)
有趣的是,这实际上不是de Casteljau的算法——我提供的代码是基于使用矩阵表示法解决“分裂”问题的直接公式,而不是迭代的de Casteljau方法。当然,结果是一样的,但步骤的数量不同(事实上,在德·卡斯特尔约的原始论文中,他以扩展的形式写道(“courbes et surfaces`a pˆoles”)。他并没有确切地建议循环或任何迭代!:P当然,同样的事情也可以通过以矩阵形式书写伯恩斯坦基得到。我需要弄到那张纸=P(同样,使用现代html,重音字母应该很好=)这张纸,很遗憾,是以未发表的笔记的形式。我不确定我们是否能在网上找到它。你可以从Farouki或Farin关于这个主题的论文中找到原稿相关部分的扫描图,包括立方的展开形式和递归关系的推导。有趣的是,德卡斯特卢并没有与伯恩斯坦基础建立明确的关系。尽管他对评估曲线的想法更为笼统,但对于较低的阶数,他只是按原样写下了递推关系。(关于口音,我是从pdf复制的,可能是因为:)。谢谢@Mike'Pomax'Kamermans和hkrish的帮助。我正在重新做这件事,并将报告我的想法:)特别感谢hkrish的可视化,这太棒了!!
function splitCubicBezier(options) {
var z = options.z,
cz = z-1,
z2 = z*z,
cz2 = cz*cz,
z3 = z2*z,
cz3 = cz2*cz,
x = options.x,
y = options.y;
var left = [
x[0],
y[0],
z*x[1] - cz*x[0],
z*y[1] - cz*y[0],
z2*x[2] - 2*z*cz*x[1] + cz2*x[0],
z2*y[2] - 2*z*cz*y[1] + cz2*y[0],
z3*x[3] - 3*z2*cz*x[2] + 3*z*cz2*x[1] - cz3*x[0],
z3*y[3] - 3*z2*cz*y[2] + 3*z*cz2*y[1] - cz3*y[0]];
var right = [
z3*x[3] - 3*z2*cz*x[2] + 3*z*cz2*x[1] - cz3*x[0],
z3*y[3] - 3*z2*cz*y[2] + 3*z*cz2*y[1] - cz3*y[0],
z2*x[3] - 2*z*cz*x[2] + cz2*x[1],
z2*y[3] - 2*z*cz*y[2] + cz2*y[1],
z*x[3] - cz*x[2],
z*y[3] - cz*y[2],
x[3],
y[3]];
if (options.fitUnitSquare) {
return {
left: left.map(function(el, i) {
if (i % 2 == 0) {
//return el * (1 / left[6])
var Xmin = left[0];
var Xmax = left[6]; //should be 1
var Sx = 1 / (Xmax - Xmin);
return (el - Xmin) * Sx;
} else {
//return el * (1 / left[7])
var Ymin = left[1];
var Ymax = left[7]; //should be 1
var Sy = 1 / (Ymax - Ymin);
return (el - Ymin) * Sy;
}
}),
right: right.map(function(el, i) {
if (i % 2 == 0) {
//xval
var Xmin = right[0]; //should be 0
var Xmax = right[6];
var Sx = 1 / (Xmax - Xmin);
return (el - Xmin) * Sx;
} else {
//yval
var Ymin = right[1]; //should be 0
var Ymax = right[7];
var Sy = 1 / (Ymax - Ymin);
return (el - Ymin) * Sy;
}
})
}
} else {
return { left: left, right: right};
}
}
var easeInOut = {
xs: [0, .42, .58, 1],
ys: [0, 0, 1, 1]
};
var splitRes = splitCubicBezier({
z: .5,
x: easeInOut.xs,
y: easeInOut.ys,
fitUnitSquare: false
});
alert(splitRes.toSource())