在UIImageView IOS上绘制圆的最佳方法

在UIImageView IOS上绘制圆的最佳方法,ios,uiview,uiimageview,cgcontext,cashapelayer,Ios,Uiview,Uiimageview,Cgcontext,Cashapelayer,我有一个UIImageView,它显示了用户刚刚用相机拍摄的照片。在这张图上,我需要画一个固定大小的透明可移动圆圈。因此,当用户在图像上拖动手指时,圆圈随之移动。然后,如果用户停止移动手指,圆圈将保持在原来的位置 我一直在阅读苹果的文档,但我仍然不确定最好的方法是什么,我应该画一个UIView吗 任何例子都会很精彩。谢谢。以下代码创建了三种手势: 点击手势会在视图上留下一个圆圈(这样您就可以看到CAShapeLayer是如何创建的) 平移手势移动圆(假设您从圆内开始移动);及 捏一捏可以调整圆

我有一个UIImageView,它显示了用户刚刚用相机拍摄的照片。在这张图上,我需要画一个固定大小的透明可移动圆圈。因此,当用户在图像上拖动手指时,圆圈随之移动。然后,如果用户停止移动手指,圆圈将保持在原来的位置

我一直在阅读苹果的文档,但我仍然不确定最好的方法是什么,我应该画一个UIView吗


任何例子都会很精彩。谢谢。

以下代码创建了三种手势:

  • 点击手势会在视图上留下一个圆圈(这样您就可以看到
    CAShapeLayer
    是如何创建的)

  • 平移手势移动圆(假设您从圆内开始移动);及

  • 捏一捏可以调整圆的大小

因此,这可能看起来像:

#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIGestureRecognizerSubclass.h>

@interface ViewController ()

@property (nonatomic, weak) CAShapeLayer *circleLayer;
@property (nonatomic) CGPoint circleCenter;
@property (nonatomic) CGFloat circleRadius;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];

    // create tap gesture

    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                          action:@selector(handleTap:)];
    [self.view addGestureRecognizer:tap];

    // create pan gesture

    UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self
                                                                          action:@selector(handlePan:)];
    [self.view addGestureRecognizer:pan];

    // create pinch gesture

    UIPinchGestureRecognizer *pinch = [[UIPinchGestureRecognizer alloc] initWithTarget:self
                                                                                action:@selector(handlePinch:)];
    [self.view addGestureRecognizer:pinch];
}

// Create a UIBezierPath which is a circle at a certain location of a certain radius.
// This also saves the circle's center and radius to class properties for future reference.

- (UIBezierPath *)makeCircleAtLocation:(CGPoint)location radius:(CGFloat)radius
{
    self.circleCenter = location;
    self.circleRadius = radius;

    UIBezierPath *path = [UIBezierPath bezierPath];
    [path addArcWithCenter:self.circleCenter
                    radius:self.circleRadius
                startAngle:0.0
                  endAngle:M_PI * 2.0
                 clockwise:YES];

    return path;
}

// Create a CAShapeLayer for our circle on tap on the screen

- (void)handleTap:(UITapGestureRecognizer *)gesture
{
    CGPoint location = [gesture locationInView:gesture.view];

    // if there was a previous circle, get rid of it

    [self.circleLayer removeFromSuperlayer];

    // create new CAShapeLayer

    CAShapeLayer *shapeLayer = [CAShapeLayer layer];
    shapeLayer.path = [[self makeCircleAtLocation:location radius:50.0] CGPath];
    shapeLayer.strokeColor = [[UIColor redColor] CGColor];
    shapeLayer.fillColor = nil;
    shapeLayer.lineWidth = 3.0;

    // Add CAShapeLayer to our view

    [gesture.view.layer addSublayer:shapeLayer];

    // Save this shape layer in a class property for future reference,
    // namely so we can remove it later if we tap elsewhere on the screen.

    self.circleLayer = shapeLayer;
}

// Let's move the CAShapeLayer on a pan gesture (assuming we started
// pan inside the circle).

- (void)handlePan:(UIPanGestureRecognizer *)gesture
{
    static CGPoint oldCenter;

    if (gesture.state == UIGestureRecognizerStateBegan)
    {
        // If we're starting a pan, make sure we're inside the circle.
        // So, calculate the distance between the circle's center and 
        // the gesture start location and we'll compare that to the 
        // radius of the circle.

        CGPoint location = [gesture locationInView:gesture.view];
        CGPoint translation = [gesture translationInView:gesture.view];
        location.x -= translation.x;
        location.y -= translation.y;

        CGFloat x = location.x - self.circleCenter.x;
        CGFloat y = location.y - self.circleCenter.y;
        CGFloat distance = sqrtf(x*x + y*y);

        // If we're outside the circle, cancel the gesture.
        // If we're inside it, keep track of where the circle was.

        if (distance > self.circleRadius)
            gesture.state = UIGestureRecognizerStateCancelled;
        else
            oldCenter = self.circleCenter;
    }
    else if (gesture.state == UIGestureRecognizerStateChanged)
    {
        // Let's calculate the new center of the circle by adding the
        // the translationInView to the old circle center.

        CGPoint translation = [gesture translationInView:gesture.view];
        CGPoint newCenter = CGPointMake(oldCenter.x + translation.x, oldCenter.y + translation.y);

        // Update the path for our CAShapeLayer

        self.circleLayer.path = [[self makeCircleAtLocation:newCenter radius:self.circleRadius] CGPath];
    }
}

