现有圆上的曲线文本 [英] Curve text on existing circle

查看:97
本文介绍了现有圆上的曲线文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

对于我正在建设的应用程序,我画了两个圆圈。一个比另一个大一点。我想在这些线之间弯曲文本,对于我正在建设的循环菜单。



我阅读大多数东西关于弯曲文本,你必须分割你的文本字符



我只是不能用自己的方式来表达自己的想法以获得我的角色的正确角度和位置。



我包含了目前菜单的截图,看起来像。只有我添加的文本是从UIImageView中的图片加载的。





我希望有人能给我一些起点,如何在白色圆圈中绘制文本。 p>

编辑:
好​​,我目前正在这一点:





我使用下列程式码完成:

   - (UIImage *)createMenuRingWithFrame:(CGRect)frame 
{
CGRect imageSize = CGRectMake(0,0,300,300);
float perSectionDegrees = 360 / [sections count];
float totalRotation = 90;
char * fontName =(char *)[self.menuItemsFont.fontName cStringUsingEncoding:NSASCIIStringEncoding];

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL,imageSize.size.width,imageSize.size.height,8,4 * imageSize.size.width,colorSpace,kCGImageAlphaPremultipliedFirst);

CGContextSetTextMatrix(context,CGAffineTransformIdentity);
CGContextSelectFont(Context,fontName,18,kCGEncodingMacRoman);

CGContextSetRGBFillColor(context,0,0,0,1);

CGPoint centerPoint = CGPointMake(imageSize.size.width / 2,imageSize.size.height / 2);
double radius =(frame.size.width / 2);

CGContextStrokeEllipseInRect(context,CGRectMake(centerPoint.x - (frame.size.width / 2),centerPoint.y - (frame.size.height / 2),frame.size.width,frame。 size)。

for(int index = 0; index< [sections count]; index ++)
{
NSString * menuItemText = [sections objectAtIndex:index];
CGSize textSize = [menuItemText sizeWithFont:self.menuItemsFont];
char * menuItemTextChar =(char *)[menuItemText cStringUsingEncoding:NSASCIIStringEncoding];

float x = centerPoint.x + radius * cos(degreesToRadians(totalRotation));
float y = centerPoint.y + radius * sin(degreesToRadians(totalRotation));

CGContextSaveGState(context);

CGContextTranslateCTM(context,x,y);
CGContextRotateCTM(context,degreesToRadians(totalRotation - 90));
CGContextShowTextAtPoint(context,0 - (textSize.width / 2),0 - (textSize.height / 2),menuItemTextChar,strlen(menuItemTextChar)

CGContextRestoreGState(context);

totalRotation + = perSectionDegrees;
}

CGImageRef contextImage = CGBitmapContextCreateImage(context);

CGContextRelease(context);
CGColorSpaceRelease(colorSpace);

return [UIImage imageWithCGImage:contextImage];
}

这些是我使用的变量:

  NSArray * sections = [[NSArray alloc] initWithObjects:@settings,@test,@stats,@nog iets woei,@​​woei2,nil]; 
self.menuItemsFont = [UIFont fontWithName:@VAGRounded-Boldsize:18];

旋转的词似乎正确,放置也。现在我需要弄清楚在哪个旋转字母(和他们的坐标)应该。我可以使用一些帮助。



编辑:修正!查看以下代码!

   - (void)drawStringAtContext:(CGContextRef)上下文字符串:(NSString *)text atAngle :( float)angle withRadius:(float)radius 
{
CGSize textSize = [text sizeWithFont:self.menuItemsFont];

float perimeter = 2 * M_PI * radius;
float textAngle = textSize.width / perimeter * 2 * M_PI;

angle + = textAngle / 2;

for(int index = 0; index< [text length]; index ++)
{
NSRange range = {index,1};
NSString * letter = [text substringWithRange:range];
char * c =(char *)[letter cStringUsingEncoding:NSASCIIStringEncoding];
CGSize charSize = [letter sizeWithFont:self.menuItemsFont];

NSLog(@Char%@ with size:%f x%f,letter,charSize.width,charSize.height);

float x = radius * cos(angle);
float y = radius * sin(angle);

float letterAngle =(charSize.width / perimeter * -2 * M_PI);

CGContextSaveGState(context);
CGContextTranslateCTM(context,x,y);
CGContextRotateCTM(context,(angle - 0.5 * M_PI));
CGContextShowTextAtPoint(context,0,0,c,strlen(c));
CGContextRestoreGState(context);

angle + = letterAngle;
}
}

- (UIImage *)createMenuRingWithFrame:(CGRect)frame
{
CGPoint centerPoint = CGPointMake(frame.size.width / 2 ,frame.size.height / 2);
char * fontName =(char *)[self.menuItemsFont.fontName cStringUsingEncoding:NSASCIIStringEncoding];

CGFloat * ringColorComponents =(float *)CGColorGetComponents(ringColor.CGColor);
CGFloat * textColorComponents =(float *)CGColorGetComponents(textColor.CGColor);

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(NULL,frame.size.width,frame.size.height,8,4 * frame.size.width,colorSpace,kCGImageAlphaPremultipliedFirst);

CGContextSetTextMatrix(context,CGAffineTransformIdentity);

CGContextSelectFont(context,fontName,18,kCGEncodingMacRoman);
CGContextSetRGBStrokeColor(context,ringColorComponents [0],ringColorComponents [1],ringColorComponents [2],ringAlpha);
CGContextSetLineWidth(context,ringWidth);

CGContextStrokeEllipseInRect(context,CGRectMake(ringWidth,ringWidth,frame.size.width - (ringWidth * 2),frame.size.height - (ringWidth * 2)));
CGContextSetRGBFillColor(context,textColorComponents [0],textColorComponents [1],textColorComponents [2],textAlpha);

CGContextSaveGState(context);
CGContextTranslateCTM(context,centerPoint.x,centerPoint.y);

float angleStep = 2 * M_PI / [sections count];
float angle = degreesToRadians(90);

textRadius = textRadius - 12;

for(NSString * text in sections)
{
[self drawStringAtContext:context string:text atAngle:angle withRadius:textRadius];
angle - = angleStep;
}

CGContextRestoreGState(context);

CGImageRef contextImage = CGBitmapContextCreateImage(context);

CGContextRelease(context);
CGColorSpaceRelease(colorSpace);

[self saveImage:[UIImage imageWithCGImage:contextImage] withName:@test.png];
return [UIImage imageWithCGImage:contextImage];

}


解决方案



将字符串的长度转换为 UnitCircle 。因此(string.lenght / circle perimeter)* 2Pi。现在你有整个字符串的弧度角。 (这是字符串开始和结束之间的角度)



对于单独的字母,你可以做同样的事情来获得单个字母的角度字母宽度)



