如何计算贝塞尔曲线上的控制点?

时间:2010-10-18 10:30:19

标签: javascript svg bezier curve-fitting

我确实有一条贝塞尔曲线,并且在某一点上,我希望第二条贝塞尔曲线以平滑的方式“分叉”第一条曲线。连同计算交点(贝塞尔曲线后面的百分比),我还需要控制点(切线和重量)。 使用以下javascript计算交叉点:

getBezier = function getBez(percent,p1,cp1,cp2,p2) {
    function b1(t) { return t*t*t }
    function b2(t) { return 3*t*t*(1-t) }
    function b3(t) { return 3*t*(1-t)*(1-t) }
    function b4(t) { return (1-t)*(1-t)*(1-t) }
    var pos = {x:0,y:0};
    pos.x = p1.x*b1(percent) + cp1.x*b2(percent) + cp2.x*b3(percent) + p2.x*b4(percent);
    pos.y = p1.y*b1(percent) + cp1.y*b2(percent) + cp2.y*b3(percent) + p2.y*b4(percent);
    return pos;
}

(非IE浏览器可以在http:// www.iscriptdesign.com - > Tutorial - > Groups& Paths)中查看它。 我现在需要的只是分支点的控制点或(正切和重量)(我不知道从哪里开始,我希望有人可以指出一些代码或数学方程,如果可能的话,作为相同参数的函数作为上面的getBezier函数。)

2 个答案:

答案 0 :(得分:1)

找到并实施它:de-Casteljau算法被证明是最快的可实施解决方案。它目前存在于: iScriptDesign(教程 - > Spit Bezier)。

答案 1 :(得分:0)

示例用法(我想,我需要@drjerry的帮助)

我有一个css3计时功能,这称为轻松进出:cubic-bezier(.42,0,.58,1)。图形上看起来像这样:http://cubic-bezier.com/#.42,0,.58,1

我想制作一个新的计时功能,它只是下半部分,然后是图表的上半部分。

所以下半部分是ease-incubic-bezier(.42,0,1,1)。以图形方式:http://cubic-bezier.com/#.42,0,1,1

上半部分为ease-outcubic-bezier(0,0,.58,1)。以图形方式:http://cubic-bezier.com/#0,0,.58,1

所以现在令我困惑的是,根据iScriptDesign的脚本,它告诉我它们是不同的。

iScriptDeisgn说ease-in-out的起始部分(ease-in)是:cubic-bezier(.21, 0, .355, .25)。以图形方式:http://cubic-bezier.com/#.21,0,.35,.25

iScriptDeisgn表示ease-in-out的结尾部分(ease-out)是:cubic-bezier(.145, .25, .29, .5)。以图形方式:http://cubic-bezier.com/#.14,.25,.29,.5

为什么iScriptDesign拆分函数返回的ease-inease-out与真实ease-in和真实ease-out不同?我不明白。

此示例的代码。

//////////////////START FROM ISCRIPTDESIGN
var splitBezier = function(array, perc) {
    array.unshift({x:0, y:0});
    var coll = [];
    while (array.length > 0) {
    for (var i = 0;i < array.length-1; i++) {
        coll.unshift(array[i]);
        array[i] = interpolate(array[i], array[i+1], perc);
    }
    coll.unshift(array.pop());
    }
    return {b1: [{x:coll[5].x, y:coll[5].y}, {x:coll[2].x, y:coll[2].y},{x:coll[0].x, y:coll[0].y}]
        , b2: [{x:coll[1].x - coll[0].x,y:coll[1].y-coll[0].y}, {x:coll[3].x - coll[0].x,y:coll[3].y-coll[0].y}, {x:coll[6].x - coll[0].x,y:coll[6].y-coll[0].y}]};
}

var interpolate = function (p0, p1, percent) {
    if (typeof percent === 'undefined') percent = 0.5;  
    return  {x: p0.x + (p1.x - p0.x) * percent
         , y: p0.y + (p1.y - p0.y) * percent};
}
//////////////////END FROM ISCRIPTDESIGN
var coord = function (x,y) {
  if(!x) var x=0;
  if(!y) var y=0;
  return {x: x, y: y};
}
var easeInOut = [new coord(.42,0), new coord(.58,1), new coord(1,1)];
var split50percent = splitBezier(easeInOut.slice(), .5);

所以split50percent设置为:

({
    b1: [{
        x: 0.21,
        y: 0
    }, {
        x: 0.355,
        y: 0.25
    }, {
        x: 0.5,
        y: 0.5
    }],
    b2: [{
        x: 0.14500000000000002,
        y: 0.25
    }, {
        x: 0.29000000000000004,
        y: 0.5
    }, {
        x: 0.5,
        y: 0.5
    }]
})

easeInOutSine

相同
  • easeInOutSine :. 44,0.05,0.55,0.95
  • REAL
    • easeInSine:0.47,0,0.745,0.715
    • easeOutSine:0.39,0.575,0.565,1
  • iScriptDesign
    • easeInSine :. 22,0.03,0.36,0.26
    • easeOutSine :. 14,0.24,0.28,0.48