ios - 在一组给定点之间绘制贝塞尔曲线

标签 ios bezier uibezierpath

在 iOS 应用程序中绘制通过一组给定点的贝塞尔曲线的最佳方法是什么

最佳答案

例如,可以通过查看 BEMSimpleLineGraph GitHub Project 来实现更通用的方法。 (有关更多信息,请参见此处:)。在这里,我提取了一种通过给定点列表绘制贝塞尔曲线的方法。

头文件(BezierLine.h):

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <CoreGraphics/CoreGraphics.h>

@interface BezierLine : NSObject

/*
 Draws a bezier curved line on the given context
 with points: Array of CGPoint values
 */
-(void) drawBezierCurveInContext:(CGContextRef)context withPoints:(NSArray*)points lineColor:(UIColor*)color lineWidth:(CGFloat)lineWidth;

@end

实现(BezierLine.m):

#import "BezierLine.h"

@implementation BezierLine

-(void) drawBezierCurveInContext:(CGContextRef)context withPoints:(NSArray*)points lineColor:(UIColor*)color lineWidth:(CGFloat)lineWidth {
    if (points.count < 2) return;

    CGPoint CP1;
    CGPoint CP2;

    // LINE
    UIBezierPath *line = [UIBezierPath bezierPath];

    CGPoint p0;
    CGPoint p1;
    CGPoint p2;
    CGPoint p3;
    CGFloat tensionBezier1 = 0.3;
    CGFloat tensionBezier2 = 0.3;

    CGPoint previousPoint1;
    CGPoint previousPoint2;

    [line moveToPoint:[[points objectAtIndex:0] CGPointValue]];

    for (int i = 0; i < points.count - 1; i++) {
        p1 = [[points objectAtIndex:i] CGPointValue];
        p2 = [[points objectAtIndex:i + 1] CGPointValue];

        const CGFloat maxTension = 1.0f / 3.0f;
        tensionBezier1 = maxTension;
        tensionBezier2 = maxTension;

        if (i > 0) { // Exception for first line because there is no previous point
            p0 = previousPoint1;
            if (p2.y - p1.y == p1.y - p0.y) tensionBezier1 = 0;
        } else {
            tensionBezier1 = 0;
            p0 = p1;
        }

        if (i < points.count - 2) { // Exception for last line because there is no next point
            p3 = [[points objectAtIndex:i + 2] CGPointValue];
            if (p3.y - p2.y == p2.y - p1.y) tensionBezier2 = 0;
        } else {
            p3 = p2;
            tensionBezier2 = 0;
        }

        // The tension should never exceed 0.3
        if (tensionBezier1 > maxTension) tensionBezier1 = maxTension;
        if (tensionBezier2 > maxTension) tensionBezier2 = maxTension;

        // First control point
        CP1 = CGPointMake(p1.x + (p2.x - p1.x)/3,
                          p1.y - (p1.y - p2.y)/3 - (p0.y - p1.y)*tensionBezier1);

        // Second control point
        CP2 = CGPointMake(p1.x + 2*(p2.x - p1.x)/3,
                          (p1.y - 2*(p1.y - p2.y)/3) + (p2.y - p3.y)*tensionBezier2);


        [line addCurveToPoint:p2 controlPoint1:CP1 controlPoint2:CP2];

        previousPoint1 = p1;
        previousPoint2 = p2;
    }

    CGContextSetAllowsAntialiasing(context, YES);
    CGContextSetStrokeColorWithColor(context, color.CGColor);
    CGContextSetLineWidth(context, lineWidth);
    CGContextAddPath(context, line.CGPath);
    CGContextDrawPath(context, kCGPathStroke);
}


@end

您可以使用它,例如使用 UIGraphicsBeginImageContext 创建图像上下文并使用 UIGraphicsGetCurrentContext() 检索上下文。

否则,您可能需要更改代码并将生成的路径分配给 CALayer,然后将其添加到 UIView。

希望这对您有所帮助。

关于ios - 在一组给定点之间绘制贝塞尔曲线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12904767/

相关文章:

ios - 应用程序在后台运行一段时间后,Firebase 存储下载任务未完成

ios - 如果 80% 的 UI 在 UIWebView 上呈现,20% 是 native OCR,iOS 应用是否会被应用商店接受

ios - 在 subview removeFromSuperview 之后执行操作(Ios Swift)

glsl - 是否可以仅使用 GPU 来加厚二次贝塞尔曲线?

ios - 在单个 CAShapeLayer 中对多个 UIBezier 路径进行动画处理

ios - Realm 查询返回字典而不是对象

php - 在贝塞尔曲线中添加颜色的算法

swift - UIBezierPath - Swift 2

ios - 警告 : Could not load any Objective-C class information using PaintCode's code

javascript - 如何绘制用三次贝塞尔曲线绘制的椭圆的一部分?