ios - 绘制有角度/旋转的多行文本 - Core Text + Core Graphics

标签 ios iphone objective-c core-graphics core-text

浏览多个博客和论坛后我没有找到在 View 上下文中使用核心文本绘制倾斜/成角度文本的合适解决方案

事情是这样的。

我有一个 View ,其 - (void)drawRect:(CGRect)rect 被调用以在屏幕上绘制字符串(多行或单行文本)。

代码:

- (void)drawRect:(CGRect)rect
{
    NSString *text = @"This is some text being drawn by CoreText!\nAnd some more text on another line!";

    //Core Text (Create Attributed String)

    UIColor *textColor = [UIColor blackColor];
    CGColorRef color = textColor.CGColor;

    CTFontRef font = CTFontCreateWithName((CFStringRef) @"HelveticaNeue", 20.0, NULL);

    CTTextAlignment theAlignment = kCTTextAlignmentLeft;

    CFIndex theNumberOfSettings = 1;
    CTParagraphStyleSetting theSettings[1] =
    {
        { kCTParagraphStyleSpecifierAlignment, sizeof(CTTextAlignment),
            &theAlignment }
    };

    CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(theSettings, theNumberOfSettings);

    NSDictionary *attributesDict = [NSDictionary dictionaryWithObjectsAndKeys:
                                    CFBridgingRelease(font), (NSString *)kCTFontAttributeName,
                                    color, (NSString *)kCTForegroundColorAttributeName,
                                    paragraphStyle, (NSString *) kCTParagraphStyleAttributeName,
                                    nil];


    NSAttributedString *stringToDraw = [[NSAttributedString alloc] initWithString:text attributes:attributesDict];

    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)stringToDraw);

    //Create Frame
    CGMutablePathRef path = CGPathCreateMutable();

    CGAffineTransform transform = CGAffineTransformMakeScale(1, -1);
    //First translate your image View according to transform
    transform = CGAffineTransformTranslate(transform, 0, - self.bounds.size.height);
    // Then whenever you want any point according to UIKit related coordinates apply this transformation on the point or rect.
    CGRect frameText = CGRectMake(60, 100, 200, 200);
    CGRect newRectForUIKit = CGRectApplyAffineTransform(frameText, transform);
    CGPathAddRect(path, NULL, newRectForUIKit);

    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);

    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextSetTextMatrix(ctx, CGAffineTransformIdentity);
    CGContextTranslateCTM(ctx, 0, ([self bounds]).size.height );
    CGContextScaleCTM(ctx, 1.0, -1.0);

    //Draw Frame

    CTFrameDraw(frame, ctx);
    //Release all retained objects
    CFRelease(path);
}

输出:

enter image description here

除了绘制文本之外,我还想为整个绘制的文本添加一个角度。像这样(需要输出)

In this particular image the drawn text is rotated by 90 degreesA

那么如何在core text中给绘制的文字加上旋转角度呢?

注意:1)一个上下文可以有多个绘制的文本对象,它们各自的角度如下图所示

enter image description here

我希望我的问题很清楚。

最佳答案

在将 CTFrameRef 绘制到其中之前,将旋转应用于上下文。

编辑: 如果你想要多个角度,你需要保存/恢复 graphics states , 每一次。 像这样的东西:

