【iOS】裁剪出环形图片并旋转制作碟片效果

工作中有一个需求,仿照各大音乐播放app做一个碟片旋转的效果。

最终效果

后台给的图片是正常的,裁剪边框什么的还是得自己来。

终于整完了,写篇blog纪念一下。

创建一个RotateView,h文件设置两个属性:Image和Rotate。
image来赋值图片,rotate来控制是否旋转。

//重写image的setter方法
-(void)setImage:(UIImage *)image{
    _image = image;
    
    //获取正方形图片
    UIImage *squarlImage = [self squarlImageWithImage:image];
    //绘制环形图片
    squarlImage = [self getClearRectImage:squarlImage];
    //添加上边框
    squarlImage = [self drawBorderWithImage:squarlImage];
    //赋值
    self.imageView.image = squarlImage;
    
}

图片不一定都是正方形的,还有长方形。这种情况需要先裁剪成正方形,我这边的需求是从center开始。

//图片做成正方形
-(UIImage *)squarlImageWithImage:(UIImage *)image{
    CGFloat imageWidth = image.size.width;
    CGFloat imageHeight = image.size.height;
    //判断图片是否是正方形
    if (imageWidth == imageHeight) {
        return image;
    }
    
    //获取正方形的边长
    CGFloat width = imageWidth;
    if (imageHeight<imageWidth) {
        width = imageHeight;
    }
    
    //从中心扩散,以最短边为边长的正方形
    CGRect rect = CGRectMake((imageWidth-width)/2, (imageHeight-width)/2, width, width);
    
    CGImageRef SquareImageRef = CGImageCreateWithImageInRect(image.CGImage,rect);

    CGRect SquareImageBounds=CGRectMake(0,0,CGImageGetWidth(SquareImageRef),CGImageGetHeight(SquareImageRef));

    UIGraphicsBeginImageContext(SquareImageBounds.size);

    CGContextRef context =UIGraphicsGetCurrentContext();

    CGContextDrawImage(context,SquareImageBounds,SquareImageRef);

    UIImage* SquareImage = [UIImage imageWithCGImage:SquareImageRef];

    UIGraphicsEndImageContext();
    
    CGImageRelease(SquareImageRef);

    return SquareImage;
}

这样就获取到了一张正方形图片,接下来就可以开始裁剪环形了。

- (UIImage*)getClearRectImage:(UIImage*)image{

    UIGraphicsBeginImageContextWithOptions(image.size,NO,0.0f);

    CGContextRef ctx =UIGraphicsGetCurrentContext();

	//最外层圆的路径
    UIBezierPath *circlePath = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, image.size.width, image.size.height) cornerRadius:image.size.width/2];

    [circlePath addClip]; // 裁剪

    // 绘制图片到图片上下文中

    [image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];

    [image drawAtPoint:CGPointZero];

	//内部圆的半径
    CGFloat bigRaduis = image.size.width/10;

    CGRect cirleRect =CGRectMake(image.size.width/2-bigRaduis, image.size.height/2-bigRaduis, bigRaduis*2, bigRaduis*2);

    CGContextAddEllipseInRect(ctx,cirleRect);

    CGContextClip(ctx);

    CGContextClearRect(ctx,cirleRect);

    UIImage*newImage =UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    return newImage;
}

环形图片已经有了,还差两圈白色边框

-(UIImage *)drawBorderWithImage:(UIImage *)image{

    UIGraphicsBeginImageContextWithOptions(image.size,NO,0.0f);
    
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    
    CGRect bigRect = CGRectMake(3,3,image.size.width-6,image.size.height-6);
    //设置空心圆的线条宽度
    CGContextSetLineWidth(ctx, 6);
    //以矩形bigRect为依据画一个圆
    CGContextAddEllipseInRect(ctx, bigRect);
    //填充当前绘画区域的颜色
    [[UIColor whiteColor] set];
    //(如果是画圆会沿着矩形外围描画出指定宽度的(圆线)空心圆)/(根据上下文的内容渲染图层)
    CGContextStrokePath(ctx);
    
    //画一个小圆
    CGFloat bigRaduis = image.size.width/10;
    CGRect smallRect =CGRectMake(image.size.width/2-bigRaduis, image.size.height/2-bigRaduis, bigRaduis*2, bigRaduis*2);
    //设置空心圆的线条宽度
    CGContextSetLineWidth(ctx, 6);
    //以矩形Rect为依据画一个圆
    CGContextAddEllipseInRect(ctx, smallRect);
    //填充当前绘画区域的颜色
    [[UIColor whiteColor] set];
    //(如果是画圆会沿着矩形外围描画出指定宽度的(圆线)空心圆)/(根据上下文的内容渲染图层)
    CGContextStrokePath(ctx);
    //图片绘制进去
    [image drawInRect:bigRect];
    UIImage*newImage =UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();
    
    return newImage;
}

ok,这样就已经完成了碟片效果的图片,接下来就是让他随着播放旋转了。

重写rotate属性的setter方法来实现控制旋转开始暂停。

-(void)setIsRotate:(BOOL)isRotate{
    _isRotate = isRotate;
    //开始旋转
    if (isRotate) {
        //是否有上次暂停的时间
        if (self.imageView.layer.timeOffset == 0.0) {
            //没有,说明是第一次旋转
            CABasicAnimation* rotateAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
            rotateAnimation.fromValue = [NSNumber numberWithFloat:0.0];
            rotateAnimation.toValue = [NSNumber numberWithFloat:M_PI * 2];   // 旋转一周
            rotateAnimation.duration = 10.0;                               // 旋转时间20秒
            rotateAnimation.repeatCount = MAXFLOAT;                          // 重复次数,这里用最大次数
            [self.imageView.layer addAnimation:rotateAnimation forKey:nil];
        }else{
            //有。说明是旋转中途暂停过,继续上次的位置来旋转
            CFTimeInterval pausedTime = self.imageView.layer.timeOffset;
            self.imageView.layer.speed = 1.0;
            self.imageView.layer.timeOffset = 0.0;
            self.imageView.layer.beginTime = 0.0;
            CFTimeInterval timeSincePause = [self.imageView.layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
            self.imageView.layer.beginTime = timeSincePause;
        }
    }else{
        //暂停旋转,保存当前旋转的进度,在下次开始旋转时使用
        CFTimeInterval pausedTime = [self.imageView.layer convertTime:CACurrentMediaTime() fromLayer:nil];
        self.imageView.layer.speed = 0.0;    ///<停止
        self.imageView.layer.timeOffset = pausedTime;    ///<保存时间
    }
}

完成!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值