2012-02-08 109 views
7

我有一個使用context.quadraticCurveTo(controlX, controlY, endX, endY);在HTML畫布上繪製的二次曲線。html二次曲線上的中心點

我有控制點和起點和終點,它們不一定水平相互水平。

如何使用這些參數找到曲線上的中心點?

其實我想把div標籤放在這個中心點上。 這個過程中是否有任何方程式解決?

+0

請解釋一下你的 「控制點」 和 「開始」 和 「結束」 點意思。 – 2012-02-08 13:50:55

+0

控制點是一個負責曲線形狀的點,起點是曲線開始的點,終點是曲線終點的點。 – 2012-02-08 13:55:28

+0

曲線的形狀沒有任何一個單獨的點可以負責 - 曲線的形狀是以a,b,c的形式寫成的。你的起點和終點 - 他們水平相互水平?你有一個你正在繪製的方程嗎? – 2012-02-08 13:56:42

回答

16

quadraticCurveTo繪製了一個quadratic Bézier curve

在任何給定位置(從0到1),以計算一個點的座標曲線上的公式是

x(t) = (1-t)^2 * x1 + 2 * (1-t) * t * x2 + t^2 * x3 
y(t) = (1-t)^2 * y1 + 2 * (1-t) * t * y2 + t^2 * y3 

其中(X1,Y1)是起始點,(X2,Y2)是控制點,(x3,y3)是終點。

所以,把那爲JavaScript,我們最終像

function _getQBezierValue(t, p1, p2, p3) { 
    var iT = 1 - t; 
    return iT * iT * p1 + 2 * iT * t * p2 + t * t * p3; 
} 

function getQuadraticCurvePoint(startX, startY, cpX, cpY, endX, endY, position) { 
    return { 
     x: _getQBezierValue(position, startX, cpX, endX), 
     y: _getQBezierValue(position, startY, cpY, endY) 
    }; 
} 

如果傳遞的起點,終點和控制點getQuadraticCurvePoint那裏,0.5的一半位置,您應該得到一個具有X和Y座標的對象。

聲明 - 我沒有測試代碼,所以你的里程可能會有所不同,但它好像沒錯。 ;)

編輯:我在jsfiddle中測試了代碼。 http://jsfiddle.net/QA6VG/

0

下面是描述二次方程的一個頁面,它是解決方案:wiki page。 這裏是關於這個問題的一個很好的教程,完整的圖表:tutorial

+0

我知道這個頁面,我也在看,但我想用javascript來計算中心點。我不知道如何找到中心點。 – 2012-02-08 13:57:26

+0

如果你的起點和終點水平相互平行,那麼曲線的x座標將直接位於中間(即)x_start +((x_end - x_start)/ 2),並且可以通過代入這個x值代入x原始方程並求解。你有等式嗎? – 2012-02-08 14:00:11

+0

這是真正的問題男人。我有隨機的開始和結束點 – 2012-02-08 14:01:34

0

一種可能的方法:

// compute coordinates of the middle point of a quadratic Bezier curve 
// need two functions: quadraticBezierCurvePoint and quadraticBezierCurvesMiddle 

function quadraticBezierCurvePoint(t, c) { 
    // compute relative coordinates of a point on the curve using t and c 
    // t is a number between 0 and 1 
    // c is an array of 3 points: 
    //  the initial point of the curve (always (0,0)) 
    //  the "handle" point of the curve 
    //  the final point of the curve 
    var t1, t1_2a, t1_2b, t1_2c; 
    t1 = 1 - t; 
    t1_2a = t1 * t1; 
    t1_2b = (2 * t) * t1; 
    t1_2c = t * t; 
    return { 
    x: (c[0].x * t1_2a) + (t1_2b * c[1].x) + (t1_2c * c[2].x), 
    y: (c[0].y * t1_2a) + (t1_2b * c[1].y) + (t1_2c * c[2].y) 
    }; 
} 

function quadraticBezierCurvesMiddle(m, c) { 
    var k, km = 1000, 
    km2 = (km >> 1), 
    len = 0, 
    len2, x, y, a = new Array(km + 1); 
    // compute curve lengths from start point to any point 
    // store relative point coordinates and corresponding length in array a 
    for (k = 0; k <= km; k++) { 
    a[k] = { 
     pt: quadraticBezierCurvePoint(k/km, c), 
     len: 0 
    }; 
    if (k > 0) { 
     x = a[k].pt.x - a[k - 1].pt.x; 
     y = a[k].pt.y - a[k - 1].pt.y; 
     a[k].len = a[k - 1].len + Math.sqrt(x * x + y * y); 
    } 
    } 
    // retrieve the point which is at a distance of half the whole curve length from start point 
    // most of the time, this point is not the one at indice km2 in array a, but it is near it 
    len2 = a[km].len/2; 
    if (a[km2].len > len2) 
    for (k = km2; k >= 0; k--) { 
     if (len2 >= a[k].len) break; 
    } else 
    for (k = km2; k <= km; k++) { 
     if (len2 <= a[k].len) break; 
    } 
    // return absolute coordinates of the point 
    return { 
    x: Math.round((a[k].pt.x + m.x) * 100)/100, 
    y: Math.round((a[k].pt.y + m.y) * 100)/100 
    }; 
} 

以及相應的jsfiddle:jsfiddle.net/pTccL/