IOS 百叶窗动画

来源:互联网 发布:模拟dfa java算法 编辑:程序博客网 时间:2024/04/19 17:17

之前看到多利用苹果开发的OpenGL接口实现的帧动画,原理是利用 Edward Patel 封装 EPGLTransitionView,绘制百叶窗的不同时间帧,实现动画效果。

考虑过将其移植到自己的代码中,但因为对OpenGL完全不懂,不能很好的切合到自己的代码里,放弃了。


后来,想到一个方法,将UIView截屏成图片,然后将图片等份切割成6份(我的代码里是6份),然后用6个UIImageView容纳这些切割后的UIImage图片,每个UIImageView代表一个扇叶,每个扇叶均沿着自己的Y轴旋转90度,这样模拟百叶窗的动画就完成了。


具体实现上有几个需要注意的地方

1、旋转要是绕着左边轴,右边轴,还是中轴旋转;如果是两边轴,那么在做仿射矩阵变化时需要做些处理。

2、6个UIImageView的动画启动有时间差。这个问题,我才用动画关键帧的方法处理(animateKeyframesWithDuration ,addKeyframeWithRelativeStartTime)

3、切割图片,要注意UIImge.scale属性


因为主要变换都是仿射矩阵变化,所以其他平台、其他语言也应该可以用相同的方式处理


具体实现代码如下:


截屏代码

UIImage* screenShotForView(UIView* view){    //[UIScreen mainScreen].scale,保持截屏的图片精度    UIGraphicsBeginImageContextWithOptions(view.bounds.size, YES, [UIScreen mainScreen].scale);    [view.layer renderInContext:UIGraphicsGetCurrentContext()];    UIImage *img = UIGraphicsGetImageFromCurrentImageContext();    UIGraphicsEndImageContext();    return img;}

切割图片代码

UIImage* UIImage_getSubImage(UIImage * srcImg , CGRect subRect){    CGImageRef subImageRef = CGImageCreateWithImageInRect(srcImg.CGImage, subRect);    UIImage *subImg = [UIImage imageWithCGImage:subImageRef];    CGImageRelease(subImageRef);    return subImg;}


围绕XY平面任意点旋转的代码

CATransform3D CATransform3DMakeRotateAroundPoint(UIView *view ,CGPoint point ,CGFloat radian ,CGFloat x ,CGFloat y, CGFloat z){//point 是view坐标系的点    //矩阵变换是相对与layer.anchorPoint为原点的坐标系进行的    //计算x ,y 在layer.anchorPoint为原点的坐标系下的坐标    const CGPoint anchor = view.layer.anchorPoint;    point.x -= view.bounds.size.width * anchor.x;    point.y -= view.bounds.size.height * anchor.y;    //矩阵变换    CATransform3D rotate = CATransform3DMakeTranslation( point.x , point.y , 0);    rotate = CATransform3DRotate(rotate, radian, x, y, z);    rotate = CATransform3DTranslate(rotate, -point.x , -point.y , 0);    return rotate;}

动画代码

(void)blindForView:(UIView *blindView){    NSMutableArray * imgVlist = [NSMutableArray array];    {        const int blindCount = 6;//扇叶数量                CGFloat oneViweWidth = blindView.bounds.size.width / blindCount;        CGRect viewBounds = blindView.bounds;                UIImage * viewShot = screenShotForView(blindView);        CGFloat oneImgWidth = viewShot.size.width * viewShot.scale / blindCount;        CGRect imgBounds = (CGRect){0,0,viewShot.size.width * viewShot.scale ,viewShot.size.height * viewShot.scale };        //切割图片,并创建UIImageView        for (int i =0 ; i< blindCount ; i++)        {            UIImageView * imgV = [[UIImageView alloc] initWithFrame: LeftRect(viewBounds, oneViweWidth, oneViweWidth * i)];            imgV.contentMode = UIViewContentModeScaleToFill;            imgV.image = UIImage_getSubImage(viewShot, LeftRect(imgBounds, oneImgWidth, oneImgWidth * i));            [blindView.superView addSubview:imgV];            [imgVlist addObject:imgV];            [imgV release];        }    }    blindView.hidden = YES;    [UIView animateKeyframesWithDuration:2 delay:0 options:UIViewKeyframeAnimationOptionCalculationModeLinear animations:^{                for (int i = 0 ; i < imgVlist.count ;i++)        {            UIView *view  = imgVlist[i];            [UIView addKeyframeWithRelativeStartTime:0.1 *i relativeDuration:2-(0.1 *i) animations:^{                                CGPoint point = {view.bounds.size.width/2 ,view.bounds.size.height/2};                CATransform3D rotate = CATransform3DMakeRotateAroundPoint(view, point, M_PI /2, 0, 1, 0);                view.layer.transform = rotate;            }];        }    } completion:^(BOOL finished) {                for (UIView *view in imgVlist)        {            [view removeFromSuperview];        }    }];}


0 0
原创粉丝点击