一旦你以弧度表示角度,就可以计算字母的x和y位置(和旋转)。



奖金:对于均匀的间距,你甚至可以计算出所有字符串的总长度和整个周长之间的比率。



更新
我制作了一个概念验证使用html5 /画布,所以查看它与一个体面的浏览器:)你应该能够移植它。 (注意,代码没有注释)

wtf:代码在chrome调试控制台打开时运行正常,关闭时失败。 (解决方法:打开chrome控制台:ctrl-shift-j并重新加载页面:f5); FF3.6.8似乎很好,但字母'跳舞'。


For an application I am building I have drawn 2 circles. One a bit bigger than the other. I want to curve text between those lines, for a circular menu I am building.

I read most stuff about curving a text that you have to split up your text in characters and draw each character on it's own with the right angle in mind (by rotating the context you are drawing on).

I just can't wrap my head around on how to get the right angles and positions for my characters.

I included a screenshot on what the menu, at the moment, look like. Only the texts I added by are loaded from an image in an UIImageView.

I hope someone can get me some starting points on how I can draw the text in the white circle, at certain points.

EDIT: Ok, I am currently at this point:

I accomplish by using the following code:

- (UIImage*) createMenuRingWithFrame:(CGRect)frame
{
    CGRect imageSize = CGRectMake(0,0,300,300);
    float perSectionDegrees = 360 / [sections count];
    float totalRotation = 90;
    char* fontName = (char*)[self.menuItemsFont.fontName cStringUsingEncoding:NSASCIIStringEncoding];

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(NULL, imageSize.size.width, imageSize.size.height, 8, 4 * imageSize.size.width, colorSpace, kCGImageAlphaPremultipliedFirst);

    CGContextSetTextMatrix(context, CGAffineTransformIdentity);
    CGContextSelectFont(context, fontName, 18, kCGEncodingMacRoman);

    CGContextSetRGBFillColor(context, 0, 0, 0, 1);

    CGPoint centerPoint = CGPointMake(imageSize.size.width / 2, imageSize.size.height / 2);
    double radius = (frame.size.width / 2);

    CGContextStrokeEllipseInRect(context, CGRectMake(centerPoint.x - (frame.size.width / 2), centerPoint.y - (frame.size.height / 2), frame.size.width, frame.size.height));

    for (int index = 0; index < [sections count]; index++)
    {
        NSString* menuItemText = [sections objectAtIndex:index];
        CGSize textSize = [menuItemText sizeWithFont:self.menuItemsFont];
        char* menuItemTextChar = (char*)[menuItemText cStringUsingEncoding:NSASCIIStringEncoding];

        float x = centerPoint.x + radius * cos(degreesToRadians(totalRotation));
        float y = centerPoint.y + radius * sin(degreesToRadians(totalRotation));

        CGContextSaveGState(context);

        CGContextTranslateCTM(context, x, y);
        CGContextRotateCTM(context, degreesToRadians(totalRotation - 90));
        CGContextShowTextAtPoint(context, 0 - (textSize.width / 2), 0 - (textSize.height / 2), menuItemTextChar, strlen(menuItemTextChar));

        CGContextRestoreGState(context);

        totalRotation += perSectionDegrees;
    }

    CGImageRef contextImage = CGBitmapContextCreateImage(context);

    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);

    return [UIImage imageWithCGImage:contextImage];
}

