图片缩放代码

//

//  TouchMoveScaleView.h

//  TouchMoveScaleDemo

//

//  Created by jimney on 07/05/10.

//  Copyright 2010 OpenSource. All rights reserved.

//Welcome to my HomePage In CocoaChina:http://www.cocoachina.com/bbs/u.php?action=topic

 

#import <UIKit/UIKit.h>

#import <QuartzCore/QuartzCore.h>

 

/*

 *类说明

 *此类主要实现在触摸过程中,实时控制视图动画的变换

 *一点触摸移动视图,两点触摸缩放视图的动作

 *实现的主要思路:因为动画的过程是连贯的,在变化的过程中,

 *不能直接去获得过程中的值,不连续的动画控制比较难

 *因为虽然图片视图的大小或者位置发生改变时,但是视图本身的数据并没变化

 *所以采用人为跟踪动画变换过程,将此时所表现在视图界面中的动画变化后的虚拟值,

 *保存在相应的变量中

 */

 

//!补充:虚拟机中使用多点触摸,按住ALT键,可显示两个触摸点,点击移动即可看到效果

 

@interface TouchMoveScaleView : UIView 

{

 

UIImage*originImage;

UIImageView*imageView;

 

CGFloatimageWidth;

CGFloatimageHeight;

 

// 跟踪图片在屏幕显示区域的原点位于整个图片的位置

CGPointmaskOriginPoint;

// 跟踪缩放后图片相对于原始图片的比例大小

CGSizescaleSize;

 

 

// 动画移动及缩放图像

CGPointfirstStartTouchPosition;

CGPointsecondStartTouchPosition;

CGFloatinitialDistance;

 

// 动画放缩后,原始图片变化比例

CGFloatanimationFinalScal;

 

}

@property(nonatomic)CGPointmaskOriginPoint;

@property(nonatomic,retain)UIImage*originImage;

@property(nonatomic)BOOLisDragAble;

 

// 初始化视图

- (id)initWithFrame:(CGRect)frame image:(UIImage*)image;

 

// 根据touch 的亮点距离变化,改变图片的大小

- (CGFloat)scaleAmount: (CGFloat)delta;

 

// 计算两个点之间的距离

- (CGFloat)distanceBetweenTwoPoints:(CGPoint)fromPoint toPoint:(CGPoint)toPoint;

 

@end

 
 

//

//  TouchMoveScaleView.m

//  TouchMoveScaleDemo

//

//  Created by jimney on 07/05/10.

//  Copyright 2010 OpenSource. All rights reserved.

//Welcome to my HomePage In CocoaChina:http://www.cocoachina.com/bbs/u.php?action=topic

 

#import "TouchMoveScaleView.h"

 

@implementation TouchMoveScaleView

@synthesize maskOriginPoint;

@synthesize originImage;

/*

 *通过传入视图大小和原始图像,初始化视图

 *同时设置图片动画初始数据

 */

- (id)initWithFrame:(CGRect)frame image:(UIImage*)image

{

    if ((self = [superinitWithFrame:frame])) 

{

imageWidth= image.size.width;

imageHeight= image.size.height;

//显示图像视图

originImage=   [[UIImagealloc] initWithCGImage:image.CGImage];

imageView=[[UIImageViewalloc] initWithImage:originImage];

imageView.frame = frame;

[selfaddSubview:imageView];

 

// 使图片视图支持交互和多点触摸

[imageViewsetUserInteractionEnabled:YES];

[imageViewsetMultipleTouchEnabled:YES];

 

// 移动初始距离

initialDistance = -1;

 

// 动画缩放比例数据

// 缩放后可见动画视图的原始位置坐标

maskOriginPoint.x=maskOriginPoint.y = 0;

 

// 缩放后可见动画视图的大小

scaleSize=   originImage.size;

 

// 缩放后可见动画视图的相对于原始图片比例

animationFinalScal=1.0;

 

// 动画缩放控制标志

//imageView.transform = CGAffineTransformIdentity;

    }

    returnself;

}

 

// 定义一个静态全局变量,跟踪两次touch

static UITouch *g_firstTouch = nil;

