code iphone image drawing lines - iphone

Hi everyone I'm french so scuse me for my english.So I want to make a game like flight control. When I draw line from an image like a plane I want that the plane follow that line .How can I do this please?

To draw the line, implement touchesBegan:, touchedMove:, touchedEnded, touchesCancelled: in your view or view controller and build a path (CGPathRef) using the touch points.
To make an an object move along the line, create a CAKeyframeAnimation, set the path and assign it to the object's layer.
Edit: sample code
When you have a CGPathRef path, creating the animation is as easy as:
CAKeyframeAnimation* animation = [CAKeyframeAnimation animation];
animation.path = thePath;
animation.duration = 2;
animation.rotationMode = kCAAnimationRotateAuto; // object auto rotates to follow the path
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
Finally, assign the animation to a layer:
[layer1 addAnimation:animation forKey:#"position"];
Edit 2: sample application:
I built an entire project called PathAnimation for you.
Edit 3: this is the code I used in the PathAnimation project:
//
// CustomView.m
// PathAnimation
//
// Created by Dominique d'Argent on 19.04.11.
// Copyright 2011 Nicky Nubbel. All rights reserved.
//
#import "CustomView.h"
#implementation CustomView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
object = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"arrow"]];
object.frame = CGRectMake(10.0, 30.0, 20.0, 20.0);
[self addSubview:object];
[self createPath];
}
return self;
}
- (void)dealloc
{
[object release];
[super dealloc];
}
#pragma mark - Custom drawing
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
CGContextRef g = UIGraphicsGetCurrentContext();
CGFloat bgColor[4] = {1.0f, 1.0f, 1.0f, 1.0f};
CGContextSetFillColor(g, bgColor);
CGContextFillRect(g, self.frame);
CGFloat color[4] = {1.0f, 0.0f, 0.0f, 1.0f};
CGContextAddPath(g,path);
CGContextSetStrokeColor(g, color);
CGContextDrawPath(g, kCGPathStroke);
CGPoint position = CGPathGetCurrentPoint(path);
CGContextAddArc(g, position.x, position.y, 5.0f, 0.0f, 2 * M_PI, 0);
CGContextSetFillColor(g, color);
CGContextDrawPath(g, kCGPathFill);
}
#pragma mark - Path creation
- (void)createPath {
path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, object.center.x, object.center.y);
}
#pragma mark - Touch handling
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint position = [touch locationInView:self];
if (CGRectContainsPoint(object.frame, position)) {
// start animation
[self go];
}
else {
CGPoint lastPosition = CGPathGetCurrentPoint(path);
if (CGPointEqualToPoint(lastPosition, object.center)) {
CGFloat angle = -atan2f(position.x - lastPosition.x, position.y - lastPosition.y);
angle += M_PI_2;
object.layer.transform = CATransform3DMakeRotation(angle, 0.0, 0.0, 1.0);
}
CGPathAddLineToPoint(path, NULL, position.x, position.y);
[self setNeedsDisplay];
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
}
#pragma mark - Animations
- (void) go {
NSLog(#"go");
object.layer.transform = CATransform3DIdentity;
CAKeyframeAnimation* animation = [CAKeyframeAnimation animation];
animation.path = path;
animation.duration = 5.0;
animation.rotationMode = kCAAnimationRotateAuto; // object auto rotates to follow the path
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
[object.layer addAnimation:animation forKey:#"position"];
object.center = CGPathGetCurrentPoint(path);
[self createPath];
}
#end

Related

Clear a drawing in drawRect

How can I clear a drawing in a subview? What should I put in my (void)clearLine below?
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Setup subview to draw a line
CGRect subviewRect = CGRectMake(0, 0, 250, 300);
Draw* _draw = [[Draw alloc] initWithFrame:subviewRect];
_draw.exclusiveTouch = NO;
_draw.backgroundColor = [UIColor clearColor];
[self addSubview:_draw];
}
return self;
}
- (void) clearLine
{
// how can I clear the drawing in Draw
}
And below is the Draw.m file, that will draw a straight line by getting the first touch as the starting point and the second touch as the ending point.
#implementation Draw
- (void)drawRect:(CGRect)rect {
CGPoint fromPoint;
CGPoint toPoint;
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 2.0);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGFloat components[] = {0.0, 0.0, 1.0, 1.0};
CGColorRef color = CGColorCreate(colorspace, components);
CGContextSetStrokeColorWithColor(context, color);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextMoveToPoint(context, fromPoint.x, fromPoint.y);
CGContextAddLineToPoint(context, toPoint.x, toPoint.y);
CGContextStrokePath(context);
CGColorSpaceRelease(colorspace);
CGColorRelease(color);
}
// Touch event
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch* touchPoint = [touches anyObject];
fromPoint = [touchPoint locationInView:self];
toPoint = [touchPoint locationInView:self];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch* touch = [touches anyObject];
toPoint = [touch locationInView:self];
[self setNeedsDisplay];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch* touch = [touches anyObject];
toPoint = [touch locationInView:self];
[self setNeedsDisplay];
}
In clear line you should remove Draw view and set it nil
Draw* _draw;
- (void) clearLine
{
[_draw removeFromSuperview];
_draw=nil;
}
and to again enable drawing use
-(void) initDrawView
{
CGRect subviewRect = CGRectMake(0, 0, 250, 300);
if(_draw!=nil)
{
[_draw removeFromSuperview];
_draw=nil;
}
_draw = [[Draw alloc] initWithFrame:subviewRect];
_draw.exclusiveTouch = NO;
_draw.backgroundColor = [UIColor clearColor];
[self addSubview:_draw];
}
Draw the background color on your view,
Like if you have white background then [UIColor whiteColor];
if you have black background then [UIColor blackColor];
Make a Bool variable in Draw class
And when you want to clear all like this
- (void) clearLine
{
// Here you can clearn lines
[_draw CleanAllLines]
}
And In Draw class make the method
-(void)CleanAllLines{
isNeedToClear = YES;
[self setNeedsLayout];
}
- (void)drawRect:(CGRect)rect {
if(isNeedToClear){
isNeedToClear = NO;
return;
}
CGPoint fromPoint;
CGPoint toPoint;
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 2.0);
CGColorSpaceRef colorspace = CGColorSpaceCreateDeviceRGB();
CGFloat components[] = {0.0, 0.0, 1.0, 1.0};
CGColorRef color = CGColorCreate(colorspace, components);
CGContextSetStrokeColorWithColor(context, color);
CGContextSetLineCap(context, kCGLineCapRound);
CGContextMoveToPoint(context, fromPoint.x, fromPoint.y);
CGContextAddLineToPoint(context, toPoint.x, toPoint.y);
CGContextStrokePath(context);
CGColorSpaceRelease(colorspace);
CGColorRelease(color);
}