- (void)drawRect:(CGRect)rect
{
    NSString *text = @"This is some text being drawn by CoreText!\nAnd some more text on another line!";

    //Core Text (Create Attributed String)

    UIColor *textColor = [UIColor blackColor];
    CGColorRef color = textColor.CGColor;

    CTFontRef font = CTFontCreateWithName((CFStringRef) @"HelveticaNeue", 20.0, NULL);

    CTTextAlignment theAlignment = kCTTextAlignmentLeft;

    CFIndex theNumberOfSettings = 1;
    CTParagraphStyleSetting theSettings[1] =
    {
        { kCTParagraphStyleSpecifierAlignment, sizeof(CTTextAlignment),
            &theAlignment }
    };

    CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(theSettings, theNumberOfSettings);

    NSDictionary *attributesDict = [NSDictionary dictionaryWithObjectsAndKeys:
                                    CFBridgingRelease(font), (NSString *)kCTFontAttributeName,
                                    color, (NSString *)kCTForegroundColorAttributeName,
                                    paragraphStyle, (NSString *) kCTParagraphStyleAttributeName,
                                    nil];


    NSAttributedString *stringToDraw = [[NSAttributedString alloc] initWithString:text attributes:attributesDict];

    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)stringToDraw);

    //Create Frame
    CGMutablePathRef path = CGPathCreateMutable();
    CGRect frameText = CGRectMake(60, 100, 200, 200);
    CGPathAddRect(path, NULL, frameText);

    CTFrameRef frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);
    CGContextRef ctx = UIGraphicsGetCurrentContext();

    CGContextSaveGState(ctx); /* save Graphic State for context rotation */

    // transform (rotate) context
    CGAffineTransform transform = CGAffineTransformMakeTranslation(self.bounds.size.width / 2.f, self.bounds.size.height / 2.f);
    CGFloat rotation = -M_PI / 2.f;
    transform = CGAffineTransformRotate(transform,rotation);
    transform = CGAffineTransformTranslate(transform,-self.bounds.size.width / 2.f, -self.bounds.size.height / 2.f);
    CGContextConcatCTM(ctx, transform);

    CGContextSaveGState(ctx);

    CGContextSetTextMatrix(ctx, CGAffineTransformIdentity);
    CGContextTranslateCTM(ctx, 0, ([self bounds]).size.height );
    CGContextScaleCTM(ctx, 1.0, -1.0);

    //Draw Frame

    CTFrameDraw(frame, ctx);
    //Release all retained objects
    CFRelease(path);

    CGContextRestoreGState(ctx);

    CGContextRestoreGState(ctx); /* restore Graphic State for context rotation */

     CGContextSaveGState(ctx); /* save Graphic States for another drawing */

     /* lets draw another string with different angle */
     attributesDict = [NSDictionary dictionaryWithObjectsAndKeys:
                                CFBridgingRelease(CTFontCreateWithName((CFStringRef) @"HelveticaNeue", 14.0, NULL)), (NSString *)kCTFontAttributeName,
                                [UIColor yellowColor].CGColor, (NSString *)kCTForegroundColorAttributeName,
                                nil];


     stringToDraw = [[NSAttributedString alloc] initWithString:@"another piece of text to drawn on same context with no angle" attributes:attributesDict];

     framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)stringToDraw);

     path = CGPathCreateMutable();
     CGPathAddRect(path, NULL, CGRectMake(60, -100, 200, 200));

     frame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);
     CFRelease(path);
     CGContextSetTextMatrix(ctx, CGAffineTransformIdentity);
     CGContextTranslateCTM(ctx, 0, ([self bounds]).size.height );
     CGContextScaleCTM(ctx, 1.0, -1.0);

     CTFrameDraw(frame, ctx);

     /**
      * @note don't forget to restore a previously saved GState, or this will be source of problems
      */
     CGContextRestoreGState(ctx);

     CFRelease(frame);
     CFRelease(framesetter);
}

enter image description here

关于ios - 绘制有角度/旋转的多行文本 - Core Text + Core Graphics,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21391348/

相关文章:

iOS:在 AV 视频上绘图,然后将绘图保存在视频文件中

ios - IOS 11-空中发布

iphone - 以编程方式使音量从静音状态变满

ios - 在 iOS 7 上以横向模式处理 UIActivityViewController 后 View 边界发生变化

iOS 在完成之前停止 animateWithDuration

iphone - 如何在 MFMailComposeViewController 的 MailComposer 工作表中添加 UIImage

iphone - 根据手机图像iphone显示图像

ios - UICollectionVIew:滚动时动画单元格

ios - 使用 UIActivityViewController 共享音频文件

objective-c - 如何使用 ABPeoplePickerNavigationController 选择地址簿中的多个条目