static UITouch *g_secondTouch = nil;

/*

 *跟踪记录触摸开始的事件,并设置触摸相关的数据

 */

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event

{

// touch move image in view

{

// 两点先后触摸和同时触摸

if([touches count] < 2)

{

// first time single touch

if (g_firstTouch == nil && g_secondTouch == nil)

{

g_firstTouch= [[touches allObjects] objectAtIndex:0];

firstStartTouchPosition= [g_firstTouchlocationInView:imageView];

initialDistance= -1;

}

else// 当有个点已经在屏幕时,设置第二点触摸点 

{

if(g_firstTouch == nil)

{

g_firstTouch= [[touches allObjects] objectAtIndex:0];

firstStartTouchPosition= [g_firstTouchlocationInView:imageView];

 

}

else

if(g_secondTouch == nil)

{

g_secondTouch= [[touches allObjects] objectAtIndex:0];

secondStartTouchPosition= [g_secondTouchlocationInView:imageView];

 

}

 

initialDistance= [selfdistanceBetweenTwoPoints:firstStartTouchPosition 

toPoint:secondStartTouchPosition];

}

 

}

else//if([touches count] == 2)

{

// multi touch

g_firstTouch= [[touches allObjects] objectAtIndex:0];

g_secondTouch= [[touches allObjects] objectAtIndex:1];

 

 

firstStartTouchPosition= [g_firstTouchlocationInView:imageView];

secondStartTouchPosition= [g_secondTouchlocationInView:imageView];

 

initialDistance= [selfdistanceBetweenTwoPoints:firstStartTouchPosition 

toPoint:secondStartTouchPosition];

 

}

#ifdef DEBUG

//NSLog(@"g_firstTouch = %@", g_firstTouch);

//NSLog(@"g_secondTouch = %@", g_secondTouch);

//NSLog(@"firstStartTouchPosition = (%f, %f)", firstStartTouchPosition.x, firstStartTouchPosition.y);

//NSLog(@"firstStartTouchPosition = (%f, %f)", secondStartTouchPosition.x, secondStartTouchPosition.y);

//NSLog(@"initialDistance = %f", initialDistance);

#endif

}

}

/*

 *在触摸移动事件中,根据一点触摸,移动视图

 *两点同时触摸,视图做缩放变化

 */

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event