Draw straight line on uiview

I'm writing a small word search game for the iPad.
i have a UIViewController and I tile the letters random in a UIView (lettersView). I set the label's tag in a 10x10 size matrix, using a UILabel for each letter.
Here is my problem: I don't know how to draw over letters (UILabels).
I have researched the matter and am confused which way to use (touch, opengl, quartz, hittest).
I just want to draw a straight line from the first point to the last point (touch down to touch up).
when user taps on the lettersView, I must find which letter was tapped. I can find the letter if I get the which UILabel was tapped first.
while the user moves their finger, it should draw the line, but while the user moves it must delete the old ones.
when the user touches up how can I get the last UILabel? i can check if its drawable, if I get the first and last uilabel.
(i found a small drawing sample written in ARC mode. but i cant convert it to non-ARC.)
i did all what you said. but i have some problems.
it draws the line on drawRect method. when i draw second line, it deletes the old one.
here is the codes:
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
touchStart = [[touches anyObject] locationInView:self];
float xPos=touchStart.x;
float yPos=touchStart.y;
startIndexCol = floor(xPos / letterWidth);
startIndexRow = floor(yPos / letterHeight);
xPos = (startIndexCol * letterWidth) + letterWidth/2;
yPos = (startIndexRow * letterHeight) + letterHeight/2;
touchStart = CGPointMake(xPos, yPos);
touchCurrent = touchStart;
[self setNeedsDisplay];
}
-(void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
touchCurrent = [[touches anyObject] locationInView:self];
//CGRect frame = CGRectMake(touchStart.x, touchStart.y, touchCurrent.x, touchCurrent.y);
//[self setNeedsDisplayInRect:frame];
[self setNeedsDisplay];
}
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
touchCurrent = [[touches anyObject] locationInView:self];
//[self hitTest:touchCurrent withEvent:event];
float xPos=touchCurrent.x;
float yPos=touchCurrent.y;
endIndexCol = floor(xPos / letterWidth);
endIndexRow = floor(yPos / letterHeight);
xPos = (endIndexCol * letterWidth) + letterWidth/2;
yPos = (endIndexRow * letterHeight) + letterHeight/2;
touchCurrent = CGPointMake(xPos, yPos);
//CGRect frame = CGRectMake(touchStart.x, touchStart.y, touchCurrent.x, touchCurrent.y);
//[self setNeedsDisplayInRect:frame];
//check if it can be drawn
if ((startIndexCol == endIndexCol) && (startIndexRow == endIndexRow)) {
//clear, do nothing
touchStart = touchCurrent = (CGPoint) { -1, -1 };
startIndexCol = startIndexRow = endIndexCol = endIndexRow = -1;
}
else{
if (startIndexRow == endIndexRow) {//horizontal
if (endIndexCol > startIndexCol) {
[delegate checkWordInHorizontal:startIndexRow start:startIndexCol end:endIndexCol];
}
else{
[delegate checkWordInHorizontalBack:startIndexRow start:startIndexCol end:endIndexCol];
}
}
else if (startIndexCol == endIndexCol){ //vertical
if (endIndexRow > startIndexRow) {
[delegate checkWordInVertical:startIndexCol start:startIndexRow end:endIndexRow];
}
else{
[delegate checkWordInVerticalBack:startIndexCol start:startIndexRow end:endIndexRow];
}
}
}
[self setNeedsDisplay];
}
-(UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
UIView *subview = [super hitTest:point withEvent:event];
if ([subview isEqual:self]) {
NSLog(#"point:%f - %f", point.x, point.y);
return self;
}
return nil;
}
-(void)drawLine{
NSLog(#"draw it");
drawIt=YES;
[self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
[super drawRect:rect];
if (drawIt) {
NSLog(#"drawit");
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(ctx, 20.0);
CGContextSetRGBStrokeColor(ctx, 1.0, 2.0, 0, 0.5);
CGContextMoveToPoint(ctx, touchStart.x, touchStart.y);
CGContextAddLineToPoint(ctx, touchCurrent.x, touchCurrent.y);
CGContextStrokePath(ctx);
drawIt=NO;
touchStart = touchCurrent = (CGPoint) { -1, -1 };
startIndexCol = startIndexRow = endIndexCol = endIndexRow = -1;
}
[[UIColor redColor] setStroke];
UIBezierPath *path = [UIBezierPath bezierPath];
[path moveToPoint:touchStart];
[path addLineToPoint:touchCurrent];
[path setLineWidth:20.0];
[path strokeWithBlendMode:kCGBlendModeNormal alpha:0.5];
// [path stroke];
}
First, the UILabels are likely to cause you more trouble than good. For such as simple grid, it is likely easier to just draw the letters by hand in drawRect:, along with your connecting line. The overall structure would look like this:
In touchesBegan:withEvent:, you would make a note of the starting point in an ivar.
In touchesMoved:withEvent:, you would update the end-point in an ivar and call [self setNeedsDisplayInRect:]. Pass the rectangle defined by your two points.
In touchesEnded:withEvent:, you would make a hit-test, do whatever processing that entails, and then clear your starting and end points and call [self setNeedsDisplayInRect:].
By "make a hit-test," I mean calculate which letter is under the touch. Since you're laying these out in a grid, this should be very simple math.
In drawRect:, you would use [NSString drawAtPoint:withFont:] to draw each letter. You would then use UIBezierPath to draw the line (you could also use CGPathRef, but I'd personally use the UIKit object).

How to convert cordinates to an image

Signature.h file
#import <UIKit/UIKit.h>
#interface Signature : UIViewController
{
CGPoint firstTouch;
CGPoint lastTouch;
UIColor *pointColor;
CGRect *points;
int npoints;
CGPoint location;
// UIImageView *signatureImageView;
}
#property CGPoint firstTouch;
#property CGPoint lastTouch;
#property (nonatomic, retain) UIColor *pointColor;
#property CGRect *points;
#property int npoints;
#property (retain, nonatomic) IBOutletCollection(UIImageView) NSArray *drawSign;
#property CGPoint location;
#property (retain, nonatomic) IBOutletCollection(UIImageView) NSArray *signatureImageView;
- (IBAction)savePressed:(id)sender;
- (IBAction)clearPressed:(id)sender;
#end
Signature.m
#import "Signature.h"
#interface Signature ()
#end
#implementation Signature
#synthesize drawSign;
#synthesize signatureImageView;
#synthesize firstTouch;
#synthesize lastTouch;
#synthesize pointColor;
#synthesize points;
- (id)initWithFrame:(CGRect)frame
{
return self;
}
- (id)initWithCoder:(NSCoder *)coder
{
if(self = [super initWithCoder:coder])
{
self.npoints = 0;
}
return self;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
NSLog(#"initwithnibname");
return self;
}
- (void)viewDidLoad
{
NSLog(#"viewdidload");
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (void)viewDidUnload
{
NSLog(#"view did unload");
[self setSignatureImageView:nil];
[self setDrawSign:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
}
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"touch has began");
UITouch *touch = [touches anyObject];
self.location = [touch locationInView:self.view];
}
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"touches moves");
UITouch *touch = [touches anyObject];
CGPoint currentLocation = [touch locationInView:self.view];
UIGraphicsBeginImageContext(self.view.frame.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
//[self.drawSign.image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
CGContextSetLineCap(ctx, kCGLineCapRound);
CGContextSetLineWidth(ctx, 5.0);
CGContextSetRGBStrokeColor(ctx, 1.0, 0.0, 0.0, 1.0);
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, location.x, location.y);
NSLog(#"%f x is",location.x);
NSLog(#"%f y is",location.y);
CGContextAddLineToPoint(ctx, currentLocation.x, currentLocation.y);
CGContextStrokePath(ctx);
// self.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
location = currentLocation;
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"touches ended");
UITouch *touch = [touches anyObject];
CGPoint currentLocation = [touch locationInView:self.view];
UIGraphicsBeginImageContext(self.view.frame.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
//[self.view.image drawInRect:CGRectMake(0, 0, self.frame.view.size.width, self.frame.view.size.height)];
CGContextSetLineCap(ctx, kCGLineCapRound);
CGContextSetLineWidth(ctx, 5.0);
CGContextSetRGBStrokeColor(ctx, 1.0, 0.0, 0.0, 1.0);
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, location.x, location.y);
CGContextAddLineToPoint(ctx, currentLocation.x, currentLocation.y);
CGContextStrokePath(ctx);
// self.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
location = currentLocation;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
- (void)dealloc {
[signatureImageView release];
[super dealloc];
}
- (IBAction)savePressed:(id)sender {
NSLog(#"save pressed");
}
- (IBAction)clearPressed:(id)sender {
NSLog(#"cancel pressed");
}
#end
Please find the two files, related to my project. From One view I am coming to this view. Now I need to save whatever has been drawn on it by the user. I am able to fetch the co-ordinates but unable to draw them. I have tried several attempts but neither of them seems to be working.Please find them in the Signature.m file itself in commented way. Kindly point me my mistake and correct me.
I really dont understand your question but the reason this code is wrong is in the touches part.
If you want to draw while you touch then you have to use the drawInRect method from the view you want to draw in.
If you want to draw over an image to save or present it after the user releases it then you have to create an image context on the touchesBegan, then draw on it on the touchesMoved, and finally save the result in the touchesEnded.
You can extract the result at the touchesEnded with
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
What your code is doing right now is, every time you move your finger you create a new canvas, draw on it and destroy it. When you lift your finger you create one more canvas draw on it and destroy it as well.
But im pretty sure you want to move your finger and show the result directly in the screen. For that I really recommend you google for a tutorial but basically you have to: create an array of points in the touches begin, on the touches move you add points to this array and on the touches end you add the final point to the array. MEANWHILE on the view drawInRect your code has to continuously draw the points in this array.
EDIT:
ASSUMING you have a valid UIImage (blanc canvas already initialized) at the beginning in
self.drawSign.image
Try:
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"touches moves");
UITouch *touch = [touches anyObject];
CGPoint currentLocation = [touch locationInView:self.view];
UIGraphicsBeginImageContext(self.view.frame.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
[self.drawSign.image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
CGContextSetLineCap(ctx, kCGLineCapRound);
CGContextSetLineWidth(ctx, 5.0);
CGContextSetRGBStrokeColor(ctx, 1.0, 0.0, 0.0, 1.0);
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, location.x, location.y);
NSLog(#"%f x is",location.x);
NSLog(#"%f y is",location.y);
CGContextAddLineToPoint(ctx, currentLocation.x, currentLocation.y);
CGContextStrokePath(ctx);
self.drawSign.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
location = currentLocation;
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"touches ended");
UITouch *touch = [touches anyObject];
CGPoint currentLocation = [touch locationInView:self.view];
UIGraphicsBeginImageContext(self.view.frame.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
[self.drawSign.image drawInRect:CGRectMake(0, 0, self.frame.view.size.width, self.frame.view.size.height)];
CGContextSetLineCap(ctx, kCGLineCapRound);
CGContextSetLineWidth(ctx, 5.0);
CGContextSetRGBStrokeColor(ctx, 1.0, 0.0, 0.0, 1.0);
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, location.x, location.y);
CGContextAddLineToPoint(ctx, currentLocation.x, currentLocation.y);
CGContextStrokePath(ctx);
self.drawSign.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
location = currentLocation;
}
I am not sure if this will work, but even if it does it is a TERRIBLE WAY of doing it (performance wise).

Limitting UIImageView size while using CGAffineTransform

I want to limit my uiimageview size while using CGAffineTransform. I am limitting scale but I can't limit the size of the my uiimageview. When I run the app I see it is limitted but in the background the size of my uiimageview keeps increasing. How can I make this?
Here is my code:
- (id)initWithFrame:(CGRect)frame
{
if ([super initWithFrame:frame] == nil) {
return nil;
}
originalTransform = CGAffineTransformIdentity;
touchBeginPoints = CFDictionaryCreateMutable(NULL, 0, NULL, NULL);
self.userInteractionEnabled = YES;
self.multipleTouchEnabled = YES;
self.exclusiveTouch = YES;
return self;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSMutableSet *currentTouches = [[[event touchesForView:self] mutableCopy] autorelease];
[currentTouches minusSet:touches];
if ([currentTouches count] > 0) {
[self updateOriginalTransformForTouches:currentTouches];
[self cacheBeginPointForTouches:currentTouches];
}
[super touchesBegan:touches withEvent:event];
[self cacheBeginPointForTouches:touches];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
CGAffineTransform incrementalTransform = [self incrementalTransformWithTouches:[event touchesForView:self]];
self.transform = CGAffineTransformConcat(originalTransform, incrementalTransform);
CGAffineTransform transform = self.transform;
float scale = sqrt(transform.a*transform.a + transform.c*transform.c);
NSLog(#"%f",self.frame.size.height);
if (scale > SCALE_MAX){
self.transform = CGAffineTransformScale(transform, SCALE_MAX/scale, SCALE_MAX/scale);
}
else if (scale < SCALE_MIN){
self.transform = CGAffineTransformScale(transform, SCALE_MIN/scale, SCALE_MIN/scale);
}
[super touchesMoved:touches withEvent:event];
}
-(void)updateOriginalTransformForTouches:(NSSet *)touches{
CGAffineTransform transform = self.transform;
float scale = sqrt(transform.a*transform.a + transform.c*transform.c);
if (scale > SCALE_MAX){
self.transform = CGAffineTransformScale(transform, SCALE_MAX/scale, SCALE_MAX/scale);
}
else if (scale < SCALE_MIN){
self.transform = CGAffineTransformScale(transform, SCALE_MIN/scale, SCALE_MIN/scale);
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
if (touch.tapCount >= 2) {
[self.superview bringSubviewToFront:self];
}
}
[self updateOriginalTransformForTouches:[event touchesForView:self]];
[self removeTouchesFromCache:touches];
NSMutableSet *remainingTouches = [[[event touchesForView:self] mutableCopy] autorelease];
[remainingTouches minusSet:touches];
[super touchesEnded:touches withEvent:event];
[self cacheBeginPointForTouches:remainingTouches];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
[self touchesEnded:touches withEvent:event];
}
You can know CGRect of UIImagView before applying transform on it like below example :
//Create transform
CGAffineTransform scaleTransform = CGAffineTransformMakeScale(1.2, 1.2);
//Apply transform on UIImageView to get CGRect
CRect newRect = CGRectApplyAffineTransform(yourImgView.frame, scaleTransform);
//Check if rect is in valid limitation
if(newRect.size.height > 200 && newRect.size.width >200) //your condition to limit UIImageView's Size
{
//Valid so apply transform
yourImageView.transform = scaleTransform
}
else
{
//rect increases so no transform
// no transform to UIImageView
NSLog(#"%#",NSStringFromCGRect(yourImageView.frame))
}
I was facing the a similar problem, I have an image view that's rotating according to compass heading data and also has to move position according to device change in interface orientation
I created a tempImageView to help maintain frame, and kept reseting it with every change in device orientation
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
// equal tempImageView to imageView
_tempImageView = [[UIImageView alloc] initWithFrame:CGRectMake(self.view.frame.size.width-75, 150, 64, 61)];
[_tempImageView setImage:[UIImage imageNamed:#"image.gif"]];
_tempImageView.transform = _imageView.transform;
// reset imageView
[_imageView removeFromSuperview];
_imageView = _tempImageView;
[self.view insertSubview:_imageView atIndex:1];
}

how to create a path using coregraphics?

i want to create a path.something like i touch the screen and draw line in touchmove event.when line intersect from starting point.fill that path using any colour.
now see in the image i've drawn a line.i just want to detect if line intersects again to start point.then fill that path with my own desired color.also i m using core graphics to draw line but it's very slow on real device.could you tell me a way to improve speed?
Header:
#import <UIKit/UIKit.h>
#interface myView : UIView {
CGMutablePathRef path;
CGPathRef drawingPath;
CGRect start;
BOOL outsideStart;
}
#end
Implementation:
#import "myView.h"
#implementation myView
- (id) init {
if (self = [super init]) {
self.userInteractionEnabled = YES;
self.multipleTouchEnabled = NO;
}
}
- (void) finishPath {
if (drawingPath) {
CGPathRelease(drawingPath);
}
CGPathCloseSubpath(path);
drawingPath = CGPathCreateCopy(path);
CGPathRelease(path);
path = NULL;
[self setNeedsDisplay];
return;
}
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
path = CGPathCreateMutable();
UITouch *t = [touches anyObject];
CGPoint p = [t locationInView:self];
start = CGRectZero;
start.origin = p;
start = CGRectInset(start,-10, -10);
outsideStart = NO;
CGPathMoveToPoint(path, NULL, p.x, p.y);
}
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if (!path) {
return;
}
UITouch *t = [touches anyObject];
CGPoint p = [t locationInView:self];
if (CGRectContainsPoint(start,p)) {
if (outsideStart) {
[self finishPath];
}
} else {
outsideStart = YES;
}
CGPathAddLineToPoint(path,NULL,p.x,p.y);
[self setNeedsDisplay];
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if (!path) {
return;
}
[self finishPath];
}
- (void) touchesCanceled:(NSSet *)touches withEvent:(UIEvent *)event {
if (!path) {
return;
}
CGPathRelease(path);
path = NULL;
}
- (void) drawInRect:(CGRect)rect {
CGContextRef g = UIGraphicsGetCurrentContext();
if (drawingPath) {
CGContextAddPath(g,drawingPath);
[[UIColor redColor] setFill];
[[UIColor blackColor] setStroke];
CGContextDrawPath(g,kCGPathFillStroke);
}
if (path) {
CGContextAddPath(g,path);
[[UIColor blackColor] setStroke];
CGContextDrawPath(g,kCGPathStroke);
}
}
- (void) dealloc {
if (drawingPath) {
CGPathRelease(drawingPath);
}
if (path) {
CGPathRelease(path);
}
[super dealloc];
}
#end
Note that you will probably want to do something so you aren't actually calling setNeedsDisplay every time the path changes. This can get very slow. Suggestions include having an NSTimer that fires every x milliseconds to check if it needs to redisplay and do so if it does, or only redrawing if the touch has moved a significant distance.
Maybe it can be useful to you link text
Core Graphics should definitely not be using [self setNeedsDisplay] every time the image changes, which is probably why your code is so slow on the device. Drawing is slow. If you use OpenGL ES to draw the lines, it will be much quicker, at the expense of being more difficult to understand.