These are the variables I use in there:

NSArray* sections = [[NSArray alloc] initWithObjects:@"settings", @"test", @"stats", @"nog iets", @"woei", @"woei2", nil];
self.menuItemsFont = [UIFont fontWithName:@"VAGRounded-Bold" size:18];

The rotation of the words seem correct, the placement also. Now I need somehow figure out at which rotation the letters (and their coordinates) should be. I could use some help with that.

Edit: Fixed! Check out the following code!

- (void) drawStringAtContext:(CGContextRef) context string:(NSString*) text atAngle:(float) angle withRadius:(float) radius
{
    CGSize textSize = [text sizeWithFont:self.menuItemsFont];

    float perimeter = 2 * M_PI * radius;
    float textAngle = textSize.width / perimeter * 2 * M_PI;

    angle += textAngle / 2;

    for (int index = 0; index < [text length]; index++)
    {
        NSRange range = {index, 1};
        NSString* letter = [text substringWithRange:range];     
        char* c = (char*)[letter cStringUsingEncoding:NSASCIIStringEncoding];
        CGSize charSize = [letter sizeWithFont:self.menuItemsFont];

        NSLog(@"Char %@ with size: %f x %f", letter, charSize.width, charSize.height);

        float x = radius * cos(angle);
        float y = radius * sin(angle);

        float letterAngle = (charSize.width / perimeter * -2 * M_PI);

        CGContextSaveGState(context);
        CGContextTranslateCTM(context, x, y);
        CGContextRotateCTM(context, (angle - 0.5 * M_PI));
        CGContextShowTextAtPoint(context, 0, 0, c, strlen(c));
        CGContextRestoreGState(context);

        angle += letterAngle;
    }
}

- (UIImage*) createMenuRingWithFrame:(CGRect)frame
{
    CGPoint centerPoint = CGPointMake(frame.size.width / 2, frame.size.height / 2);
    char* fontName = (char*)[self.menuItemsFont.fontName cStringUsingEncoding:NSASCIIStringEncoding];

    CGFloat* ringColorComponents = (float*)CGColorGetComponents(ringColor.CGColor);
    CGFloat* textColorComponents = (float*)CGColorGetComponents(textColor.CGColor);

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = CGBitmapContextCreate(NULL, frame.size.width, frame.size.height, 8, 4 * frame.size.width, colorSpace, kCGImageAlphaPremultipliedFirst);

    CGContextSetTextMatrix(context, CGAffineTransformIdentity);

    CGContextSelectFont(context, fontName, 18, kCGEncodingMacRoman);
    CGContextSetRGBStrokeColor(context, ringColorComponents[0], ringColorComponents[1], ringColorComponents[2], ringAlpha);
    CGContextSetLineWidth(context, ringWidth);  

    CGContextStrokeEllipseInRect(context, CGRectMake(ringWidth, ringWidth, frame.size.width - (ringWidth * 2), frame.size.height - (ringWidth * 2)));
    CGContextSetRGBFillColor(context, textColorComponents[0], textColorComponents[1], textColorComponents[2], textAlpha);

    CGContextSaveGState(context);
    CGContextTranslateCTM(context, centerPoint.x, centerPoint.y);

    float angleStep = 2 * M_PI / [sections count];
    float angle = degreesToRadians(90);

    textRadius = textRadius - 12;

    for (NSString* text in sections)
    {
        [self drawStringAtContext:context string:text atAngle:angle withRadius:textRadius];
        angle -= angleStep;
    }

    CGContextRestoreGState(context);

    CGImageRef contextImage = CGBitmapContextCreateImage(context);

    CGContextRelease(context);
    CGColorSpaceRelease(colorSpace);

    [self saveImage:[UIImage imageWithCGImage:contextImage] withName:@"test.png"];
    return [UIImage imageWithCGImage:contextImage];

}

解决方案

I tried to work it out quickly on paper, so i may be wrong :)

Convert the length of the string into units on the UnitCircle. Thus (string.lenght/ circle perimeter)*2Pi. You now have the angle in radians for the whole string. (That is the angle between start and end of the string)

For the separate letters you could do the same to get the angle (in radians) for individual letters (using letter widths)

Once you have the angle in radians you can work out the x and y position (and rotation) of the letters.

Bonus: for even spacing you could even work out the ratio between the total length of all strings and the whole perimeter. And divide the remaining space equally between the string.

Update I made a proof of concept using html5/canvas, so view it with a decent browser :) You should be able to port it. (mind you, the code isn't commented)
wtf: the code runs fine with the chrome debug console open, and fails when it is closed. (workaround: open chrome console: ctrl-shift-j and reload the page: f5); FF3.6.8 seems to do fine, but the letters 'dance'.

这篇关于现有圆上的曲线文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