「ios開発」ios画像を移動、ズームするサンプルプログラム
コード下記:
#import <UIKit/UIKit.h>
#import <QuartzCore/QuartzCore.h>
#import “NetworkHelperDelegate.h"
#import “CCImageViewDelegate.h"
#define MAX_SCALE 2.5
#define MIN_SCALE 1.0
typedef enum {
CCImageViewStyleSmall, //size初期化
CCImageViewStyleLarge //_imageLayerを計算
}CCImageViewStyle;
@interface CCImageView : UIControl<NSURLConnectionDataDelegate>
{
@private
CCImageViewStyle _style;
NSString *_imageUrl;
CAScrollLayer *_baseLayer;
CALayer *_imageLayer;
UIActivityIndicatorView *_indicatorView;
CATextLayer *_toastLayer;
}
@property (assign, nonatomic) id<CCImageViewDelegate> delegate;
– (id)initWithFrame:(CGRect)frame url:(NSString *)url style:(CCImageViewStyle)style;
– (void)startLoad;
– (void)stopLoad;
@end
#import “CCImageView.h"
@interface CCImageView ()
{
NSURLConnection *_conn;
NSMutableData *_imageData;
BOOL _isLoadEnded;
/* ズーム–移動 */
CGSize _originSize;
BOOL _canTranslateOrScroll;
double _startDisc;
CGFloat _currentScale;
CGPoint _originPoint; //移動開始位置を記録
CGPoint _startPoint; //移動開始
}
@end
@implementation CCImageView
– (id)initWithFrame:(CGRect)frame url:(NSString *)url style:(CCImageViewStyle)style
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
_imageUrl = url;
_style = style;
_isLoadEnded = NO;
_currentScale = 1.0f;
self.backgroundColor = [UIColor lightGrayColor];
_baseLayer = [CAScrollLayer layer];
_baseLayer.frame = self.bounds;
_baseLayer.scrollMode = kCAScrollBoth;
_baseLayer.masksToBounds = YES;
[self.layer addSublayer:_baseLayer];
//layer
_imageLayer = [CALayer layer];
_imageLayer.frame = self.bounds;
_imageLayer.backgroundColor = [UIColor clearColor].CGColor;
//ネットワークをロードする時ヒントを与える
_indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: _style == CCImageViewStyleLarge ? UIActivityIndicatorViewStyleWhiteLarge : UIActivityIndicatorViewStyleWhite];
_indicatorView.frame = _style == CCImageViewStyleLarge ? CGRectMake((_imageLayer.frame.size.width – 37) / 2.0, (_imageLayer.frame.size.height – 37) / 2.0 – 20, 37, 37) : CGRectMake((_imageLayer.frame.size.width – 20) / 2.0, (_imageLayer.frame.size.height – 20) / 2.0 – 10, 20, 20);
[_indicatorView startAnimating];
[_imageLayer addSublayer:_indicatorView.layer];
_toastLayer = [CATextLayer layer];
_toastLayer.string = @"loading…";
_toastLayer.fontSize = _style == CCImageViewStyleLarge ? 16 : 14;
_toastLayer.frame = CGRectMake((_imageLayer.frame.size.width – 60)/2.0, (_imageLayer.frame.size.height – 50)/2.0 + 25, 60, 20);
[_imageLayer addSublayer:_toastLayer];
[_baseLayer addSublayer:_imageLayer];
}
return self;
}
– (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];
if (_canTranslateOrScroll) {
NSArray *arrayTouches = [[event allTouches] allObjects];
if (arrayTouches.count == 1) {
//開始位置をクリック
_startPoint = [[arrayTouches objectAtIndex:0] locationInView:self];
_originPoint = _startPoint;
}else if (arrayTouches.count > 1) {
CGPoint point1 = [[arrayTouches objectAtIndex:0] locationInView:self];
CGPoint point2 = [[arrayTouches objectAtIndex:1] locationInView:self];
_startDisc = sqrt((point1.x – point2.x)*(point1.x – point2.x) + (point1.y – point2.y)*(point1.y – point2.y));
}
}
}
– (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesCancelled:touches withEvent:event];
_startDisc = 0;
}
– (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesMoved:touches withEvent:event];
if (_canTranslateOrScroll) {
NSArray *arrayTouches = [[event allTouches] allObjects];
if (arrayTouches.count == 1) {
CGPoint tempPoint = [[arrayTouches objectAtIndex:0] locationInView:self];
CGFloat moveX = tempPoint.x – _startPoint.x;
CGFloat moveY = tempPoint.y – _startPoint.y;
CGPoint oringinPoint = _imageLayer.position;
//30より大きい移動操作を行う
if (fabs(moveX) > 30 || fabs(moveY) > 30) {
_imageLayer.position = CGPointMake(oringinPoint.x + moveX, oringinPoint.y + moveY);
_startPoint = tempPoint;
}
}else if (arrayTouches.count > 1) {
//ズーム
CGPoint point1 = [[arrayTouches objectAtIndex:0] locationInView:self];
CGPoint point2 = [[arrayTouches objectAtIndex:1] locationInView:self];
double tempDisc = sqrt((point1.x – point2.x)*(point1.x – point2.x) + (point1.y – point2.y)*(point1.y – point2.y));
if (_startDisc == 0) {
_startDisc = tempDisc;
}
//ズーム率を計算
_currentScale += (tempDisc – _startDisc) / 100.0;
if (_currentScale < MAX_SCALE + 0.5) {
_imageLayer.bounds = CGRectMake(0, 0, _currentScale * _originSize.width, _currentScale * _originSize.height);
_startDisc = tempDisc;
}
}
}
}
– (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesEnded:touches withEvent:event];
_startDisc = 0;
if (_canTranslateOrScroll) {
NSArray *arrayTouches = [[event allTouches] allObjects];
if (arrayTouches.count == 1) {
//移動終了
CGPoint endPoint = [[arrayTouches objectAtIndex:0] locationInView:self];
CGFloat moveX = endPoint.x – _originPoint.x;
CGFloat moveY = endPoint.y – _originPoint.y;
if (moveX > 0 && _imageLayer.frame.origin.x > 0) {
_imageLayer.frame = CGRectMake(0, _imageLayer.frame.origin.y, _imageLayer.frame.size.width, _imageLayer.frame.size.height);
}
if (moveX < 0 && _imageLayer.frame.origin.x + _imageLayer.frame.size.width < _baseLayer.frame.size.width) {
_imageLayer.frame = CGRectMake(_baseLayer.frame.size.width – _imageLayer.frame.size.width, _imageLayer.frame.origin.y, _imageLayer.frame.size.width, _imageLayer.frame.size.height);
}
if (_imageLayer.frame.size.height > _baseLayer.frame.size.height) {
if (moveY < 0 && _imageLayer.frame.origin.y + _imageLayer.frame.size.height < _baseLayer.frame.size.height) {
_imageLayer.frame = CGRectMake(_imageLayer.frame.origin.x, _baseLayer.frame.size.height – _imageLayer.frame.size.height, _imageLayer.frame.size.width, _imageLayer.frame.size.height);
}
if (moveY > 0 && _imageLayer.frame.origin.y > 0) {
_imageLayer.frame = CGRectMake(_imageLayer.frame.origin.x, 0, _imageLayer.frame.size.width, _imageLayer.frame.size.height);
}
} else {
if (moveY > 0 && _imageLayer.frame.origin.y + _imageLayer.frame.size.height > _baseLayer.frame.size.height) {
_imageLayer.frame = CGRectMake(_imageLayer.frame.origin.x, _baseLayer.frame.size.height – _imageLayer.frame.size.height, _imageLayer.frame.size.width, _imageLayer.frame.size.height);
}
if (moveY < 0 && _imageLayer.frame.origin.y < 0) {
_imageLayer.frame = CGRectMake(_imageLayer.frame.origin.x, 0, _imageLayer.frame.size.width, _imageLayer.frame.size.height);
}
}
}
//スケーリングを判断
if (_currentScale > MAX_SCALE) {
_imageLayer.bounds = CGRectMake(0, 0, _originSize.width * MAX_SCALE, _originSize.height * MAX_SCALE);
_currentScale = MAX_SCALE;
}else if (_currentScale < MIN_SCALE) {
_imageLayer.bounds = CGRectMake(0, 0, _originSize.width, _originSize.height);
_currentScale = MIN_SCALE;
}
_startDisc = 0;
}
}
#pragma mark – NSURLConnectonDelegate
– (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
[self removeSubLayer];
_imageLayer.contents = (id)[UIImage imageNamed:@"anjisi"].CGImage;
}
– (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[_imageData appendData:data];
}
– (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
_isLoadEnded = YES;
[self removeSubLayer];
UIImage *image = [UIImage imageWithData:_imageData];
if (image) {
if (_style == CCImageViewStyleSmall) {
_imageLayer.contents = (id)image.CGImage;
[self addTarget:self action:@selector(clickAction) forControlEvents:UIControlEventTouchUpInside];
}else {
//成功した画像を取得
CGFloat tempScale = _baseLayer.frame.size.width / image.size.width;
_imageLayer.frame = CGRectMake((_baseLayer.frame.size.width – image.size.width * tempScale) / 2.0, (_baseLayer.frame.size.height – image.size.height * tempScale) / 2.0, image.size.width * tempScale, image.size.height * tempScale);
_originSize = CGSizeMake(_imageLayer.frame.size.width, _imageLayer.frame.size.height);
_imageLayer.contents = (id)image.CGImage;
_canTranslateOrScroll = YES;
}
}else {
_isLoadEnded = NO;
_imageLayer.contents = (id)[UIImage imageNamed:@"anjisi"].CGImage;
}
}
//画像をロードするための一般的な方法を提供
– (void)startLoad
{
_imageData = [NSMutableData data];
_imageUrl = [[_imageUrl stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]] stringByReplacingOccurrencesOfString:@" " withString:@"%20″];
_conn = [NSURLConnection connectionWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:_imageUrl] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:20] delegate:self];
}
– (void)stopLoad
{
if (_conn) {
[_conn cancel];
_conn = nil;
_imageData = nil;
}
}
#pragma mark – private
– (void)clickAction
{
if (_delegate && [_delegate respondsToSelector:@selector(imageClickAction:)]) {
[_delegate imageClickAction:self];
}
}
– (void)removeSubLayer
{
[_indicatorView stopAnimating];
[_indicatorView.layer removeFromSuperlayer];
[_toastLayer removeFromSuperlayer];
}
@end
//初期化
_mImageView = [[CCImageView alloc] initWithFrame:CGRectMake(0, 32, SCREEN_WIDTH, SCREEN_HEIGHT – 76) url:[_mDict objectForKey:@"Planeurl"] style:CCImageViewStyleLarge];
[_baseView addSubview:_mImageView];
[_mImageView startLoad];