通过CGMutablePathRef动画在drawRect中绘制的框

时间:2013-04-08 20:43:14

标签: ios objective-c uiview drawrect uiviewanimation

我的目标是在我的UIView上投下一个空的圆形框,它应该显示为一个洞,以显示其中的内容。 我通过覆盖drawRect方法实现了这一点,如下所示。 这使我能够创建一个圆形的矩形,其大小为我的holeRect属性(这是一个CGRect),将一个内部阴影放入其中并将其放在我的视图上,清除(使用 clearColor 和< strong> CGContextSetBlendMode(context,kCGBlendModeSourceOut))此框所涵盖的区域,并显示我的视图背后的内容(我从this问题中获取了一些代码并对其进行了修改)。 现在我的问题是我必须用动画移动并调整此矩形的大小,我找不到这样做的方法,也许我选择了错误的方法来做到这一点但是我不是那么专业的绘图所以任何暗示非常感谢。

- (void)drawRect:(CGRect)rect
{



//I set the frame of my "holey" rect
CGRect bounds =  self.holeRect;
CGContextRef context = UIGraphicsGetCurrentContext();
CGFloat radius = 20;

//fill my whole view with gray
CGContextSetFillColorWithColor( context, [UIColor colorWithRed:.5 green:.5 blue:.5 alpha:.8].CGColor );
CGContextFillRect( context, rect );

// Create the "visible" path, which will be the shape that gets the inner shadow
// In this case it's just a rounded rect, but could be as complex as your want
CGMutablePathRef visiblePath = CGPathCreateMutable();
CGRect innerRect = CGRectInset(bounds, radius, radius);
CGPathMoveToPoint(visiblePath, NULL, innerRect.origin.x, bounds.origin.y);
CGPathAddLineToPoint(visiblePath, NULL, innerRect.origin.x + innerRect.size.width, bounds.origin.y);
CGPathAddArcToPoint(visiblePath, NULL, bounds.origin.x + bounds.size.width, bounds.origin.y, bounds.origin.x + bounds.size.width, innerRect.origin.y, radius);
CGPathAddLineToPoint(visiblePath, NULL, bounds.origin.x + bounds.size.width, innerRect.origin.y + innerRect.size.height);
CGPathAddArcToPoint(visiblePath, NULL,  bounds.origin.x + bounds.size.width, bounds.origin.y + bounds.size.height, innerRect.origin.x + innerRect.size.width, bounds.origin.y + bounds.size.height, radius);
CGPathAddLineToPoint(visiblePath, NULL, innerRect.origin.x, bounds.origin.y + bounds.size.height);
CGPathAddArcToPoint(visiblePath, NULL,  bounds.origin.x, bounds.origin.y + bounds.size.height, bounds.origin.x, innerRect.origin.y + innerRect.size.height, radius);
CGPathAddLineToPoint(visiblePath, NULL, bounds.origin.x, innerRect.origin.y);
CGPathAddArcToPoint(visiblePath, NULL,  bounds.origin.x, bounds.origin.y, innerRect.origin.x, bounds.origin.y, radius);
CGPathCloseSubpath(visiblePath);

// Fill this path
UIColor *aColor = [UIColor clearColor];
[aColor setFill];
CGContextAddPath(context, visiblePath);
CGContextSetBlendMode(context, kCGBlendModeSourceOut);
CGContextFillPath(context);


// Now create a larger rectangle, which we're going to subtract the visible path from
// and apply a shadow
CGMutablePathRef path = CGPathCreateMutable();
//(when drawing the shadow for a path whichs bounding box is not known pass "CGPathGetPathBoundingBox(visiblePath)" instead of "bounds" in the following line:)
//-42 cuould just be any offset > 0
CGPathAddRect(path, NULL, CGRectInset(bounds, -42, -42));

// Add the visible path (so that it gets subtracted for the shadow)
CGPathAddPath(path, NULL, visiblePath);
CGPathCloseSubpath(path);

// Add the visible paths as the clipping path to the context
CGContextAddPath(context, visiblePath);
CGContextClip(context);


// Now setup the shadow properties on the context
aColor = [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.5f];
CGContextSaveGState(context);
CGContextSetShadowWithColor(context, CGSizeMake(0.0f, 1.0f), 5.0f, [aColor CGColor]);

// Now fill the rectangle, so the shadow gets drawn
[aColor setFill];   
CGContextSaveGState(context);   
CGContextAddPath(context, path);
CGContextEOFillPath(context);

// Release the paths
//CGPathRelease(path);
CGPathRelease(visiblePath);

}

2 个答案:

答案 0 :(得分:1)

看看我给出的关于在UIImageView中打洞的问题的答案:

https://stackoverflow.com/a/8632731/341994

请注意,它的工作方式是UIImageView的superview图层有一个子层,可以进行掩蔽,从而打孔。这意味着要为洞穴设置动画,您所要做的就是为该子图层的移动设置动画。核心动画很简单,如我的书中所述:

http://www.apeth.com/iOSBook/ch17.html#_using_a_cabasicanimation

换句话说,如果你可以封装你作为一个图层做的所有事情,那么通过移动图层来动画它是微不足道的。

答案 1 :(得分:0)

按照您已经进行的设置,您要做的是将剪切块的位置存储在视图类的实例变量(实现此drawRect方法的类)中,并使用NSTimer更新位置定期。例如,在视图的代码中,您可以制作如下的预定计时器:

[NSTimer scheduledTimerWithTimeInterval:1.0/30.0 target:self selector:@selector(updateCutoutPosition) userInfo:nil repeats:YES];

然后实现更新方法:

- (void)updateCutoutPosition {
    // Do whatever you need to do to update the position of the cutout.
    [self setNeedsDisplay]; // Will cause drawRect to be called again soon.
}