// Let's resize circle in the CAShapeLayer on a pinch gesture (assuming we have
// a circle layer).

- (void)handlePinch:(UIPinchGestureRecognizer *)gesture
{
    static CGFloat oldCircleRadius;

    if (gesture.state == UIGestureRecognizerStateBegan)
    {
        if (self.circleLayer)
            oldCircleRadius = self.circleRadius;
        else
            gesture.state = UIGestureRecognizerStateCancelled;
    }
    else if (gesture.state == UIGestureRecognizerStateChanged)
    {
        CGFloat newCircleRadius = oldCircleRadius * gesture.scale;
        self.circleLayer.path = [[self makeCircleAtLocation:self.circleCenter radius:newCircleRadius] CGPath];
    }
}

@end
#导入
#进口
@界面视图控制器()
@属性(非原子,弱)CAShapeLayer*circleLayer;
@属性(非原子)CGPoint circleCenter;
@性质(非原子)环;
@结束
@实现视图控制器
-(无效)viewDidLoad
{
[超级视图下载];
//创建点击手势
UITapGestureRecognizer*点击=[[UITapGestureRecognizer alloc]initWithTarget:self
操作:@selector(handleTap:)];
[self.view addgesturecognizer:tap];
//创建平移手势
UIPangestureRecognitor*pan=[[UIPangestureRecognitor alloc]initWithTarget:self
操作:@selector(handlePan:)];
[self.view addgestureRecognitor:pan];
//创建捏手势
UIPinchGestureRecognizer*pinch=[[UIPinchGestureRecognizer alloc]initWithTarget:self
操作:@选择器(handlePinch:)];
[self.view addgesturecognizer:pinch];
}
//创建一个UIBezierPath,它是一个在特定半径的特定位置的圆。
//这还会将圆的圆心和半径保存到类属性中,以供将来参考。
-(UIBezierPath*)makeCircleAtLocation:(CGPoint)位置半径:(CGFloat)半径
{
self.circleCenter=位置;
自循环=半径;
UIBezierPath*路径=[UIBezierPath bezierPath];
[路径addArcWithCenter:self.circleCenter
半径:自环
startAngle:0.0
端角:M_PI*2.0
顺时针:是];
返回路径;
}
//在屏幕上点击,为我们的圆圈创建一个CAShapeLayer
-(无效)handleTap:(UITapgestureRecognitor*)手势
{
CGPoint location=[手势位置视图:手势.视图];
//如果有前一圈,就把它去掉
[self.circleLayer从Superlayer移除];
//创建新的CAShapeLayer
CAShapeLayer*shapeLayer=[CAShapeLayer层];
shapeLayer.path=[[self-makeCircleAtLocation:location radius:50.0]CGPath];
shapeLayer.strokeColor=[[UIColor redColor]CGColor];
shapeLayer.fillColor=nil;
shapeLayer.lineWidth=3.0;
//将CAShapeLayer添加到我们的视图中
[手势.视图.图层添加子图层:shapeLayer];
//将此形状图层保存在类特性中以供将来参考,
//也就是说,如果我们点击屏幕上的其他地方,我们可以删除它。
self.circleLayer=shapeLayer;
}
//让我们以平移姿势移动CAShapeLayer(假设我们开始
//在圆圈内平移)。
-(无效)手持面板:(UIPangestureRecognitor*)手势
{
静态重心;
if(signature.state==UIGestureRecognitizerStateStart)
{
//如果我们要启动平底锅,确保我们在圆圈内。
//因此,计算圆的圆心和圆之间的距离
//手势开始位置,我们将其与
//圆的半径。
CGPoint location=[手势位置视图:手势.视图];
CGPoint translation=[手势翻译视图:手势.视图];
location.x-=translation.x;
location.y-=translation.y;
CGFloat x=location.x-self.circleCenter.x;
CGFloat y=location.y-self.circleCenter.y;
CGFloat距离=sqrtf(x*x+y*y);
//如果我们在圈外,取消这个手势。
//如果我们在里面,追踪圆圈的位置。
if(距离>自循环)
手势.state=ui手势识别器状态已取消;
其他的
oldCenter=self.circleCenter;
}
else if(signature.state==UIgestureRecognitizerStateChanged)
{
//让我们通过添加
//将视图平移到旧圆心。
CGPoint translation=[手势翻译视图:手势.视图];
CGPoint newCenter=CGPointMake(oldCenter.x+translation.x,oldCenter.y+translation.y);
//更新CAShapeLayer的路径
self.circleLayer.path=[[self-makeCircleLocation:newCenter radius:self.circleRadius]CGPath];
}
}
//让我们用捏的手势调整CAShapeLayer中的圆的大小(假设我们有
//圆形层)。
-(无效)handlePinch:(UIPinchGestureRecognitor*)手势
{
静态循环;
if(signature.state==UIGestureRecognitizerStateStart)
{
if(自循环层)
oldCircleRadius=self.circleRadius;
其他的
手势.state=ui手势识别器状态已取消;
}
else if(signature.state==UIgestureRecognitizerStateChanged)
{
CGFloat newCircleRadius=旧Circleradius*手势.scale;
self.circleLayer.path=[[self-makeCircleLocation:self.circleCenter radius:newCircleRadius]CGPath];
}
}
@结束

谢谢Rob,非常清楚,正是我想要的,如果可以的话,我会打两个勾:-)@Rob上面的代码很棒,你能帮我知道如何将圆圈下的图像部分裁剪成单独的图像吗?Tha