简体   繁体   English

如何在圆形贝塞尔曲线路径内绘制图像

[英]How to draw image inside a circular bezier path

I am trying to create a custom view to draw a music CD with the album artwork on the CD. 我正在尝试创建一个自定义视图,以使用CD上的专辑插图绘制音乐CD。

Currently I use core graphics to draw two circular disks inside the drawRect method. 目前,我使用核心图形在drawRect方法内绘制两个圆形磁盘。 The inner disk's colour is set to the background colour of the view to make it look like the inner circle is a hollow circle. 内圆盘的颜色设置为视图的背景色,以使其看起来像内圆是空心圆。

My problem is that I can't draw the UIImage inside the the circular bezier path to get the result that I need. 我的问题是我无法在圆形贝塞尔曲线路径内绘制UIImage以获得所需的结果。

Here's my drawRect code: 这是我的drawRect代码:

// Draw a CD like view using three drawing operations:
// 1st draw the main disk
// 2nd draw the image if it is set
// 3rd draw the inner disk over the image so that it looks like it is a hollow disk with the image painted on the disk.
// Note:) This view expects its aspect ratio to be set as 1:1
- (void)drawRect:(CGRect)rect
{
    // Draw the main Circular CD disk
    UIBezierPath* outerRing = [UIBezierPath bezierPathWithOvalInRect:self.bounds];

    [self.mainColor setFill];
    [outerRing fill];

    [self.outerRingColor setStroke];
    [outerRing stroke];

    // Draw the album image if it is set
    if(self.artwork){
        [self.artwork drawInRect:self.bounds blendMode:kCGBlendModeNormal alpha:1.0];
    }

    // now draw another smaller disk inside
    // this will be a percentage smaller than the whole disk's bounds and will be centered inside it
    CGFloat sidePaddingCoord = ((1.0f - INNER_DISK_SIZE_PERCENTAGE) / 2) * self.bounds.size.height;
    CGFloat side = INNER_DISK_SIZE_PERCENTAGE * self.bounds.size.width;

    UIBezierPath* innerRing = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(sidePaddingCoord, sidePaddingCoord, side, side)];

    [self.innerRingColor setFill];
    [innerRing fill];

    [innerRing stroke];
}

This fills the image as a square. 这会将图像填充为正方形。 I want the image to be clipped inside the outerRing bezier path so that it looks like a music CD. 我希望将图像剪切在outerRing贝塞尔曲线路径中 ,以使其看起来像音乐CD。

I'm sure there is a way to use core graphics to achieve something else besides using the image's drawInRect method. 我确信除了使用图像的drawInRect方法之外,还有一种方法可以使用核心图形来实现其他目的。 Is there any way to 'clip' the image inside the circular bezier path or only draw inside the bezier path? 有什么方法可以“剪切”圆形贝塞尔曲线路径内的图像或仅在贝塞尔曲线路径内绘制图像吗?

I've read really great posts by rob mayoff, UIBezierPath Subtract Path , iOS UIImage clip to paths , many thanks. 我已经阅读了rob mayoff的精彩文章, UIBezierPath减去PathiOS UIImage路径的剪辑 ,非常感谢。

Here is an adoption of his code. 这是他的代码的采用。 Keep your creation code of outerRing and innerRing , add them to an array named paths . 保留您的outerRinginnerRing创建代码,并将它们添加到名为paths的数组中。

[self.paths addObject:outerRing];
[self.paths addObject:innerRing];

Then use this help method. 然后使用此帮助方法。

- (UIImage *)maskedImage
{
    CGRect rect = CGRectZero;
    rect.size = self.originalImage.size;
    UIGraphicsBeginImageContextWithOptions(rect.size, YES, 0.0);

    UIBezierPath *clipPath = [UIBezierPath bezierPathWithRect:CGRectInfinite];
    [clipPath appendPath:self.paths[1]];
    clipPath.usesEvenOddFillRule = YES;

    CGContextSaveGState(UIGraphicsGetCurrentContext()); {
        [clipPath addClip];
        [[UIColor orangeColor] setFill];
        [self.paths[0] fill];
    } CGContextRestoreGState(UIGraphicsGetCurrentContext());

    UIImage *mask = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0.0); {
        CGContextClipToMask(UIGraphicsGetCurrentContext(), rect, mask.CGImage);
        [self.originalImage drawAtPoint:CGPointZero];
    }
    UIImage *maskedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return maskedImage;
}

In drawRect , drawRect

UIImage *maskedImage = [self maskedImage];
[maskedImage drawInRect:self.bounds blendMode:kCGBlendModeNormal alpha:1.0];

Try below code: 试试下面的代码:

    UIImageView *userImageView= [[UIImageView alloc] initWithFrame:CGRectMake(85, 55.0, 90, 90)];
    userImageView.layer.cornerRadius = 90/2;
    userImageView.clipsToBounds = YES;
    userImageView.layer.borderWidth = 1.0f;
    userImageView.layer.borderColor = [UIColor blueColor];
    [self.view addSubview:userImageView]; //or add it to the view you want
    UIImage *userImage = [UIImage imageNamed:@"<image you want to set>"];
    userImageView= [[UIImageView alloc] initWithFrame:CGRectMake(90, 60.0, 80, 80)];
    userImageView.image = userImage;
    userImageView.layer.cornerRadius = 80/2;
    userImageView.clipsToBounds = YES;
    userImageView.layer.borderWidth = 1.0f;
    userImageView.layer.borderColor = [UIColor blueColor;
    [self.view addSubview:userImageView]; //or add it to the view you want

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM