I am creating a circular slider menu, I am using coregraphics to draw the control UI, Here I am trying to draw words on the circumference of a circle. But i cant able to make the spaces equally.
Here is my code and output. Please help me to give equal spaces between each word.
In drawRect
float angleStep = 2 * M_PI / [menuArray count];
float angle = degreesToRadians(90);
textRadius = textRadius - 12;
for (NSString* text in`enter code here` titleArray)
{
[self drawStringAtContext:ctx string:text atAngle:angle withRadius:textRadius];
angle -= angleStep;
}
//////////
- (void) drawStringAtContext:(CGContextRef) context string:(NSString*) text atAngle:(float)angle withRadius:(float) radis
{
CGSize textSize = [text sizeWithFont:[UIFont systemFontOfSize:11.0]];
float perimeter = 2 * M_PI * radis;
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:[UIFont systemFontOfSize:11.0]];
float x = radis * cos(angle);
float y = radis * 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;
}
}
Output
Related
Hi all I'm hoping someone can tell me how to decrease the spacing between sprites added from an array at the moment they are evenly spaced and centered but I need to decrease the width between the sprites
the whole block of code just incase is kind enough to test the spacing
int images = 5
for(int i = 0; i < images; ++i)
{
///load same ammount of spriteimages as images
SKSpriteNode *sprite =
[SKSpriteNode spriteNodeWithImageNamed:#"Null.jpg"];
sprite.name = #"sprite.name =Sprite%d",[NSString stringWithFormat:#"%i",i];
NSLog(#"***sprite.name %#",[NSString stringWithFormat:#"%i",i]);
///spriteSpacing
float offsetFraction = ((float)(i + 1)) / (images + 1);
float widthOfScreen =self.frame.size.width;
sprite.position = CGPointMake(widthOfScreen * offsetFraction,self.frame.size.height/2 +200);
[self addChild:sprite];
}
try this and see what happens
float widthOfScreen = self.frame.size.width + 100.0;
in the end I did this
float padding = 100.0f;
int blockWidth = [SKSpriteNode spriteNodeWithImageNamed:#"Null.jpg"].size.width;
float xOffset = (self.frame.size.width - (blockWidth * images + padding * (images-1))) / 2;
//float xOffset = (self.frame.size.width - (blockWidth * numberOfBlocks + padding * (numberOfBlocks-1))) / 2;
float StartPoint = xOffset+blockWidth/2;
for(int i = 0; i < images; ++i)
{
SKSpriteNode *sprite = [SKSpriteNode spriteNodeWithImageNamed:#"Null.jpg"];
///set start point of 1st sprite to load
if (i>0&&i<images)
{
StartPoint = StartPoint+ blockWidth+padding;
}
//increment sprite position
else if (i==images)
{
StartPoint = StartPoint+ blockWidth;
}
sprite.position = CGPointMake(StartPoint, self.frame.size.height * 0.8f);
[self addChild:sprite];
}
I'm trying to create clockwise text in Xcode. My current coding is just displaying like that.
But I want to change outer text to as follow
By using this library : https://github.com/javenisme/CurvaView
CoreTextArcView * cityLabel = [[[CoreTextArcView alloc] initWithFrame:rect1
font:font1
text:#"Hello this is radious arc with text"
radius:85
arcSize:110
color:color1] autorelease];
Remove arc for one file like as follows (set -fno-objc-arc to that library's .m file from build phases of your project target) :
Output like this
This is my code to do this, it draw attributed strings.
I can't post images but the result it's just right.
Text is also automatically reversed if the angle is between 100° and 260°
#define degreesToRadians(degrees) (( degrees ) / 180.0 * M_PI )
#define radiansToDegrees(radians) (( radians ) * ( 180.0 / M_PI ) )
+ (void)drawCurvedStringOnLayer:(CALayer *)layer
withAttributedText:(NSAttributedString *)text
atAngle:(float)angle
withRadius:(float)radius {
// angle in radians
CGSize textSize = CGRectIntegral([text boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)
options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
context:nil]).size;
float perimeter = 2 * M_PI * radius;
float textAngle = (textSize.width / perimeter * 2 * M_PI); // text curved width
float textRotation;
float textDirection;
if (angle > degreesToRadians(10) && angle < degreesToRadians(170))
{
//down
textRotation = 0.5 * M_PI ;
textDirection = - 2 * M_PI;
angle += textAngle / 2 + degreesToRadians(6);
}
else
{
//up
textRotation = 1.5 * M_PI ;
textDirection = 2 * M_PI;
angle -= textAngle / 2; // + degreesToRadians(6);
}
for (int c = 0; c < text.length; c++)
{
NSRange range = {c, 1};
NSAttributedString* letter = [text attributedSubstringFromRange:range];
CGSize charSize = CGRectIntegral([letter boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)
options:(NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading)
context:nil]).size;
float letterAngle = ( (charSize.width / perimeter) * textDirection );
float x = radius * cos(angle + (letterAngle/2));
float y = radius * sin(angle + (letterAngle/2));
//NSLog(#"Char %# with size: %f x %f", letter, charSize.width, charSize.height);
//NSLog(#"Char %# with angle: %f x: %f y: %f", letter, angle, x, y);
CATextLayer *text = [layers drawTextOnLayer:layer
withText:letter
frame:CGRectMake(layer.frame.size.width/2 - charSize.width/2 + x,
layer.frame.size.height/2 - charSize.height/2 + y,
charSize.width, charSize.height)
bgColor:nil
opacity:1];
text.transform = CATransform3DMakeAffineTransform( CGAffineTransformMakeRotation(angle - textRotation) );
angle += letterAngle;
}
}
+ (CATextLayer *)drawTextOnLayer:(CALayer *)layer
withText:(NSAttributedString *)text
frame:(CGRect)frame
bgColor:(UIColor *)bgColor
opacity:(float)opacity {
CATextLayer *textLayer = [[CATextLayer alloc] init];
textLayer.needsDisplayOnBoundsChange = true;
//[textLayer setFont:(__bridge CFTypeRef)(font)];
//[textLayer setFontSize:fontSize];
[textLayer setFrame:frame];
[textLayer setString:text];
[textLayer setAlignmentMode:kCAAlignmentCenter];
// [textLayer setForegroundColor:color.CGColor];
[textLayer setBackgroundColor:bgColor.CGColor];
[textLayer setContentsScale:[UIScreen mainScreen].scale];
[textLayer setOpacity:opacity];
[layer addSublayer:textLayer];
}
I'm using this to generate a curved text:
- (UIImage*)createCircularText:(NSString*)text withSize:(CGSize)size andCenter:(CGPoint)center
{
UIFont *font = [UIFont fontWithName:#"HelveticaNeue-Light" size:15];
// Start drawing
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
// Retrieve the center and set a radius
CGFloat r = center.x / 3;
// Start by adjusting the context origin
// This affects all subsequent operations
CGContextTranslateCTM(context, center.x, center.y);
// Calculate the full extent
CGFloat fullSize = 0;
for (int i = 0; i < [text length]; i++)
{
NSString *letter = [text substringWithRange:NSMakeRange(i, 1)];
CGSize letterSize = [letter sizeWithAttributes:#{NSFontAttributeName:font}];
fullSize += letterSize.width;
}
// Initialize the consumed space
CGFloat consumedSize = 0.0f;
// Iterate through the alphabet
for (int i = 0; i < [text length]; i++)
{
// Retrieve the letter and measure its display size
NSString *letter = [text substringWithRange:NSMakeRange(i, 1)];
CGSize letterSize = [letter sizeWithAttributes:#{NSFontAttributeName:font}];
// Calculate the current angular offset
//CGFloat theta = i * (2 * M_PI / ((float)[text length] * 3));
// Move the pointer forward, calculating the new percentage of travel along the path
consumedSize += letterSize.width / 2.0f;
CGFloat percent = consumedSize / fullSize;
CGFloat theta = (percent * 2 * M_PI) / ((float)[text length] / 4);
consumedSize += letterSize.width / 2.0f;
// Encapsulate each stage of the drawing
CGContextSaveGState(context);
// Rotate the context
CGContextRotateCTM(context, theta);
// Translate up to the edge of the radius and move left by
// half the letter width. The height translation is negative
// as this drawing sequence uses the UIKit coordinate system.
// Transformations that move up go to lower y values.
CGContextTranslateCTM(context, -letterSize.width / 2, -r);
// Draw the letter and pop the transform state
[letter drawAtPoint:CGPointMake(0, 0) withAttributes:#{NSFontAttributeName:font}];
CGContextRestoreGState(context);
}
// Retrieve and return the image
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
and i get this back:
The problem is that the text starts at 0° but I actually want it to begin more at the left, so that the center of the string is at 0°. How to accomplish this?
Two options should work:
After drawing all of the text, rotate the context half of the use angle and get the image from the context at that point.
Make two passes. The first simply calculates the required angle to draw the text. The second pass does what you do now. Except in the 2nd pass, subtract half of the required total angle from each letter's angle.
I want to draw shape of small land on view by taking latitude and longitude at the corner of land.
I have wrote following code. For now I took hard core values.
- (void)drawRect:(CGRect)rect {
CGSize screenSize = [UIScreen mainScreen].applicationFrame.size;
SCALE = MIN(screenSize.width, screenSize.height) / (2.0 * EARTH_RADIUS);
OFFSET = MIN(screenSize.width, screenSize.height) / 2.0;
CGPoint latLong1 = {18.626103, 73.805023};
CGPoint latLong2 = {18.626444, 73.804884};
CGPoint latLong3 = {18.626226, 73.804969};
CGPoint latLong4 = {18.626103, 73.805023};
NSMutableArray *points=[NSMutableArray arrayWithObjects:[NSValue valueWithCGPoint:[self convertLatLongCoord:latLong1]],[NSValue valueWithCGPoint:[self convertLatLongCoord:latLong2]], [NSValue valueWithCGPoint:[self convertLatLongCoord:latLong3]],[NSValue valueWithCGPoint:[self convertLatLongCoord:latLong4]],nil];
CGContextRef ctx = UIGraphicsGetCurrentContext();
for(int i=0;i<points.count;i++)
{
// CGPoint newCoord = [self convertLatLongCoord:latLong];
NSValue *val = [points objectAtIndex:i];
CGPoint newCoord = [val CGPointValue];
if(i == 0)
{
// move to the first point
CGContextMoveToPoint(ctx, newCoord.x, newCoord.y);
}
else
{
CGContextAddLineToPoint(ctx, newCoord.x, newCoord.y);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 1);
CGContextSetStrokeColorWithColor(ctx, [[UIColor redColor] CGColor]);
}
}
CGContextStrokePath(ctx);
}
Below is method which converts lat long into x,y co-ordinates.
- (CGPoint)convertLatLongCoord:(CGPoint)latLong
{
CGFloat x = EARTH_RADIUS * cos(latLong.x) * cos(latLong.y) * SCALE + OFFSET;
CGFloat y = EARTH_RADIUS * cos(latLong.x) * sin(latLong.y) * SCALE + OFFSET;
return CGPointMake(x, y);
}
My problem is when I took small land(e.g house land) area lat long its shape is not visible on view after draw. How I can show maximise shape of land on view.
Thanks in advance.
I am trying to make a simple graph for the ipad. I need to plot sin(x), cos(x) and tan(x) functions using QUARTZ. I know how to make the grid and the lines, but have no idea how to start with this. Any help is appreciated.
Please note I am not interested in core plot and other frameworks so please don't offer this as an answer.
Simple: you decide what resolution/precision you want, then you split the domain of the functions into intervals according to that, you calculate the values of the function in each interval and you connect those with a straight line:
// Within a subclass of UIView
- (void)drawFunction:(double (*)(double))fn from:(double)x1 to:(double)x2
{
[super drawRect:rect];
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGFloat comps[] = { 1.0, 0.0, 0.0, 1.0 };
CGContextSetStrokeColor(ctx, comps);
CGContextSetLineWidth(ctx, 2.0);
const double dx = 0.01; // precision
double scale_x = self.bounds.size.width / (x2 - x1);
double off_x = 0.0;
double scale_y = scale_x;
double off_y = self.bounds.size.height / 2;
CGContextMoveToPoint(ctx, x1 * scale_x - off_x, off_y - fn(x1) * scale_y);
for (double x = x1 + dx; x <= x2; x += dx) {
double y = fn(x);
CGFloat xp = x * scale_x - off_x;
CGFloat yp = off_y - y * scale_y;
CGContextAddLineToPoint(ctx, xp, yp);
}
CGContextStrokePath(ctx);
}
Call this from - drawRect::
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
[self drawFunction:sin from:0.0 to: 2 * M_PI];
}