iOS开发系列之常用自定义控件开发集—自动3D广告墙图片控件开发

来源:互联网 发布:淘宝数据的uv是什么 编辑:程序博客网 时间:2024/05/21 21:45

这节课我们根据上一节课的自动广告墙图片控件版本进行升级改进为3D效果上一节课的代码链接
下面是3D自动广告墙实现代码版本如下:
WHC_3DAdvertisingWall.h头文件如下:

////  WHC_3DAdvertisingWall.h//  WHC_3DAdvertisingWall////  Created by 吴海超 on 15/3/26.//  Copyright (c) 2015年 吴海超. All rights reserved.//#import <UIKit/UIKit.h>@class WHC_3DAdvertisingWall;//单击图片代理@protocol WHC_3DAdvertisingWallDelegate <NSObject>@optional- (void)WHC_3DAdvertisingWall:(WHC_3DAdvertisingWall*)whc_AdWallView clickImage:(UIImage*)image index:(NSInteger)index;@end@interface WHC_3DAdvertisingWall : UIView@property (nonatomic,assign) id<WHC_3DAdvertisingWallDelegate>delegate;@property (nonatomic,assign) BOOL  isCanTouchScroll;@property (nonatomic,assign) BOOL  isCanAutoScroll;//以图片对象数组初始化- (instancetype)initWithFrame:(CGRect)frame withImages:(NSArray*)imageArr;//以图片名称数组初始化- (instancetype)initWithFrame:(CGRect)frame withImageNames:(NSArray *)imageNames;//以图片对象数组重载图片- (void)reloadImage:(NSArray*)images;//以图片名称数组重载图片- (void)reloadImageNames:(NSArray*)imageNames;@end

WHC_3DAdvertisingWall.m源文件如下:

