如何在ios中的uiimage上创建动态矩形?

时间:2013-09-24 10:26:24

标签: ios core-graphics nsbezierpath

我正在尝试在imageview上创建一个动态矩形。这意味着矩形应该在触摸时开始,只要用户移动触摸,它应该在那个方向上更大。 朋友建议我,拜托。

3 个答案:

答案 0 :(得分:0)

您需要使用Core Graphics,尝试本教程:

Quartz 2D Programming Guide

答案 1 :(得分:0)

听起来好像你想在UIImage的之上选择一个矩形,而不仅仅是调整图像大小的能力。

如果是这种情况,我建议采用以下结构:

  1. 将UIImage加载到UIImageView中并将其放在屏幕上。
  2. 创建一个UIView,它是UIImageView的兄弟姐妹
  3. 从#2覆盖UIView的-drawRect:方法,只是绘制一个有边框的轮廓。
  4. 使用-touchesBegan检测用户的触摸:/ - touchesMoved:/ - touchesEnded:等。
  5. 根据#4中的逻辑和数学,在动画块中调整UIView的帧。
  6. 根据我的经验,这种性质的动画在使用震动和支柱以及-touchesBegan等时更容易实现,而不是Autolayout和UIGestureRecognizers,而是YMMV。

    当然,你正在做的事情可能需要一些高级数学,基于你如何回答如下问题:

    1. 用户可以移动选择矩形吗?
    2. 我是否希望用户抓住“边缘”以便能够调整大小?
    3. 用户离“抓住”边缘的距离有多近?
    4. 如果没有,用户是否只是朝着一个方向“推”,使得矩形更大,无论他们的手指在哪里?
    5. 以下代码执行以下操作:

      1. 将图像加载到UIImageView
      2. 允许用户放置100x100选择矩形(首先)
      3. 允许用户通过触摸/拖动矩形内部
      4. 来移动选择矩形
      5. 允许用户通过抓取8个边缘区域之一
      6. 来调整选择矩形的大小
      7. 更新选择矩形的图形以从“非活动”模式指示“活动”模式
      8. 代码所做的假设:

        1. 用户将使用1根手指与屏幕进行互动
        2. UIImageView占用整个视图
        3. 此代码需要更新:

          1. 用户可以在屏幕外部分移动选择矩形
          2. 此代码不会 DO 任何带有选择矩形的内容(例如,拍摄选择矩形内容的快照/图像)
          3. #define GRAB_DISTANCE                       10
            #define VIEW_PLACEMENT_ANIMATION_DURATION   0.1
            #define VIEW_SIZING_ANIMATION_DURATION      0.1
            typedef enum {
                kMSSLineTypeDashed,
                kMSSLineTypeSolid
            } MSSLineType;
            typedef enum {
                kMSSRectangleGrabZoneBottom,
                kMSSRectangleGrabZoneBottomLeft,
                kMSSRectangleGrabZoneBottomRight,
                kMSSRectangleGrabZoneLeft,
                kMSSRectangleGrabZoneNone,
                kMSSRectangleGrabZoneRight,
                kMSSRectangleGrabZoneTop,
                kMSSRectangleGrabZoneTopLeft,
                kMSSRectangleGrabZoneTopRight
            } MSSRectangleGrabZone;
            typedef enum {
                kMSSRectangleStatusNone,
                kMSSRectangleStatusPlacement,
                kMSSRectangleStatusResizing
            } MSSRectangleStatus;
            @interface MSSSelectionView : UIView
            @property (assign, nonatomic)   MSSLineType  currentLineType;
            @property (strong, nonatomic)   UIColor     *borderColor;
            @end
            @implementation MSSSelectionView
            - (void)awakeFromNib {
                [super awakeFromNib];
                self.currentLineType = kMSSLineTypeSolid;
            }
            - (void)drawRect:(CGRect)rect {
                // Just make a border, 2 points wide, 1 point inset (so it is all contained by the view)
                CGContextRef context    = UIGraphicsGetCurrentContext();
                CGRect borderRect       = CGRectInset(rect, 1, 1);
                CGContextSetLineCap(context, kCGLineCapRound);
                CGContextSetLineWidth(context, 2.0f);
                switch (self.currentLineType) {
                    case kMSSLineTypeDashed:
                    {
                        CGFloat lengths[2] = {3, 4};
                        CGContextSetLineDash(context, 0.0f, lengths, 2);
                    }
                        break;
            
                    case kMSSLineTypeSolid:
                    {
                        CGContextSetLineDash(context, 0.0f, NULL, 0);
                    }
                        break;
            
                    default:
                        break;
                }
                [self.borderColor setStroke];
                CGContextStrokeRect(context, borderRect);
            }
            @end
            #import "MSSViewController.h"
            @interface MSSViewController ()
            @property (assign, nonatomic)           BOOL                     selectionIsVisible;
            @property (assign, nonatomic)           MSSRectangleGrabZone     currentGrabZone;
            @property (assign, nonatomic)           MSSRectangleStatus       currentStatus;
            @property (strong, nonatomic) IBOutlet  MSSSelectionView        *selectionView;
            @property (strong, nonatomic) IBOutlet  UIImageView             *imageView;
            @end
            @implementation MSSViewController
            - (void)viewDidLoad {
                [super viewDidLoad];
                self.imageView.image    = [UIImage imageNamed:@"image.jpg"];
                self.currentGrabZone    = kMSSRectangleGrabZoneNone;
                self.currentStatus      = kMSSRectangleStatusNone;
            }
            #pragma mark - Touch Handling
            - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
                // Get a touch object (assuming just a 1-finger touch here)
                UITouch *touch = [touches anyObject];
                CGPoint location = [touch locationInView:self.view];
            
                if (self.selectionIsVisible == NO) {
                    // Showing the selection view for the first time
            
                    // Update instance property
                    self.selectionIsVisible = YES;
            
                    // Place the rectangle (centered around touch)
                    self.selectionView.center = location;
            
                    // Unhide the rectangle
                    self.selectionView.hidden = NO;
            
                    // Set the status flag to placement
                    self.currentStatus = kMSSRectangleStatusPlacement;
            
                    // Change the border color to indicate that it's active
                    self.selectionView.borderColor      = [UIColor lightGrayColor];
                    self.selectionView.currentLineType  = kMSSLineTypeDashed;
                    [self.selectionView setNeedsDisplay];
            
                } else {
                    // Selection view already visible, so first make sure the touch was inside the selection view
                    if (CGRectContainsPoint(self.selectionView.frame, location)) {
                        // The touch was inside the selection view, so update the selection view's line drawing properties
                        self.selectionView.borderColor      = [UIColor lightGrayColor];
                        self.selectionView.currentLineType  = kMSSLineTypeDashed;
                        [self.selectionView setNeedsDisplay];
            
                        // Set status flag based on proximity to edge
                        BOOL edgeGrabbed = [self location:location inGrabZoneForRect:self.selectionView.frame];
                        if (edgeGrabbed == YES) {
                            // The user has grabbed the edge, so allow selection view resizing
                            self.currentStatus      = kMSSRectangleStatusResizing;
                            self.currentGrabZone    = [self zoneGrabbedForPoint:location inRect:self.selectionView.frame];
            
                        } else {
                            // The user has touched the interior, so allow selection view movement/placement
                            self.currentStatus      = kMSSRectangleStatusPlacement;
                            self.currentGrabZone    = kMSSRectangleGrabZoneNone;
                        }
            
                    }
            
                }
            
            }
            - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
            
                // Get a touch object (assuming just a 1-finger touch here)
                UITouch *touch              = [touches anyObject];
                CGPoint currentLocation     = [touch locationInView:self.view];
                CGPoint previousLocation    = [touch previousLocationInView:self.view];
                CGFloat xDelta              = currentLocation.x - previousLocation.x;
                CGFloat yDelta              = currentLocation.y - previousLocation.y;
                CGRect frame                = self.selectionView.frame;
            
            
                switch (self.currentStatus) {
                    case kMSSRectangleStatusNone:
                        // Do nothing
                        break;
            
                    case kMSSRectangleStatusPlacement:
                    {
                        // The entire selection view should be moved under the user's finger
                        frame.origin.x      = frame.origin.x + xDelta;
                        frame.origin.y      = frame.origin.y + yDelta;
                    }
                        break;
            
                    case kMSSRectangleStatusResizing:
                    {
                        switch (self.currentGrabZone) {
                            case kMSSRectangleGrabZoneBottom:
                            {
                                // Make the view's frame taller or shorter based on yDelta
                                frame.size.height   = frame.size.height + yDelta;
            
                            }
                                break;
            
                            case kMSSRectangleGrabZoneBottomLeft:
                            {
                                // Make the view's frame taller or shorter based on yDelta
                                // Make the view's frame wider or narrower PLUS move origin based on xDelta
                                frame.origin.x      = frame.origin.x    + xDelta;
                                frame.size.height   = frame.size.height + yDelta;
                                frame.size.width    = frame.size.width  - xDelta;
            
                            }
                                break;
            
                            case kMSSRectangleGrabZoneBottomRight:
                            {
                                // Make the view's frame taller or shorter based on yDelta
                                // Make the view's frame wider or narrower based on xDelta
                                frame.size.height   = frame.size.height + yDelta;
                                frame.size.width    = frame.size.width  + xDelta;
            
                            }
                                break;
            
                            case kMSSRectangleGrabZoneLeft:
                            {
                                // Make the view's frame wider or narrower PLUS move origin based on xDelta
                                frame.origin.x      = frame.origin.x    + xDelta;
                                frame.size.width    = frame.size.width  - xDelta;
            
                            }
                                break;
            
                            case kMSSRectangleGrabZoneNone:
                                // Do nothing
                                break;
            
                            case kMSSRectangleGrabZoneRight:
                            {
                                // Make the view's frame wider or narrower based on xDelta
                                frame.size.width    = frame.size.width  + xDelta;
                            }
                                break;
            
                            case kMSSRectangleGrabZoneTop:
                            {
                                // Make the view's frame taller or shorter PLUS move origin based on yDelta
                                frame.origin.y      = frame.origin.y    + yDelta;
                                frame.size.height   = frame.size.height - yDelta;
                            }
                                break;
            
                            case kMSSRectangleGrabZoneTopLeft:
                            {
                                // Make the view's frame wider or narrower PLUS move origin based on xDelta
                                // Make the view's frame taller or shorter PLUS move origin based on yDelta
                                frame.origin.x      = frame.origin.x    + xDelta;
                                frame.origin.y      = frame.origin.y    + yDelta;
                                frame.size.width    = frame.size.width  - xDelta;
                                frame.size.height   = frame.size.height - yDelta;
                            }
                                break;
            
                            case kMSSRectangleGrabZoneTopRight:
                            {
                                // Make the view's frame wider or narrower based on xDelta
                                // Make the view's frame taller or shorter PLUS move origin based on yDelta
                                frame.origin.y      = frame.origin.y    + yDelta;
                                frame.size.height   = frame.size.height - yDelta;
                                frame.size.width    = frame.size.width  + xDelta;
                            }
                                break;
            
                            default:
                                break;
                        }
                    }
                        break;
            
                    default:
                        break;
                }
                // Any frame changes made above should be animated here
                [UIView animateWithDuration:VIEW_PLACEMENT_ANIMATION_DURATION
                                 animations:^{
                                     self.selectionView.frame = frame;
                                 }
                                 completion:^(BOOL finished) {
                                     [self.selectionView setNeedsDisplay];
                                 }
                 ];
            }
            - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
                // Nothing much to do, just make the border black to indicate activity is done
                self.currentGrabZone                = kMSSRectangleGrabZoneNone;
                self.currentStatus                  = kMSSRectangleStatusNone;
                self.selectionView.borderColor      = [UIColor blackColor];
                self.selectionView.currentLineType  = kMSSLineTypeSolid;
                [self.selectionView setNeedsDisplay];
            
            }
            #pragma mark - Rectangle helper methods
            - (BOOL)location:(CGPoint)location inGrabZoneForRect:(CGRect)rect {
                if (CGRectContainsPoint(rect, location)) {
            
                    // The point is inside the rectangle, so determine if it's in the grab zone or the interior
                    CGRect nonGrabZoneRect = CGRectInset(rect, GRAB_DISTANCE, GRAB_DISTANCE);
            
                    if (CGRectContainsPoint(nonGrabZoneRect, location)) {
                        // This point is in the interior (non-grab zone)
                        return NO;
            
                    } else {
                        // This point is in the grab zone
                        return YES;
            
                    }
            
                } else {
                    // The point is not inside the rectangle, which means they didn't grab the edge/border
                    return NO;
            
                }
            
            }
            - (MSSRectangleGrabZone)zoneGrabbedForPoint:(CGPoint)point inRect:(CGRect)rect {
                CGRect topLeftGrabZone      = CGRectMake(rect.origin.x,                                     rect.origin.y,                                      GRAB_DISTANCE,                          GRAB_DISTANCE);
                CGRect topGrabZone          = CGRectMake(rect.origin.x + GRAB_DISTANCE,                     rect.origin.y,                                      rect.size.width - (2 * GRAB_DISTANCE),  GRAB_DISTANCE);
                CGRect topRightGrabZone     = CGRectMake(rect.origin.x + rect.size.width - GRAB_DISTANCE,   rect.origin.y,                                      GRAB_DISTANCE,                          GRAB_DISTANCE);
            
                CGRect leftGrabZone         = CGRectMake(rect.origin.x,                                     rect.origin.y + GRAB_DISTANCE,                      GRAB_DISTANCE,                          rect.size.height - (2 * GRAB_DISTANCE));
            
                CGRect rightGrabZone        = CGRectMake(rect.origin.x + rect.size.width - GRAB_DISTANCE,   rect.origin.y + GRAB_DISTANCE,                      GRAB_DISTANCE,                          rect.size.height - (2 * GRAB_DISTANCE));
            
                CGRect bottomLeftGrabZone   = CGRectMake(rect.origin.x,                                     rect.origin.y + rect.size.height - GRAB_DISTANCE,   GRAB_DISTANCE,                          GRAB_DISTANCE);
                CGRect bottomGrabZone       = CGRectMake(rect.origin.x + GRAB_DISTANCE,                     rect.origin.y + rect.size.height - GRAB_DISTANCE,   rect.size.width - (2 * GRAB_DISTANCE),  GRAB_DISTANCE);
                CGRect bottomRightGrabZone  = CGRectMake(rect.origin.x + rect.size.width - GRAB_DISTANCE,   rect.origin.y + rect.size.height - GRAB_DISTANCE,   GRAB_DISTANCE,                          GRAB_DISTANCE);
            
                if (CGRectContainsPoint(topLeftGrabZone, point)) {
                    return kMSSRectangleGrabZoneTopLeft;
            
                } else if (CGRectContainsPoint(topGrabZone, point)) {
                    return kMSSRectangleGrabZoneTop;
            
                } else if (CGRectContainsPoint(topRightGrabZone, point)) {
                    return kMSSRectangleGrabZoneTopRight;
            
                } else if (CGRectContainsPoint(leftGrabZone, point)) {
                    return kMSSRectangleGrabZoneLeft;
            
                } else if (CGRectContainsPoint(rightGrabZone, point)) {
                    return kMSSRectangleGrabZoneRight;
            
                } else if (CGRectContainsPoint(bottomLeftGrabZone, point)) {
                    return kMSSRectangleGrabZoneBottomLeft;
            
                } else if (CGRectContainsPoint(bottomGrabZone, point)) {
                    return kMSSRectangleGrabZoneBottom;
            
                } else if (CGRectContainsPoint(bottomRightGrabZone, point)) {
                    return kMSSRectangleGrabZoneBottomRight;
            
                } else {
                    return kMSSRectangleGrabZoneNone;
            
                }
            }
            @end
            

答案 2 :(得分:-1)

您可以以编程方式创建imageview,并在触摸移动时调整其框架大小。请参阅以下链接,它可以帮助您。

How can I draw dynamic rectangle on screen according to touchMove event on iOS