{

{

UITouch *touch1 = [[touches allObjects] objectAtIndex:0];

 

if ([touches count] == 1 && (g_firstTouch == nil || g_secondTouch == nil))// 只有一个点在move

{

CGPoint vectorPoint;

if (touch1 == g_firstTouch)

{

//NSLog(@"firstTouch touch move!");

CGPoint pos = [g_firstTouchlocationInView:imageView];

vectorPoint = CGPointMake(pos.x - firstStartTouchPosition.x, pos.y - firstStartTouchPosition.y);

}

elseif (touch1 == g_secondTouch)

{

//NSLog(@"second Touch touch move!");

CGPoint pos = [g_secondTouchlocationInView:imageView];

vectorPoint = CGPointMake(pos.x - secondStartTouchPosition.x, pos.y - secondStartTouchPosition.y);

}

else

{

return;

}

 

// 改变maskOriginPoint

// 当图片放大后,在屏幕上滑动距离的实际值改变,应该是* animationAllScal,这很重要

maskOriginPoint.x -= vectorPoint.x * animationFinalScal;

maskOriginPoint.y -= vectorPoint.y * animationFinalScal;

// 单点触摸移动,做动画移动变换

imageView.transform = CGAffineTransformTranslate(imageView.transform, vectorPoint.x,  vectorPoint.y);

return;

}

 

if ((initialDistance > 0) && ([touches count] > 1)) 

{

UITouch *touch2 = [[touches allObjects] objectAtIndex:1];

CGFloat currentDistance = [selfdistanceBetweenTwoPoints:[touch1 locationInView:imageView

toPoint:[touch2 locationInView:imageView]];

CGFloat movement = currentDistance - initialDistance;

CGFloat scale = [selfscaleAmount: movement];

// 两点触摸移动,做动画缩放

imageView.transform = CGAffineTransformScale(imageView.transform, scale, scale);

 

// x,y 缩放为整体大小变化的一半

// 遮罩区域原始位置准确

maskOriginPoint.x += scaleSize.width * (scale - 1) /2;

maskOriginPoint.y += scaleSize.height * (scale - 1) /2;

// 缩放的计算没问题

// 相对原始图片变化

animationFinalScal = imageView.transform.a;

scaleSize.width  = animationFinalScal * originImage.size.width;

scaleSize.height = animationFinalScal * originImage.size.height;

//NSLog(@"move: scaleSize.width = %f scaleSize.height = %f\n", scaleSize.width, scaleSize.height);

 

 

//当缩放图像的宽度小于屏幕时,不能缩放 

#define SCALE_BACK

#ifdef SCALE_BACK

//缩放后的图像不小于屏幕

CGRect screenRect = [[UIScreenmainScreen] applicationFrame];

BOOL isScaled = NO;

scale = 1.0;

if(scaleSize.width >= scaleSize.height)

{

//NSLog(@"scaleSize.width >= scaleSize.height");

//NSLog(@"scaleSize.width = %f scaleSize.height = %f\n", scaleSize.width, scaleSize.height);

 

if(scaleSize.width < screenRect.size.width)

{

scale= screenRect.size.width / scaleSize.width ;

isScaled= YES;

}

}

else

{

 

if(scaleSize.height < screenRect.size.height)

{

scale= screenRect.size.height / scaleSize.height ;

isScaled= YES;

}

}

// 需要恢复整屏幕大小

if (isScaled)

{

imageView.transform = CGAffineTransformScale(imageView.transform, scale, scale);

// x,y 缩放为整体大小变化的一半

// 遮罩区域原始位置准确

maskOriginPoint.x += scaleSize.width * (scale - 1) /2;

maskOriginPoint.y += scaleSize.height * (scale - 1) /2;

// 缩放的计算没问题

// 相对原始图片变化,获得当前视图的缩放后的比例

animationFinalScal = imageView.transform.a;

scaleSize.width    = animationFinalScal * originImage.size.width;

scaleSize.height   = animationFinalScal * originImage.size.height;

 

}

#endif

 

 

}

}

}

/*

 * 触摸结束,重设事件相关数据

 */

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

{

{

// 重设touch移动的距离

initialDistance= -1;

// 重设touch事件变量

g_firstTouch= nil ;

g_secondTouch= nil;

//当只有一次touch事件时

if ([touches count] < 2 )

{

if ([[touches allObjects] objectAtIndex:0] == g_firstTouch

{

g_firstTouch = nil;

}

elseif ([[touches allObjects] objectAtIndex:0] == g_secondTouch

{

g_secondTouch = nil;

}

 

}

else  

{

if ([[touches allObjects] objectAtIndex:0] == g_firstTouch

{

// 以后用for循环替代,更好

g_firstTouch = nil;

g_secondTouch = nil;

}

}

 

// 在结束,动画恢复相应的移动或者缩放

// 当图片移除边界,恢复

// 当图片缩放到一定大小,恢复,此功能以后要实现

// maskImageView.size

// maskOriginPoint

// scaleSize

 

CGContextRef context = UIGraphicsGetCurrentContext();

[UIViewbeginAnimations:nilcontext:context];

[UIViewsetAnimationCurve:UIViewAnimationCurveEaseOut];

[UIViewsetAnimationDuration:0.5f];

 

CGRect screenRect = [[UIScreenmainScreen] applicationFrame];

CGRectrect = imageView.frame;

 

// 下面为动画缩放超过所设置大小,做动画恢复

// 注意:下面的效果没有实现,有问题,你可以修改

//#define SCALE_BACK

#ifdef SCALE_BACK

//缩放后的图像不小于屏幕

BOOL isScaled = NO;

CGFloat scale = 1.0;

if(scaleSize.width >= scaleSize.height)

{

//NSLog(@"scaleSize.width >= scaleSize.height");

//NSLog(@"scaleSize.width = %f scaleSize.height = %f\n", scaleSize.width, scaleSize.height);

 

if(scaleSize.width < screenRect.size.width)

{

scale= screenRect.size.width / scaleSize.width ;

isScaled= YES;

}

}

else

{

 

if(scaleSize.height < screenRect.size.height)

{

scale= screenRect.size.height / scaleSize.height ;

isScaled= YES;

}

}

// 需要恢复整屏幕大小

if (isScaled)

{

// x,y 缩放为整体大小变化的一半

// 遮罩区域原始位置准确

maskOriginPoint.x += scaleSize.width * (scale - 1) /2;

maskOriginPoint.y += scaleSize.height * (scale - 1) /2;

// 缩放的计算没问题

// 相对原始图片变化

animationFinalScal*= scale;

scaleSize.width= animationFinalScal * originImage.size.width;

scaleSize.height= animationFinalScal * originImage.size.height;

rect.size= scaleSize;

}

#endif

 

// 此值为判断图片右边和下边到屏幕距离

CGFloat deltaX = (scaleSize.width  - maskOriginPoint.x) -  screenRect.size.width;

//CGFloat deltaY = (scaleSize.height - maskOriginPoint.y) -  screenRect.size.height;

#ifdef DEBUG

//NSLog(@"==========================================================\n");

//NSLog(@"animationFinalScal = %f\n", animationFinalScal);

//NSLog(@"mainscreen move dist = %f\n", animationFinalScal * screenRect.size.width);

//NSLog(@"maskOriginPoint.x = %f, maskOriginPoint.y = %f\n",maskOriginPoint.x, maskOriginPoint.y);

//NSLog(@"scaleSize.width = %f scaleSize.height = %f\n", scaleSize.width, scaleSize.height);

//NSLog(@"screenRealSize.width = %f screenRealSize.height = %f\n", screenRect.size.width, screenRect.size.height);

//NSLog(@"moveX = %f, moveY = %f\n", deltaX, deltaY);

#endif

 

// 移出右外

if(deltaX < 0)

{

//NSLog(@"right outside!\n");

rect.origin.x= -(scaleSize.width - screenRect.size.width);

maskOriginPoint.x=   scaleSize.width - screenRect.size.width;

}

// 优先右上对齐

// x小于零,表示移出左外

if (maskOriginPoint.x < 0)

{

//NSLog(@"left outside!\n");

rect.origin.x= 0;

maskOriginPoint.x= 0;

}

else// x > 0

{

if (rect.size.width < screenRect.size.width

{

//NSLog(@"up outside!\n");

rect.origin.x= 0;

maskOriginPoint.x= 0;

}

}

// y小于零,表示移出上外

if (maskOriginPoint.y < 0 )

{

//NSLog(@"up outside!\n");

rect.origin.y= 0;

maskOriginPoint.y= 0;

}

else// y > 0

{

if (rect.size.height < screenRect.size.height

{

//NSLog(@"up outside!\n");

rect.origin.y= 0;

maskOriginPoint.y= 0;

}

}

 

 

[imageViewsetFrame:rect];

[UIViewcommitAnimations]; 

 

//NSLog(@"maskOriginPoint.x = %f", maskOriginPoint.x);

//NSLog(@"animation end: scaleSize.width = %f scaleSize.height = %f\n", scaleSize.width, scaleSize.height);

 

}

}

 

/*

 *计算touch的两个点的距离

 */

- (CGFloat)distanceBetweenTwoPoints:(CGPoint)fromPoint toPoint:(CGPoint)toPoint 

{

 

float x = toPoint.x - fromPoint.x;

float y = toPoint.y - fromPoint.y;

 

returnsqrt(x * x + y * y);

}

 

/*

 *根据移动的距离,计算相应的缩放比例

 */

- (CGFloat)scaleAmount: (CGFloat)delta 

{

CGFloat pix = sqrt(self.bounds.size.width * self.bounds.size.height);

CGFloat scale = 1.0 + (delta / pix);

return scale;

}

 

/*

 *释放内存

 */

- (void) dealloc

{

[imageViewrelease];

[originImagerelease];

    [superdealloc];

}

@end

posted on 2012-11-15 18:01  无量少年  阅读(627)  评论(0编辑  收藏  举报

导航