////  WHC_3DAdvertisingWall.m//  WHC_3DAdvertisingWall////  Created by 吴海超 on 15/3/26.//  Copyright (c) 2015年 吴海超. All rights reserved.//#import "WHC_3DAdvertisingWall.h"#define KWHC_MOVE_IMAGE_DURING (0.4)        //动画切换图片周期#define KWHC_LEFT_START_INDEX (1)           //向左切换时的初始imageView下标#define KWHC_RIGHT_START_INDEX (0)          //向右切换时的初始imageView下标#define KWHC_PAGE_CONTROL_HEIGHT (20.0)     //页控件高度#define KWHC_3D_WIDTH (50.0)                //3D效果UIImageView的宽度#define KWHC_DISZ (-1.0 / 900.0)            //3D透视参数#define KWHC_EXEC_DISTANCE (18.0)           //进行切换图片有效像素距离#define KWHC_HIDE_DISTANCE (6.0)            //进行移动图片隐藏有效像素距离//自定义方向枚举typedef enum {    NONE,    LEFT,    RIGHT}WHC_TOUCH_ORI;@interface WHC_3DImageView : UIImageView@property (nonatomic,assign)CGFloat hideCenterX;       //存储隐藏时中心点x坐标@property (nonatomic,assign)WHC_TOUCH_ORI ori;         //存储触摸方向- (void)reset;                                         //恢复初始参数的状态@end@implementation WHC_3DImageView- (void)reset{    self.hidden = NO;    _hideCenterX = 0.0;    _ori = NONE;}@end@interface WHC_3DAdvertisingWall (){    NSArray                 * _imageArr;                 //图片数组          NSMutableArray          * _imageViewArr;             //图片控件数组    UIPageControl           * _pageCtl;                  //页控件    NSTimer                 * _timer;                    //定时器    UIPanGestureRecognizer  * _panGesture;               //触摸手势    CGRect                    _frame;                    //该控件frame    NSInteger                 _currentIndex;             //当前图片下标    CGPoint                   _startPoint;               //触摸开始点    WHC_TOUCH_ORI             _currentMoveOri;           //当前移动方向    BOOL                      _isStartTouch;             //是否开始触摸了    BOOL                      _isExecAnimation;          //是否执行切换动画}@end@implementation WHC_3DAdvertisingWall#pragma mark - init//以图片对象数组初始化- (instancetype)initWithFrame:(CGRect)frame withImages:(NSArray*)imageArr{    self = [super initWithFrame:frame];    if(self != nil){        _currentIndex = 0;        _currentMoveOri = NONE;        _frame = frame;        _imageArr = [NSArray arrayWithArray:imageArr];        _imageViewArr = [NSMutableArray array];        //注册触摸事件        [self registerTouchEvent];        //初始化UI布局        [self initLayout];    }    return self;}//以图片名称数组初始化- (instancetype)initWithFrame:(CGRect)frame withImageNames:(NSArray *)imageNames{    NSMutableArray  * images = [NSMutableArray array];    for (NSString * imagePath in imageNames) {        [images addObject:[UIImage imageNamed:imagePath]];    }    return [self initWithFrame:frame withImages:images];}#pragma mark - controlAnimation//设置是否可以触摸切换- (void)setIsCanTouchScroll:(BOOL)isCanTouchScroll{    _isCanTouchScroll = isCanTouchScroll;    if(!isCanTouchScroll){        [self removeGestureRecognizer:_panGesture];    }else{        [self addGestureRecognizer:_panGesture];    }}//设置是否可以自动切换- (void)setIsCanAutoScroll:(BOOL)isCanAutoScroll{    _isCanAutoScroll = isCanAutoScroll;    if(isCanAutoScroll){        if(_timer != nil){            [_timer invalidate];            _timer = nil;        }        _timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(startAutoScrollImage) userInfo:nil repeats:YES];    }else{        [_timer invalidate];        _timer = nil;    }}//开始自动切换- (void)startAutoScrollImage{    //default to left scroll image    WHC_3DImageView  * imageView0 = _imageViewArr[0];    [UIView animateWithDuration:0.1 animations:^{        imageView0.center = CGPointMake(0.0, imageView0.center.y);        imageView0.layer.transform = [self initMakeTransform3D:M_PI / 2.0];    } completion:^(BOOL finished) {        imageView0.layer.transform = [self initMakeTransform3D:-M_PI / 2.0];        imageView0.center = CGPointMake(CGRectGetWidth(_frame), imageView0.center.y);        [self updateImageViewImage:LEFT];        [self animationResetImage:0 withOri:LEFT];    }];}#pragma mark - other//加载错误提示view- (void)loadAlertText{    UILabel  * labText = [[UILabel alloc]initWithFrame:CGRectMake(0.0, .0, CGRectGetWidth(_frame), CGRectGetHeight(_frame))];    labText.backgroundColor = [UIColor clearColor];    labText.textColor = [UIColor grayColor];    labText.textAlignment = NSTextAlignmentCenter;    labText.numberOfLines = 0;    labText.text = @"WHC_3DAdvertisingWall\nimage count = 0";    [self addSubview:labText];}- (void)registerTouchEvent{    _panGesture = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(handlePanGesture:)];}#pragma mark - reload//重新加载图片以图片对象数组- (void)reloadImage:(NSArray*)images{    //清除旧的    for (UIView * view in self.subviews) {        [view removeFromSuperview];    }    self.isCanTouchScroll = NO;    self.isCanAutoScroll = NO;    _currentIndex = 0;    _currentMoveOri = NONE;    [_imageViewArr removeAllObjects];    _imageArr = nil;    //加载新的    _imageArr = [NSArray arrayWithArray:images];    [self initLayout];}//重新加载图片以图片名称数组- (void)reloadImageNames:(NSArray*)imageNames{    NSMutableArray  * images = [NSMutableArray array];    for (NSString * imagePath in imageNames) {        [images addObject:[UIImage imageNamed:imagePath]];    }    [self reloadImage:images];}#pragma mark - makeTransform3D//3D处理- (CATransform3D)initMakeTransform3D:(CGFloat)angle{    CGPoint        center = CGPointZero;    CATransform3D  rotate = CATransform3DMakeRotation(angle, 0.0, 1.0, 0.0);    CATransform3D  transform3DToCenter = CATransform3DMakeTranslation(-center.x, -center.y, 0.0);    CATransform3D  transform3DToBack = CATransform3DMakeTranslation(center.x, center.y, 0.0);    CATransform3D  scale = CATransform3DIdentity;    scale.m34 = KWHC_DISZ;    return CATransform3DConcat(rotate , CATransform3DConcat(CATransform3DConcat(transform3DToCenter, scale), transform3DToBack));}//设置图片控件3d效果- (void)setImageViewTransform3D:(WHC_3DImageView*)imageView angle:(CGFloat)angle distance:(CGFloat)distance ori:(WHC_TOUCH_ORI)ori{    CATransform3D  rotate = CATransform3DRotate(imageView.layer.transform, angle, 0.0, 1.0, 0.0);    imageView.center = CGPointMake(imageView.center.x + distance, imageView.center.y);    imageView.layer.transform = rotate;    if((imageView.center.x <= KWHC_HIDE_DISTANCE && ori == LEFT) ||       (imageView.center.x >= (CGRectGetWidth(_frame) - KWHC_HIDE_DISTANCE) && ori == RIGHT)){        if(!imageView.hidden){            imageView.hidden = YES;            imageView.ori = ori;            imageView.hideCenterX = imageView.center.x;        }    }else{        if(ori == LEFT && imageView.tag == 2){            CGFloat  centerX = imageView.center.x;            if(CGRectGetWidth(_frame) - centerX - cosf(rotate.m13) * (CGRectGetWidth(imageView.frame) / 2.0) >= KWHC_EXEC_DISTANCE){                if(_isExecAnimation)return;                [self animationMoveImage:0 withOri:ori];            }        }else if(ori == RIGHT && imageView.tag == 0){            CGFloat  centerX = imageView.center.x;            if(centerX - cosf(rotate.m31) * (CGRectGetWidth(imageView.frame) / 2.0) >= KWHC_EXEC_DISTANCE){                if(_isExecAnimation)return;                [self animationMoveImage:0 withOri:ori];            }        }        if(imageView.hidden && imageView.ori != ori){            if((ori == LEFT && imageView.center.x < imageView.hideCenterX) ||               (ori == RIGHT && imageView.center.x > imageView.hideCenterX)){                [imageView reset];            }        }    }}#pragma mark - initUI//初始化ui布局- (void)initLayout{    NSInteger  imageCount = _imageArr.count;    if(imageCount < 1){        [self loadAlertText];        return;    }    CGFloat  imageWidth = CGRectGetWidth(_frame) - KWHC_3D_WIDTH * 2.0;    for (int i = 0; i < 3; i++) {        WHC_3DImageView  * imageView = [[WHC_3DImageView alloc]initWithFrame:CGRectMake((i - 1) * imageWidth + KWHC_3D_WIDTH, 0.0, imageWidth, CGRectGetHeight(_frame))];        imageView.tag = i;        if(i == 1){            imageView.image = _imageArr[0];            imageView.layer.transform = [self initMakeTransform3D:0.0];        }else if(i == 0){            imageView.center = CGPointMake(KWHC_3D_WIDTH / 2.0, imageView.center.y);            imageView.image = _imageArr[imageCount - 1];            imageView.layer.transform = [self initMakeTransform3D:acosf(KWHC_3D_WIDTH / imageWidth)];        }else{            imageView.center = CGPointMake(imageWidth + KWHC_3D_WIDTH + KWHC_3D_WIDTH / 2.0, imageView.center.y);            NSInteger  index = i >= imageCount ? imageCount - 1 : i - 1;            imageView.image = _imageArr[index];            imageView.layer.transform = [self initMakeTransform3D:-acosf(KWHC_3D_WIDTH / imageWidth)];        }        [self addSubview:imageView];        [_imageViewArr addObject:imageView];    }    _pageCtl = [[UIPageControl alloc]initWithFrame:CGRectMake(0.0, CGRectGetHeight(_frame) - KWHC_PAGE_CONTROL_HEIGHT, CGRectGetWidth(_frame), KWHC_PAGE_CONTROL_HEIGHT)];    _pageCtl.backgroundColor = [UIColor clearColor];    _pageCtl.numberOfPages = imageCount;    [self addSubview:_pageCtl];    UIButton * clearBtn = [UIButton buttonWithType:UIButtonTypeCustom];    clearBtn.frame = CGRectMake(.0, .0, CGRectGetWidth(_frame), CGRectGetHeight(_frame));    clearBtn.backgroundColor = [UIColor clearColor];    [clearBtn addTarget:self action:@selector(clickClearBtn:) forControlEvents:UIControlEventTouchUpInside];    [self addSubview:clearBtn];    if(imageCount > 1){        self.isCanTouchScroll = YES;        self.isCanAutoScroll = YES;    }}#pragma mark - handleAnimation//切换时更新图片- (void)updateImageViewImage:(WHC_TOUCH_ORI)touchOri{    if(touchOri == LEFT){        _currentIndex++;        if(_currentIndex >= _imageArr.count){            _currentIndex = 0;        }        [_imageViewArr exchangeObjectAtIndex:0 withObjectAtIndex:1];        [_imageViewArr exchangeObjectAtIndex:1 withObjectAtIndex:2];    }else{        _currentIndex--;        if(_currentIndex < 0){            _currentIndex = _imageArr.count - 1;        }        [_imageViewArr exchangeObjectAtIndex:0 withObjectAtIndex:2];        [_imageViewArr exchangeObjectAtIndex:1 withObjectAtIndex:2];    }    _pageCtl.currentPage = _currentIndex;    for(int i = 0; i < _imageViewArr.count; i++){        WHC_3DImageView * imageView  = _imageViewArr[i];        imageView.tag = i;        if(i == 0){            NSInteger index = _currentIndex - 1;            if(index < 0){                index = _imageArr.count - 1;            }            imageView.image = _imageArr[index];        }else if(i == 1){            imageView.image = _imageArr[_currentIndex];        }else{            NSInteger index = _currentIndex + 1;            if(index >= _imageArr.count){                index = 0;            }            imageView.image = _imageArr[index];        }    }}//触摸移动图片- (void)touchMoveImage:(WHC_TOUCH_ORI)ori withDistance:(CGFloat)moveXDistace{    CGFloat        imageWidth = CGRectGetWidth([UIScreen mainScreen].bounds) - KWHC_3D_WIDTH * 2.0;    CGFloat        angle = (moveXDistace / ((KWHC_3D_WIDTH / 2.0) + imageWidth)) * 2.0 * acosf((KWHC_3D_WIDTH / imageWidth));    for (int i = 0; i < 3; i++) {        WHC_3DImageView * imageView = _imageViewArr[i];        [self setImageViewTransform3D:imageView angle:-angle distance:moveXDistace ori:ori];    }}//动画移动图片- (void)animationMoveImage:(NSInteger)index withOri:(WHC_TOUCH_ORI)touchOri{    WHC_3DImageView  * imageView0 = _imageViewArr[0];    WHC_3DImageView  * imageView2 = _imageViewArr[2];    if(touchOri == LEFT){        [imageView0 reset];        imageView0.layer.transform = [self initMakeTransform3D:-M_PI / 2.0];        imageView0.center = CGPointMake(CGRectGetWidth(_frame), imageView0.center.y);    }else if(touchOri == RIGHT){        [imageView2 reset];        imageView2.layer.transform = [self initMakeTransform3D:M_PI / 2.0];        imageView2.center = CGPointMake(0.0, imageView2.center.y);    }    [self updateImageViewImage:touchOri];    [self updateImageViewPosition];}//更新图片空间位子- (void)updateImageViewPosition{    CGFloat  imageWidth = CGRectGetWidth(_frame) - KWHC_3D_WIDTH * 2.0;    WHC_3DImageView  * imageView0 = _imageViewArr[0];    WHC_3DImageView  * imageView1 = _imageViewArr[1];    WHC_3DImageView  * imageView2 = _imageViewArr[2];    [imageView0 reset];    [imageView1 reset];    [imageView2 reset];    imageView0.center = CGPointMake(KWHC_3D_WIDTH / 2.0, imageView0.center.y);    imageView0.layer.transform = [self initMakeTransform3D:acosf(KWHC_3D_WIDTH / imageWidth)];    imageView1.center = CGPointMake(CGRectGetWidth(_frame) / 2.0,imageView1.center.y);    imageView1.layer.transform = [self initMakeTransform3D:0.0];    imageView2.center = CGPointMake(CGRectGetWidth(_frame) - KWHC_3D_WIDTH / 2.0, imageView2.center.y);    imageView2.layer.transform = [self initMakeTransform3D:-acosf(KWHC_3D_WIDTH / imageWidth)];#if 0    [UIView animateWithDuration:KWHC_MOVE_IMAGE_DURING animations:^{        imageView0.center = CGPointMake(KWHC_3D_WIDTH / 2.0, imageView0.center.y);        imageView0.layer.transform = [self initMakeTransform3D:acosf(KWHC_3D_WIDTH / imageWidth)];        imageView1.center = CGPointMake(CGRectGetWidth(_frame) / 2.0,imageView1.center.y);        imageView1.layer.transform = [self initMakeTransform3D:0.0];        imageView2.center = CGPointMake(CGRectGetWidth(_frame) - KWHC_3D_WIDTH / 2.0, imageView2.center.y);        imageView2.layer.transform = [self initMakeTransform3D:-acosf(KWHC_3D_WIDTH / imageWidth)];    }completion:^(BOOL finished) {        _isExecAnimation = NO;        self.isCanTouchScroll = YES;    }];#endif}//动画调整图片位子- (void)animationResetImage:(NSInteger)index  withOri:(WHC_TOUCH_ORI)touchOri{    CGFloat  imageWidth = CGRectGetWidth(_frame) - KWHC_3D_WIDTH * 2.0;    WHC_3DImageView  * imageView0 = _imageViewArr[0];    WHC_3DImageView  * imageView1 = _imageViewArr[1];    WHC_3DImageView  * imageView2 = _imageViewArr[2];    if(imageView0.hidden){        imageView0.center = CGPointMake(0.0, imageView0.center.y);        imageView0.layer.transform = [self initMakeTransform3D:M_PI / 2.0];    }    if(imageView2.hidden){        imageView2.center = CGPointMake(CGRectGetWidth(_frame), imageView2.center.y);        imageView2.layer.transform = [self initMakeTransform3D:-M_PI / 2.0];    }    [imageView0 reset];    [imageView1 reset];    [imageView2 reset];    _isExecAnimation = YES;    self.isCanTouchScroll = NO;    [UIView animateWithDuration:KWHC_MOVE_IMAGE_DURING animations:^{        imageView0.center = CGPointMake(KWHC_3D_WIDTH / 2.0, imageView0.center.y);        imageView0.layer.transform = [self initMakeTransform3D:acosf(KWHC_3D_WIDTH / imageWidth)];        imageView1.center = CGPointMake(CGRectGetWidth(_frame) / 2.0,imageView1.center.y);        imageView1.layer.transform = [self initMakeTransform3D:0.0];        imageView2.center = CGPointMake(CGRectGetWidth(_frame) - KWHC_3D_WIDTH / 2.0, imageView2.center.y);        imageView2.layer.transform = [self initMakeTransform3D:-acosf(KWHC_3D_WIDTH / imageWidth)];    }completion:^(BOOL finished) {        _isExecAnimation = NO;        self.isCanTouchScroll = YES;    }];}#pragma mark - handleGesture//手势触摸处理- (void)handlePanGesture:(UIPanGestureRecognizer *)panGesture{    switch (panGesture.state) {        case UIGestureRecognizerStateBegan:            if(self.isCanAutoScroll){                _isStartTouch = YES;                self.isCanAutoScroll = NO;            }            _startPoint = [panGesture locationInView:self];            break;        case UIGestureRecognizerStateChanged:{            if(_isExecAnimation) return;            CGPoint  currentPoint = [panGesture locationInView:self];            CGFloat  moveXInstance = currentPoint.x - _startPoint.x;            if([panGesture velocityInView:self].x < 0){                //left                if (_currentMoveOri == RIGHT) {                    [self touchMoveImage:LEFT withDistance:-fabsf(moveXInstance)];                }else{                    _currentMoveOri = LEFT;                    [self touchMoveImage:LEFT withDistance:-fabsf(moveXInstance)];                }            }else{                //right                if(_currentMoveOri == LEFT){                    [self touchMoveImage:RIGHT withDistance:fabsf(moveXInstance)];                }else{                    _currentMoveOri = RIGHT;                    [self touchMoveImage:RIGHT withDistance:fabsf(moveXInstance)];                }            }            _startPoint = currentPoint;        }            break;        case UIGestureRecognizerStateEnded:        case UIGestureRecognizerStateCancelled:{            _currentMoveOri = NONE;            if(_isStartTouch){                self.isCanAutoScroll = YES;            }            _isStartTouch = NO;            [self animationResetImage:KWHC_RIGHT_START_INDEX withOri:_currentMoveOri];        }            break;        default:            break;    }}#pragma mark - clickAction//单击图片处理- (void)clickClearBtn:(UIButton*)sender{    if(_currentIndex <= _imageArr.count - 1){        if(_delegate && [_delegate respondsToSelector:@selector(WHC_3DAdvertisingWall:clickImage:index:)]){            [_delegate WHC_3DAdvertisingWall:self clickImage:_imageArr[_currentIndex] index:_currentIndex];        }    }}@end

运行效果
WHC_3DAdvertisingWallDemo下载

0 0
原创粉丝点击