小的先给客官呈上效果图。
这里的原型是我在cocoaChina上看到的,之后下载下来研究了下,发现他只是将大部分代码放在controller中,这样如果别的controller要用,得各种复制粘贴了。所以我将那些代码进行了封装。
在controller中只需
- (CardWith3DView *)cardsView {
if (!_cardsView) {
CGRect frame = CGRectMake(0, 100*k_IOS_Scale, 320*k_IOS_Scale, 280*k_IOS_Scale);
_cardsView = [[CardWith3DView alloc] initWithFrame:frame
imageArr:self.imageArr
index:self.imageArr.count/2];
}
return _cardsView;
}
当然这个cardsView是封装后的View
那么在View中的是怎么写的呢?
- (instancetype)initWithFrame:(CGRect)frame imageArr:(NSArray *)arr index:(NSInteger)index {
self = [super initWithFrame:frame];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(addGesToCardView) name:@"AddGes" object:nil];
self.initialIndex = 0;
self.isRight = YES;
self.imageArr = [arr mutableCopy];
[self addSubview:self.scrollView];
[self initImageViewWithImageArr:arr];
[self getCardsWithIndex:index];
}
return self;
}
这里面有些全局变量需要自己去懒加载的
- (UIScrollView *)scrollView {
if (!_scrollView) {
_scrollView = [UIScrollView new];
_scrollView.frame = self.bounds;
_scrollView.top = 0;
_scrollView.contentSize = CGSizeMake((self.imageArr.count-1)*55*k_IOS_Scale+154*k_IOS_Scale+100*k_IOS_Scale + 50, 0);
_scrollView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0);
_scrollView.backgroundColor = [UIColor blackColor];
_scrollView.delegate = self;
}
return _scrollView;
}
接着就可以对每张图片的frame进行设置了,并且有些图片在y轴上进行了旋转。
在方法
- (void)initImageViewWithImageArr:(NSArray *)imgArr {
NSMutableArray *imageViewArr = [NSMutableArray array];
[imgArr enumerateObjectsUsingBlock:^(NSString *obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSString *ss = [[obj componentsSeparatedByString:@"/"] lastObject];
UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:ss]];
imageView.tag = idx;
imageView.layer.borderWidth = 3;
imageView.layer.cornerRadius = 10;
imageView.clipsToBounds = YES;
imageView.layer.borderColor = [UIColor yellowColor].CGColor;
imageView.userInteractionEnabled = YES;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(imageTapClick:)];
[imageView addGestureRecognizer:tap];
if (idx == 0) {
imageView.frame = CGRectMake(0, 0, 154*k_IOS_Scale, 280*k_IOS_Scale);
imageView.center = CGPointMake(160*k_IOS_Scale, 140*k_IOS_Scale);
}else{
UIImageView *ima =[imageViewArr lastObject];
if (idx == 1) {
imageView.frame = CGRectMake(CGRectGetMaxX(ima.frame)-20*k_IOS_Scale, 20*k_IOS_Scale, 154*k_IOS_Scale, 230*k_IOS_Scale);
}else{
imageView.frame = CGRectMake((ima.frame.origin.x)+15*k_IOS_Scale, 20*k_IOS_Scale, 144*k_IOS_Scale, 230*k_IOS_Scale);
}
CATransform3D t = CATransform3DIdentity;
t.m34 = 4.5/-2000;
t = CATransform3DRotate(t, M_PI/2*3/4, 0, 1, 0);
imageView.layer.transform = t;
}
[_scrollView addSubview:imageView];
[imageViewArr addObject:imageView];
}];
self.cardsViewArr = [imageViewArr copy];
}
在上面的方法中会对每一张图片添加一个点击手势
- (void)imageTapClick:(UITapGestureRecognizer *)sender{
if (self.initialIndex == sender.view.tag) {
return;
}
if (self.initialIndex < sender.view.tag) {
_isRight = YES;
}else{
_isRight = NO;
}
[self getCardsWithIndex:sender.view.tag];
}
接着当我们点击图片时我们会重新改变刚才图片初始化时的frame以及旋转的角度。把这些改变放在View的动画中。
- (void)updateFrameForVisilably{
UIImageView *ima = self.cardsViewArr[self.initialIndex];
if (self.initialIndex > 0 && self.initialIndex < self.cardsViewArr.count - 1) {
UIImageView *pre = self.cardsViewArr[self.initialIndex-1];
UIImageView *tail = self.cardsViewArr[self.initialIndex+1];
CATransform3D t = CATransform3DIdentity;
t.m34 = 4.5/-2000;
t = CATransform3DRotate(t, -M_PI/2*3/4, 0, 1, 0);
CATransform3D t2 = CATransform3DIdentity;
t2.m34 = 4.5/-2000;
t2 = CATransform3DRotate(t2, 0, 0, 1, 0);
CATransform3D t3 = CATransform3DIdentity;
t3.m34 = 4.5/-2000;
t3 = CATransform3DRotate(t3, M_PI/2*3/4, 0, 1, 0);
UIImageView *four = nil;
if (self.initialIndex > 2&& self.initialIndex < self.cardsViewArr.count - 2) {
if (_isRight) {
four = self.cardsViewArr[self.initialIndex + 2];
}else{
four = self.cardsViewArr[self.initialIndex - 2];;
}
}
[UIView animateWithDuration:1.0 delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:0 options:0 animations:^{
if (!_isRight) {
four.frame = CGRectMake(55*(self.initialIndex)*k_IOS_Scale+30*k_IOS_Scale+154*k_IOS_Scale+55*k_IOS_Scale, 20*k_IOS_Scale, 144*k_IOS_Scale, 230*k_IOS_Scale);
tail.layer.transform = t3;
tail.frame = CGRectMake(55*(self.initialIndex-1)*k_IOS_Scale+240*k_IOS_Scale, 20*k_IOS_Scale, 144*k_IOS_Scale, 230*k_IOS_Scale);
ima.layer.transform = t2;
ima.frame = CGRectMake(55*(self.initialIndex-1)*k_IOS_Scale+110*k_IOS_Scale, 0, 154*k_IOS_Scale, 280*k_IOS_Scale);
pre.layer.transform = t;
pre.frame = CGRectMake(55*(self.initialIndex-1)*k_IOS_Scale+30*k_IOS_Scale, 20*k_IOS_Scale, 144*k_IOS_Scale, 230*k_IOS_Scale);
}else{
four.frame = CGRectMake(55*(self.initialIndex-1)*k_IOS_Scale+30*k_IOS_Scale, 20*k_IOS_Scale, 144*k_IOS_Scale, 230*k_IOS_Scale);
pre.layer.transform = t;
pre.frame = CGRectMake(55*(self.initialIndex-1)*k_IOS_Scale, 20*k_IOS_Scale, 144*k_IOS_Scale, 230*k_IOS_Scale);
ima.layer.transform = t2;
ima.frame = CGRectMake(55*(self.initialIndex-1)*k_IOS_Scale+30*k_IOS_Scale+80*k_IOS_Scale, 0, 154*k_IOS_Scale, 280*k_IOS_Scale);
tail.layer.transform = t3;
tail.frame = CGRectMake(55*(self.initialIndex-1)*k_IOS_Scale+30*k_IOS_Scale+154*k_IOS_Scale+55*k_IOS_Scale, 20*k_IOS_Scale, 144*k_IOS_Scale, 230*k_IOS_Scale);
}
} completion:^(BOOL finished) {
}];
}else if(self.initialIndex == 0){
UIImageView *tail = self.cardsViewArr[self.initialIndex+1];
CATransform3D t = CATransform3DIdentity;
t.m34 = 4.5/-2000;
t = CATransform3DRotate(t, -M_PI/2*3/4, 0, 1, 0);
CATransform3D t2 = CATransform3DIdentity;
t2.m34 = 4.5/-2000;
t2 = CATransform3DRotate(t2, 0, 0, 1, 0);
CATransform3D t3 = CATransform3DIdentity;
t3.m34 = 4.5/-2000;
t3 = CATransform3DRotate(t3, M_PI/2*3/4, 0, 1, 0);
[UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:0 options:0 animations:^{
ima.layer.transform = t2;
ima.frame = CGRectMake(55*(self.initialIndex - 1)*k_IOS_Scale+110*k_IOS_Scale, 0, 154*k_IOS_Scale, 280*k_IOS_Scale);
tail.layer.transform = t3;
tail.frame = CGRectMake(55*(self.initialIndex - 1)*k_IOS_Scale+234*k_IOS_Scale, 20*k_IOS_Scale, 144*k_IOS_Scale, 230*k_IOS_Scale);
}completion:^(BOOL finished) {
}];
}else if (self.initialIndex == self.cardsViewArr.count - 1){
UIImageView *pre = self.cardsViewArr[self.initialIndex - 1];
CATransform3D t = CATransform3DIdentity;
t.m34 = 4.5/-2000;
t = CATransform3DRotate(t, -M_PI/2*3/4, 0, 1, 0);
CATransform3D t2 = CATransform3DIdentity;
t2.m34 = 4.5/-2000;
t2 = CATransform3DRotate(t2, 0, 0, 1, 0);
[UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:0.8 initialSpringVelocity:0 options:0 animations:^{
pre.layer.transform = t;
pre.frame = CGRectMake(55*(self.initialIndex-1)*k_IOS_Scale+30*k_IOS_Scale, 20*k_IOS_Scale, 144*k_IOS_Scale, 230*k_IOS_Scale);
ima.layer.transform = t2;
ima.frame = CGRectMake(55*(self.initialIndex-1)*k_IOS_Scale+30*k_IOS_Scale+80*k_IOS_Scale, 0, 154*k_IOS_Scale, 280*k_IOS_Scale);
}completion:^(BOOL finished) {
}];
}
}
- (void)updateFrame{
for (NSInteger i=0; iself.initialIndex){
CATransform3D t = CATransform3DIdentity;
t.m34 = 4.5/-2000;
t = CATransform3DRotate(t, M_PI/2*3/4, 0, 1, 0);
imageV.layer.transform = t;
imageV.frame = CGRectMake(55*(i-1)*k_IOS_Scale+30*k_IOS_Scale+154*k_IOS_Scale+55*k_IOS_Scale, 20*k_IOS_Scale, 144*k_IOS_Scale, 230*k_IOS_Scale);
}
}
UIImageView *imaa = self.cardsViewArr[self.initialIndex];
_scrollView.contentOffset = CGPointMake(imaa.frame.origin.x-85, 0);
}
我们的View中有可以滑动的ScrollerVIew,所以这里当我们滑动View时可以响应的方法
- (void)swipeCardView:(UISwipeGestureRecognizer *)ges {
if (ges == self.swipeRightGes && self.initialIndex != 0) {
self.isRight = YES;
[self getCardsWithIndex:--self.initialIndex];
}else if (ges == self.swipeLeftGes && self.initialIndex != self.imageArr.count - 1) {
self.isRight = NO;
[self getCardsWithIndex:++self.initialIndex];
}
}
这样的动画算是完成了,其实主要就是frame的变化和View的layer层会绕y轴进行角度旋转。