[英]cubic bezier cuve different in ios and javascript
背景:
在我的應用程序中,我必須沿着用戶點擊屏幕的點繪制一條曲線。 我在下面的博客中找到了該博客,該博客解釋了如何根據貝塞爾曲線的路徑點計算控制點。
該示例使用javascript,我將其調整為適用於iOS。 以下是我在應用程序中使用的代碼
void (^calculateAndAddControlPoints)(CGPoint firstPoint, CGPoint secondPoint, CGPoint thirdPoint) = ^void (CGPoint firstPoint, CGPoint secondPoint, CGPoint thirdPoint)
{
CGPoint controlPoint1;
CGPoint controlPoint2;
CGFloat distance12 = sqrt(pow(firstPoint.x-secondPoint.x, 2) + pow(firstPoint.y-secondPoint.y, 2));
CGFloat distance23 = sqrt(pow(secondPoint.x-thirdPoint.x, 2) + pow(secondPoint.y-thirdPoint.y, 2));
CGFloat scallingFactor12 = (tension * distance12) / (distance12 + distance23);
CGFloat scallingFactor23 = tension - scallingFactor12;
controlPoint1.x = secondPoint.x - (scallingFactor12 * (thirdPoint.x - firstPoint.x));
controlPoint1.y = secondPoint.y - (scallingFactor12 * (thirdPoint.y - firstPoint.y));
controlPoint2.x = secondPoint.x + (scallingFactor23 * (thirdPoint.x - firstPoint.x));
controlPoint2.y = secondPoint.y + (scallingFactor23 * (thirdPoint.y - firstPoint.y));
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [UIColor yellowColor].CGColor);
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:controlPoint1];
[path addLineToPoint:controlPoint2];
[path stroke];
[controlPoints addObject:[NSValue valueWithCGPoint:controlPoint1]];
[controlPoints addObject:[NSValue valueWithCGPoint:controlPoint2]];
};
NSUInteger curvePointsCount = [curvePoints count];
if (_closed) {
NSValue *lastPoint = [curvePoints lastObject];
[curvePoints addObject:curvePoints[0]];
[curvePoints addObject:curvePoints[1]];
[curvePoints insertObject:lastPoint atIndex:0];
for (NSInteger i=0; i < curvePointsCount; ++i) {
calculateAndAddControlPoints([curvePoints[i + 0] CGPointValue],
[curvePoints[i + 1] CGPointValue],
[curvePoints[i + 2] CGPointValue]);
}
[controlPoints addObject:controlPoints[0]];
[controlPoints addObject:controlPoints[1]];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:[curvePoints[1] CGPointValue]];
for (NSInteger i=1; i < curvePointsCount + 1; ++i) {
[path addCurveToPoint:[curvePoints[i + 1] CGPointValue]
controlPoint1:[controlPoints[2 * i + 0] CGPointValue]
controlPoint2:[controlPoints[2 * i + 1] CGPointValue]];
}
[path stroke];
} else {
for (NSInteger i=0; i < curvePointsCount - 2; ++i) {
calculateAndAddControlPoints([curvePoints[i + 0] CGPointValue],
[curvePoints[i + 1] CGPointValue],
[curvePoints[i + 2] CGPointValue]);
}
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:[curvePoints[0] CGPointValue]];
[path addQuadCurveToPoint:[curvePoints[1] CGPointValue]
controlPoint:[controlPoints[0] CGPointValue]];
for (NSInteger i=1; i < curvePointsCount - 2; ++i) {
[path addCurveToPoint:[curvePoints[i + 1] CGPointValue]
controlPoint1:[controlPoints[2 * i + 0] CGPointValue]
controlPoint2:[controlPoints[2 * i + 1] CGPointValue]];
}
[path moveToPoint:[curvePoints[curvePointsCount - 2] CGPointValue]];
[path addQuadCurveToPoint:[curvePoints[curvePointsCount - 1] CGPointValue]
controlPoint:[controlPoints[[controlPoints count] - 1] CGPointValue]];
[path stroke];
}
問題:
iOS中的輸出與JavaScript中的輸出不同,因為您可以看到下面的曲線在路徑點附近不平滑。 白線是實際曲線線,黃線是連接控制點的線,紅點是曲線點。
這就是javascript中相同曲線的外觀。
使用的曲線點:(100,100),(300,100),(300,300),(100,300)
生成的控制點:(50,150),(150,50),(250,50),(350,150),(350,250),(250,350),(150,350),(50, 250)
為什么我在iOS中找不到圈,如何解決?
解:
事實證明我在正確地計算控制點,但錯誤地將它們映射到曲線點。 感謝@gabbler我現在修復了它,下面是繪制曲線的正確循環
for (NSInteger i=1; i < curvePointsCount + 1; ++i) {
[_bezierPath moveToPoint:[curvePoints[i] CGPointValue]];
[_bezierPath addCurveToPoint:[curvePoints[i + 1] CGPointValue]
controlPoint1:[controlPoints[2 * i - 1] CGPointValue]
controlPoint2:[controlPoints[2 * i + 0] CGPointValue]];
}
當您添加從(100,100)到(300,100)的曲線時,控制點應為(150,50)和(250,50),在代碼中,控制點應改為(350,150)和(250,50),指定正確的控制點應使其起作用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.