iOS - drawRect in UIView : Suggestions to smoothen animation - ios

The following is my code, it's working properly, it's just that the "animation" of a moving line in the line if (guidelineOn) is not smooth. The drawRect is being called every 0.01 seconds.
if (guideLineOn)
{
[self drawGuidanceLineAtPoint:CGPointMake((65+guideLineOffset)*scalingF, 98*scalingF) withAlpha:paramAlpha];
}
It's kind of laggy and sometimes interferes with the user input. How do I resolve this? New to this so open to suggestions.
Thanks in advance for your help.
Pier.
- (void)drawRect:(CGRect)rect
{
scalingF = 1.0; // default : iPhone
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
scalingF = IPAD_SCALING_FACTOR;
}
if (guideLineOn)
{
[self drawGuidanceLineAtPoint:CGPointMake((65+guideLineOffset)*scalingF, 98*scalingF) withAlpha:paramAlpha];
}
// draw staff line
[self drawStaffLineFrom:CGPointMake(65*scalingF, 98*scalingF) toPoint:CGPointMake(420*scalingF, 98*scalingF)];
[self drawStaffLineFrom:CGPointMake(420*scalingF,108*scalingF) toPoint:CGPointMake(420*scalingF, 50*scalingF)];
[self drawStaffLineFrom:CGPointMake(415*scalingF,108*scalingF) toPoint:CGPointMake(415*scalingF, 50*scalingF)];
// cycle through all the static images to draw tbd
float offSet = 0.0;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
{
offSet += 50.0; // to adjust the metronome down
}
if (metronomeImage)
{
[metronomeImage drawInRect:CGRectMake(410.0f*scalingF, 195.0f*scalingF+offSet, metronomeImage.size.width*scalingF, metronomeImage.size.height*scalingF)];
}
if (circlesImage)
{
[circlesImage drawInRect:CGRectMake(400.0f*scalingF, 255.0f*scalingF+offSet, circlesImage.size.width*scalingF, circlesImage.size.height*scalingF)];
}
for (Note * v in notesArray)
{
UIImage * noteImage = [UIImage imageNamed: v.imageName];
[noteImage drawInRect:CGRectMake(v.notePlacement.x*scalingF, v.notePlacement.y*scalingF, noteImage.size.width*scalingF, noteImage.size.height*scalingF)];
}
if (!clearDisplay)
{
// draw the arrows
for (int i=0; i < arrowsToDrawArray.count; i++)
{
Arrow * arrowObj = [arrowsToDrawArray objectAtIndex:i];
UIColor * colourOfArrow = [arrowObj colourOfArrow]; // colour determines whether right or wrong
CGPoint p = [arrowObj arrowPlacement];
p.x = p.x*scalingF;
p.y = p.y*scalingF;
// CGPoint p = [val CGPointValue];
[self drawRooftopAtTopPointof:p colour:colourOfArrow lineJoin:kCGLineJoinMiter];
}
// draw the ties
for (int j=0; j < tiePointsArray.count; j++)
{
CGPointPair * tiePairToDraw = [tiePointsArray objectAtIndex:j];
CGPoint firstPt = [tiePairToDraw firstPoint];
firstPt.x = firstPt.x *scalingF;
firstPt.y = firstPt.y *scalingF;
CGPoint secondPt = [tiePairToDraw secondPoint];
secondPt.x = secondPt.x *scalingF;
secondPt.y = secondPt.y *scalingF;
[self drawPseudoCurveFromPoint:firstPt toPoint:secondPt];
}
// bool perfect = true;
// int noOfNotesHit = 0;
// draw the tick/cross/arrow
for (int k=0; k < answerObjArray.count; k++)
{
Answer * ansObj = [answerObjArray objectAtIndex:k];
if (ansObj.hit)
{
// noOfNotesHit++;
if (ansObj.earlyOrLate == -1) // early, draw right pointing arrow
{
UIImage * arrowImage = [UIImage imageNamed: #"arrowright.png"];
[arrowImage drawInRect:CGRectMake((ansObj.xPosition-(0.5*arrowImage.size.width))*scalingF, 125*scalingF, arrowImage.size.width*scalingF, arrowImage.size.height*scalingF)];
// perfect = false;
}
else if (ansObj.earlyOrLate == 1) // late, draw left pointing arrow
{
UIImage * arrowImage = [UIImage imageNamed: #"arrowleft.png"];
[arrowImage drawInRect:CGRectMake((ansObj.xPosition-(0.5*arrowImage.size.width))*scalingF, 125*scalingF, arrowImage.size.width*scalingF, arrowImage.size.height*scalingF)];
//perfect = false;
}
else // perfect!
{
// draw a tick
UIImage * tickImage = [UIImage imageNamed: #"tick.png"];
[tickImage drawInRect:CGRectMake((ansObj.xPosition-(0.5*tickImage.size.width))*scalingF, 125*scalingF, tickImage.size.width*scalingF, tickImage.size.height*scalingF)];
}
}
else
{
// draw a cross
UIImage * crossImage = [UIImage imageNamed: #"cross.png"];
[crossImage drawInRect:CGRectMake((ansObj.xPosition-(0.5*crossImage.size.width))*scalingF, 125*scalingF, crossImage.size.width*scalingF, crossImage.size.height*scalingF)];
//perfect = false;
}
}
}
else
{
// draw nothing
clearDisplay = false;
}
}

Here's my Core Animation solution for those interested.
- (void) animateRedLine: (float) alphaParam
{
[self.view addSubview:self.redlineImageView];
/* Start from top left corner */
[self.redlineImageView setFrame:CGRectMake(65.0f*scalingF,
50.0f*scalingF,
self.redlineImageView.image.size.width*scalingF,
self.redlineImageView.image.size.height*scalingF*2)];
[self.redlineImageView setAlpha:alphaParam];
[UIView beginAnimations:#"redLineAnimation"
context:( void *)self.redlineImageView];
/* 3 seconds animation */
[UIView setAnimationDuration:noOfBeatsInBar*timeInSecondsForOneBeat];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
/* Receive animation delegates */
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:
#selector(imageViewDidStop:finished:context:)];
/* End at the bottom right corner */
[self.redlineImageView setFrame:CGRectMake((65.0f+LENGTH_OF_BAR)*scalingF,
50.0f*scalingF,
self.redlineImageView.image.size.width*scalingF,
self.redlineImageView.image.size.height*scalingF*2)];
//[self.redlineImageView setAlpha:0.0f];
[UIView commitAnimations];
}

Related

Setting CPU Difficulty for Pong

Second time on here hoping that someone can guide me in the right direction.
I'm trying to implement a Pong game within an app for iOS devices (iPhone/iPod/iPad) and it works just fine, except for the fact that I can't beat the CPU, let alone score a point. Here's the implementation .m code:
#import "BTM_pongGame.h"
#import <QuartzCore/QuartzCore.h>
#define STEP_DURATION 0.05
#define RESET_BALL_ANIMATION_DURATION 0.5f
#define MARGIN_WHERE_BALL_IS_LEAVING 40
//#define CPU_SKILL 20
#interface BTM_pongGame ()
#end
#implementation BTM_pongGame
#synthesize cpuSkill, ballShape;
- (void)viewDidLoad
{
[super viewDidLoad];
cpuSkill = [BT_strings getJsonPropertyValue:self.screenData.jsonVars nameOfProperty:#"cpuSkill" defaultValue:#"20"];
ballShape = [BT_strings getJsonPropertyValue:self.screenData.jsonVars nameOfProperty:#"ballShape" defaultValue:#"1"];
if ([ballShape isEqual: #"1"]) {
self.ball.layer.cornerRadius = self.ball.frame.size.width / 2;
} else {
//self.ball.layer.cornerRadius = self.ball.frame.size.width / 2;
}
}
- (void) wordsPerLineInfoShowAlert {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Choose Game"
message:#"Multiplayer or Single Player? You decide! Choose below."
delegate:self
cancelButtonTitle:#"Single Player"
otherButtonTitles:#"Go Back",#"Multi Player", nil];
[alert show];
}
- (void)alertView: (UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString *title = [alertView buttonTitleAtIndex:buttonIndex];
if([title isEqualToString:#"Single Player"]) {
[self resetPlayerScoreLabels];
[self updatePlayerScoreLabels];
self.mode = kGameSinglePlayer;
[self moveComputerPaddle];
//Disable panning of computer paddle
[self.playerOne.superview setGestureRecognizers:#[]];
[self resetBoardForNewRound];
} else if ([title isEqualToString:#"Multi Player"]) {
[self resetPlayerScoreLabels];
[self updatePlayerScoreLabels];
self.mode = kGameMultiPlayer;
[self resetBoardForNewRound];
} else if ( [title isEqualToString:#"Go Back"]){
[self navLeftTap];
}
}
// thanks to MrsVanBeveren for coding the reset score stuff
-(void)resetPlayerScoreLabels
{
playerOneScore = 0;
playerTwoScore = 0;
}
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self wordsPerLineInfoShowAlert];
[self startGameTimer];
}
-(void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
[_gameTimer invalidate];
}
-(void)quitPressed:(id)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)startGameTimer
{
[_gameTimer invalidate];
_gameTimer = [NSTimer scheduledTimerWithTimeInterval:STEP_DURATION target:self selector:#selector(step:) userInfo:nil repeats:YES];
}
#pragma mark Game setup
/*
* Some maths to calculate a new starting direction
* By choosing mid left/right part of the unit circle
* we avoid getting straight up/down directions
*/
-(void)resetBallDirection
{
float randomUnity = arc4random_uniform(100)/100.0;
int horizontalDirection = (arc4random() % 2 ? 1 : -1);
float angle = M_PI_4 + randomUnity * M_PI_2;
float direction = horizontalDirection * angle;
dirX = sin(direction);
dirY = cos(direction);
}
-(void)resetBoardForNewRound
{
speed = self.view.frame.size.width / 50.0;
[self resetBallDirection];
[_gameTimer invalidate];
[UIView animateWithDuration:RESET_BALL_ANIMATION_DURATION animations:^{
self.ball.center = CGPointMake(self.view.bounds.size.width / 2.0, self.view.bounds.size.height / 2.0);
} completion:^(BOOL finished){
[self startGameTimer];
}];
[self enlargeAnimation:self.ball];
}
-(void)updatePlayerScoreLabels
{
self.playerOneScoreLabel.text = [NSString stringWithFormat:#"%d",playerOneScore];
self.playerTwoScoreLabel.text = [NSString stringWithFormat:#"%d",playerTwoScore];
}
#pragma mark Paddle handling
- (IBAction)paddlePanned:(UIPanGestureRecognizer*)recognizer {
UIView *paddleWrapper = recognizer.view;
UIView *paddle = [[paddleWrapper subviews] lastObject];
switch([recognizer state]) {
case UIGestureRecognizerStateBegan: {
paddle.backgroundColor = UIColor.whiteColor;
}
break;
case UIGestureRecognizerStateChanged: {
CGPoint position = [recognizer locationInView:self.view];
CGFloat haldPaddleHeight = paddleWrapper.frame.size.height / 2.0;
CGPoint newCenter = paddleWrapper.center;
newCenter.y = position.y;
newCenter.y = MAX(haldPaddleHeight, newCenter.y);
newCenter.y = MIN(self.view.bounds.size.height - haldPaddleHeight, newCenter.y);
paddleWrapper.center = newCenter;
}
break;
case UIGestureRecognizerStateEnded: {
paddle.backgroundColor = UIColor.grayColor;
}
break;
default:
break;
}
}
#pragma mark Game loop
/*
* Game loop
* - Moves the ball and checks for obstacles
*/
- (void)step:(NSTimer*)timer
{
speed += 0.05;
[self checkForBallLevingSide];
CGPoint newCenter = self.ball.center;
CGFloat ballRadius = self.ball.frame.size.height / 2.0;
newCenter.x += dirX * speed;
newCenter.y += dirY * speed;
CGFloat upperEdge = ballRadius;
CGFloat bottomEdge = self.view.bounds.size.height - ballRadius;
// Bounce ball of top/bottom walls
if (newCenter.y <= upperEdge) {
dirY = ABS(dirY);
newCenter.y = upperEdge;
} else if (newCenter.y >= bottomEdge) {
dirY = -ABS(dirY);
newCenter.y = bottomEdge;
}
[UIView animateWithDuration:STEP_DURATION animations:^{
self.ball.center = newCenter;
}];
}
-(BOOL)didBallHitPaddle:(UIView *)paddle withinLimit:(CGFloat)limit
{
if (CGRectIntersectsRect(paddle.frame, self.ball.frame)){
[self deflectBallFromPaddle:paddle];
CGRect ballFrame = self.ball.frame;
ballFrame.origin.x = limit;
self.ball.frame = ballFrame;
return YES;
} else
return NO;
}
-(void)checkForBallLevingSide
{
float limitLeft = MARGIN_WHERE_BALL_IS_LEAVING;
float limitRight = self.view.bounds.size.width - self.ball.frame.size.width - MARGIN_WHERE_BALL_IS_LEAVING;
CGRect ballFrame = self.ball.frame;
CGFloat ballX = ballFrame.origin.x;
if (ballX < limitLeft) {
if (![self didBallHitPaddle:self.playerOne.superview withinLimit:limitLeft])
[self playerDidMiss:kPlayerOne];
}else if (ballX > limitRight) {
if (![self didBallHitPaddle:self.playerTwo.superview withinLimit:limitRight])
[self playerDidMiss:kPlayerTwo];
}
}
/*
* Calculates new dirX and dirY after the bounce.
* The longer from the paddle's middle the bigger the result angle gets. (Pong style)
*/
-(void)deflectBallFromPaddle:(UIView *)paddle
{
dirX *= -1;
CGFloat diff = self.ball.center.y - paddle.center.y;
float p = diff / paddle.frame.size.height * 2.0f;
dirY += p * 0.5;
}
-(void)playerDidMiss:(kPlayer)player
{
if (player == kPlayerOne) {
playerTwoScore++;
[self victoryShake:self.playerTwo];
[self enlargeAnimation:self.playerTwoScoreLabel];
}
else if (player == kPlayerTwo) {
playerOneScore++;
[self victoryShake:self.playerOne];
[self enlargeAnimation:self.playerOneScoreLabel];
}
[self resetBoardForNewRound];
[self updatePlayerScoreLabels];
}
-(void)moveComputerPaddle
{
UIView *paddle = self.playerOne.superview;
CGPoint cpuCenter = paddle.center;
CGFloat diff = self.ball.center.y - paddle.center.y;
CGFloat movement = MIN((int)cpuSkill, ABS(diff));
movement *= diff > 0 ? 1 : -1;
cpuCenter.y += movement;
[UIView animateWithDuration:0.1 animations:^{
self.playerOne.superview.center = cpuCenter;
} completion:^(BOOL b) {
[self moveComputerPaddle];
}];
}
#pragma mark Animation
-(void)victoryShake:(UIView *)view
{
CAKeyframeAnimation * anim = [ CAKeyframeAnimation animationWithKeyPath:#"transform" ] ;
anim.values = [ NSArray arrayWithObjects:
[ NSValue valueWithCATransform3D:CATransform3DMakeTranslation(0.0f, -20.0f, 0.0f) ],
[ NSValue valueWithCATransform3D:CATransform3DMakeTranslation(0.0f, 20.0f, 0.0f) ],
nil ] ;
anim.autoreverses = YES ;
anim.repeatCount = 4.0f ;
anim.duration = 0.07f ;
[view.layer addAnimation:anim forKey:nil];
}
-(void)enlargeAnimation:(UIView *)view
{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:#"transform"];
animation.fromValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(1.0, 1.0, 1.0)];
animation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(3.0, 3.0, 1.0)];
[animation setDuration:RESET_BALL_ANIMATION_DURATION * 0.5];
animation.repeatCount = 1.0f ;
[animation setAutoreverses:YES];
[view.layer addAnimation:animation forKey:nil];
}
#end
I've simply tried changing the number where it states #define CPU_SkILL and again #"cpuSkill" defaultValue:#"20"];, but I've had no luck with changing the number in any direction.
Any ideas?
Thank you in advance.
The cpuSkill variable controls the movement of the CPU-controlled paddle:
CGFloat movement = MIN((int)cpuSkill, ABS(diff));
So maybe the cpuSkill is higher than intended in every situation. Try much lower values or make some random little adjustment to movement after the calculation.
Also, you should ABS() the cpuSkill to avoid perfect moving when negative moving.

What will be the best approach implementing infinite/repeating scrolling world in SpriteKit?

While moving the character it must stay inside a rectangle centred on the screen and all other game objects must scroll.
But as you get to the edge of the world it must repeat.
The characters can move in any direction.
You have to divide the world in 3 sections. Section 1 and 3 must be identical. If you reach the end of the world (Section 3) you can switch back to section 1.
http://www.youtube.com/watch?v=-FX-tFks5pg
-(id)initWithSize:(CGSize)size {
if (self = [super initWithSize:size]) {
_background = [SKSpriteNode spriteNodeWithImageNamed:#"background"];
_background.anchorPoint = CGPointMake(0, 0);
_background.name = #"background";
_background.position = CGPointMake(0, 0);
[self addChild:_background];
}
-(void)update:(CFTimeInterval)currentTime {
/* Called before each frame is rendered */
if (_lastUpdateTime) {
_deltaTime = currentTime - _lastUpdateTime;
} else {
_deltaTime = 0;
}
_lastUpdateTime = currentTime;
if (_deltaTime > 1) {
_deltaTime = 1.0 / 60.0;
}
[self enumerateChildNodesWithName:#"background" usingBlock:^(SKNode *node, BOOL *stop) {
node.position = CGPointMake(node.position.x - backgroundMoveSpeed * _deltaTime, node.position.y);
if (node.position.x < - (node.frame.size.width + 100)) {
[node removeFromParent];
}
}];
if (_background.position.x < -bound) {
//bound = 500
SKSpriteNode *temp = [SKSpriteNode spriteNodeWithImageNamed:#"background"];
temp.anchorPoint = CGPointMake(0, 0);
temp.name = #"background";
temp.position = CGPointMake(_background.position.x + _background.frame.size.width, 0);
[self addChild:temp];
_background = temp;
}
the background image's size is 2048x640, so you should change the bound according to your background image's size.

NSMutableArray addsubview UIImageView when is in Event

My images do not appear in my UIImageView when i am in event, in my viewDidLoad no problem.
(void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event
{
if ( event.subtype == UIEventSubtypeMotionShake )
{
int i;
int r;
for ( i = 1 ; i <= 5 ; )
{
r = (arc4random()%NbrCells) + 1;
if (GridCell[r].hidden == NO)
{
// View position.
CGFloat OriginX = GridCell[r].frame.origin.x;
CGFloat OriginY = GridCell[r].frame.origin.y;
CGFloat Height = GridCell[r].frame.size.height;
CGFloat Whidth = GridCell[r].frame.size.width;
[GridCell[r] removeFromSuperview];
GridCell[r] = nil;
GridCell[r] = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"background.png"]];
GridCell[r].frame = CGRectMake(OriginX, OriginY, Whidth, Height);
GridCell[r].hidden = NO;
[self.MyImage1 addSubview:GridCell[r]];
// [MyArray[r] addObject:[NSNumber numberWithInt:NO]];
i++;
sleep(1);
}
}
NSLog(#"Event stop, number delete = %d", i - 1);
}
if ( [super respondsToSelector:#selector(motionEnded:withEvent:)] )
[super motionEnded:motion withEvent:event];
return;
}
Many Thanks.
Alan10977.

transform image when it hits the edge of the screen in iOS

I have 10 fireflies that I make "fly" around the screen using the code below.
The code also serves to keep the fireflies on the screen.
- (void)viewDidLoad
{
[super viewDidLoad];
NSArray *blueArray = [NSArray array];
blueArray = [[NSArray alloc] initWithObjects:
[UIImage imageNamed:#"blue1.png"],
[UIImage imageNamed:#"blue2.png"], nil];
blue.animationImages = blueArray;
blue.animationDuration = 0.20;
blue.animationRepeatCount = -1;
[blue startAnimating];
bluepos =CGPointMake(2.0, 1.5);
}
-(void) someMethod {
endingAnimationTimer = [NSTimer scheduledTimerWithTimeInterval:(0.03) target:self selector:#selector(makeFly) userInfo:nil repeats:YES];
}
-(void) makeFly {
blue.center = CGPointMake(blue.center.x+bluepos.x, blue.center.y+bluepos.y);{
if(blue.center.x > 480 || blue.center.x <0)
bluepos.x = -bluepos.x;
if(blue.center.y > 320 || blue.center.y <0)
bluepos.y = -bluepos.y;
}
}
The "flying" works great except that when the fireflies hit the edge of the screen and reverse direction to keep them on the screen the firefly image itself is still "facing" the othe direction so it looks like they are flying backwards half the time.
I want to set it up so that when the fireflies hit the edge of the screen they reverse direction AND the image itself is reversed.
I tried this:
In .h
#property (nonatomic, assign) BOOL blueIsFacingRight;
In .m
#synthesize blueIsFacingRight;
-(void) makeFly {
blue.center = CGPointMake(blue.center.x+bluepos.x, blue.center.y+bluepos.y); {
if(blue.center.x > 480 ) {
if (blueIsFacingRight == YES) {
blue.transform = CGAffineTransformMakeScale(-1, 1);
blueIsFacingRight = NO;
}
bluepos.x = -bluepos.x;
}
if(blue.center.x <0) {
bluepos.x = -bluepos.x;
if (blueIsFacingRight == NO) {
blue.transform = CGAffineTransformMakeScale(1, 1);
blueIsFacingRight = YES;
}
}
if(blue.center.y > 320 )
bluepos.y = -bluepos.y;
if( blue.center.y <0)
bluepos.y = -bluepos.y;
}
}
I thought this would work but the image does not reverse when it hits the "wall"
Can anyone explain why this does not work and if there is a better why to accomplish the effect im looking for?
You are setting the transform X value to -1 in both cases. When its facing right you should set transform like this CGAffineTransformMakeScale(1, 1);
blue.center = CGPointMake(blue.center.x+bluepos.x, blue.center.y+bluepos.y); {
if(blue.center.x > 480 ) {
if (blueIsFacingRight == YES) {
blue.transform = CGAffineTransformMakeScale(-1, 1);
blueIsFacingRight = NO;
}
bluepos.x = -bluepos.x;
}
if(blue.center.x <0) {
bluepos.x = -bluepos.x;
if (blueIsFacingRight == NO) {
blue.transform = CGAffineTransformMakeScale(1, 1);
blueIsFacingRight = YES;
}
}
**blue.transform =CGAffineTransformIdentity;**
THe above was in my makeFly method with a bunch of other stuff above where I was reversing the image so I was undoing the change the very next time the method was called ( 0.03 later)
Man I feel stupid

multiple pinch gestures on different images on the same UIView

I am using Xcode 4.4 and target is iOS 5.
As on the title, I would like to create multiple pinch gestures for different images. I use two type of images. One is set as a background and the 2nd type of image is a stamp that is pasted on the image that is set as background. To do this I am using UIGestureRecognizer. Everything is fine until I paste the stamp type of image and try to zoom that image. I can zoom but when I zoom the image, the image has has been set as background zooms as well.
With the code below, I can paste different images (stamp type), tap and drag them individually but not when I try all the content zooms as well. Why isn't working?
Thank you in advance
- (void)viewDidLoad{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
NSLog(#"menuListType=%# ; menuID=%#", self.category.menuListType ,self.menu.menuID);
UIImage *aImage;
NSString *imagepath = [NSString stringWithFormat:#"%#%#",[FileUtility getPDFImageFolderPath], self.menu.imageID];
if (self.menu.imageID == nil || [self.menu.imageID isEqualToString:#""]) {
// self.canvasView.image = [UIImage imageNamed:#"NotExistFile.jpg"];
aImage = [UIImage imageNamed:#"NotExistFile.jpg"];
} else {
// self.canvasView.image = [UIImage imageWithContentsOfFile:imagepath];
aImage = [UIImage imageWithContentsOfFile:imagepath];
// self.canvasView = [[[UIImageView alloc] initWithImage:self.canvasView.image] autorelease];
}
// Choose image base and set as background
if ([self.category.menuListType isEqualToString:#"4"]) {
//set size
int imageW = aImage.size.width;
int imageH = aImage.size.height;
float scale = (imageW > imageH ? 500.0f/imageH : 500.0f/imageW);
CGSize resizedSize = CGSizeMake(imageW * scale, imageH * scale);
UIGraphicsBeginImageContext(resizedSize);
[aImage drawInRect:CGRectMake(0, 0, resizedSize.width, resizedSize.height)];
UIImage *resizedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.canvasView.contentMode = UIViewContentModeTop;
self.canvasView.image = resizedImage;
if (self.menu.imageID == nil || [self.menu.imageID isEqualToString:#""]) {
} else {
self.canvasView = [[[UIImageView alloc] initWithImage:self.canvasView.image] autorelease];
}
} else {
// Paste image and set as background
UIImage *captureImage;
NSString *capturepath = [NSString stringWithFormat:#"%#%#",[FileUtility getPDFImageFolderPath], #"capture.png"];
if ([FileUtility fileExist:capturepath]) {
captureImage = [UIImage imageWithContentsOfFile:capturepath];
} else {
captureImage = [UIImage imageNamed:#"NotExistFile3.png"];
}
self.canvasView.contentMode = UIViewContentModeTop;;
self.canvasView.image = captureImage;
self.canvasView = [[[UIImageView alloc] initWithImage:self.canvasView.image] autorelease];
// Prepare Gestures
iViewsTapidx = 0;
iViewsDblTapidx = 0;
ivMax = sizeof(iViews) / sizeof(iViews[0]);
isTaped = NO;
isDblTaped = NO;
_width = 100;
// Initialization code
// Single tap
UITapGestureRecognizer *tapg =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(tapAction:)];
[self.itemView addGestureRecognizer:tapg];
// Double tap
UITapGestureRecognizer *doubleTap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(doubleTapAction:)];
doubleTap.numberOfTapsRequired = 2;
[self.itemView addGestureRecognizer:doubleTap];
// longPress(長押し)
UILongPressGestureRecognizer *longPress =
[[UILongPressGestureRecognizer alloc] initWithTarget:self
action:#selector(longPressAction:)];
[self.itemView addGestureRecognizer:longPress];
// drag
UIPanGestureRecognizer *pan =
[[UIPanGestureRecognizer alloc] initWithTarget:self
action:#selector(panAction:)];
[self.itemView addGestureRecognizer:pan];
//pinch
UIPinchGestureRecognizer *pinchGestureRognizer = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:#selector(handlePinch:)];
[self.itemView addGestureRecognizer:pinchGestureRognizer];
// Stamp Image
int i = 0;
CGPoint tapPoint = CGPointMake(self.canvasView.center.x, self.canvasView.center.y);
int parcent = aImage.size.width / _width; // Prepare image to paste
// Show stamp
*(iViews+i) = [[UIImageView alloc] initWithImage:aImage];
(*(iViews+i)).frame = CGRectMake(tapPoint.x - aImage.size.width/parcent/2,
tapPoint.y - aImage.size.height/parcent/2,
aImage.size.width/parcent,
aImage.size.height/parcent);
(*(iViews+i)).tag = i+1;
[self.itemView addSubview:*(iViews+i)];
iViewsTapidx = i;
isTaped = YES;
self.itemView.userInteractionEnabled = YES;
}
[self showAnimation];
}
// tap
-(void)tapAction:(UITapGestureRecognizer *) sender{
CGPoint tapPoint = [sender locationInView:self.itemView];
NSLog(#">>>tap x=%.2f, y=%.2f", tapPoint.x, tapPoint.y);
int i =0;
isTaped = NO;
for (i = 0; i < ivMax; i++) {
if (CGRectContainsPoint((*(iViews+i)).frame, tapPoint)) {
isTaped = YES;
iViewsTapidx = i;
NSLog(#"i = %d", i);
break;
}
}
}
// doubleTap
-(void)doubleTapAction:(UITapGestureRecognizer *) sender{
NSLog(#">>>doubleTap");
CGPoint tapPoint = [sender locationInView:self.itemView];
isTaped = NO;
isDblTaped = NO;
int i =0;
for (i = 0; i < ivMax; i++) {
if (CGRectContainsPoint((*(iViews+i)).frame, tapPoint)) {
isDblTaped = YES;
iViewsDblTapidx = i;
break;
}
}
// remove
if (isDblTaped) {
NSLog(#"remove %d", i);
(*(iViews+i)).tag = 0;
[*(iViews+i) removeFromSuperview];
}
}
// longPress
- (void)longPressAction:(UILongPressGestureRecognizer *) sender{
if ([sender state] == UIGestureRecognizerStateBegan) {
NSLog(#">>>longPress 1");
}else if ([sender state] == UIGestureRecognizerStateEnded) {
CGPoint tapPoint = [sender locationInView:self.itemView];
NSLog(#">>>longPress 2 x=%.2f, y=%.2f", tapPoint.x, tapPoint.y);
int i =0;
for (i = 0; i < ivMax; i++) {
NSLog(#"i = %d", i);
if ((*(iViews+i)).tag == 0) {
break;
}
}
if (i < ivMax) {
//Stamp imapge
UIImage *stampImage;
NSString *imagepath = [NSString stringWithFormat:#"%#%#",[FileUtility getPDFImageFolderPath], self.menu.imageID];
if (self.menu.imageID == nil || [self.menu.imageID isEqualToString:#""]) {
stampImage = [UIImage imageNamed:#"NotExistFile.jpg"];
} else {
stampImage = [UIImage imageWithContentsOfFile:imagepath];
}
int parcent = stampImage.size.width / _width; // Set stamp image
//Sow stamp image
*(iViews+i) = [[UIImageView alloc] initWithImage:stampImage];
(*(iViews+i)).frame = CGRectMake(tapPoint.x - stampImage.size.width/parcent/2,
tapPoint.y - stampImage.size.height/parcent/2,
stampImage.size.width/parcent,
stampImage.size.height/parcent);
(*(iViews+i)).tag = i+1;
[self.itemView addSubview:*(iViews+i)];
iViewsTapidx = i;
isTaped = YES;
}
}
}
// drag
- (void)panAction:(UIPanGestureRecognizer *) sender{
NSLog(#">>>pan");
if (isTaped) {
CGPoint p = [sender translationInView:self.itemView];
CGPoint movePoint = CGPointMake((*(iViews+iViewsTapidx)).center.x + p.x,
(*(iViews+iViewsTapidx)).center.y + p.y);
(*(iViews+iViewsTapidx)).center = movePoint;
// NSLog(#">>>pan x=%.2f, y=%.2f --> x=%.2f, y=%.2f", p.x, p.y, movePoint.x, movePoint.y);
NSLog(#">>>pan x=%.2f, y=%.2f", p.x, p.y);
[sender setTranslation:CGPointZero inView:self.itemView];
}
}
-(void) handlePinch:(UIGestureRecognizer *) sender {
UIPinchGestureRecognizer *pinchGesture = (UIPinchGestureRecognizer *) sender;
if (pinchGesture.state == UIGestureRecognizerStateBegan || pinchGesture.state == UIGestureRecognizerStateChanged) {
//UIView *view = pinchGesture.view;
// UIView *view = self.itemView;
self.itemView.transform = CGAffineTransformScale(self.itemView.transform, pinchGesture.scale, pinchGesture.scale);
pinchGesture.scale = 1;
NSLog(#"zoom");
}
}
You will have to add Gesture Recognizer on Uiimageview, Look here for doing so : UIGestureRecognizer on UIImageView
Yet another way is to use UIScrolliew as your container instead of UIView and use the - (UIView*)viewForZoomingInScrollView:(UIScrollView *)aScrollView {
return imageView;
}
here imageView is the image you want to zoom,this will zoom that only image you are pinching its tested and works fine.

Resources