2013-04-08 64 views
2

我的目標是將一個空的圓角框(它應該顯示爲一個洞)拖到我的UIView上以顯示下面的內容。 我通過覆蓋drawRect方法做到了這一點,如下所示。 這給我創造我holeRect屬性的大小的圓角的矩形(這是一個的CGRect),下降內側陰影到它,並把它放在我的看法,清除能力(使用clearColorCGContextSetBlendMode(背景下, kCGBlendModeSourceOut))這個盒子覆蓋的區域,揭示了我的觀點背後(我從this問題中拿了一些代碼並修改了它)。 現在我的問題是,我必須移動和調整動畫的矩形,我找不到這樣做的方式,也許我選擇了錯誤的方式來做到這一點,但我並不擅長繪圖,所以任何提示將非常感激。通過CGMutablePathRef爲在drawRect中繪製的框設置動畫效果

- (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); 

} 

回答

1

看看這個答案我給了一個關於衝壓問題在一個UIImageView一洞:

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

注意,它的工作方式是的UIImageView的上海華盈的層具有子層,做日掩蔽並因此打孔。這意味着要對該孔進行動畫處理,您只需對該子圖層的運動進行動畫處理即可。這是用的Core Animation簡單,因爲在我的書中描述:

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

換句話說,如果你可以封裝你正在做的一切層,然後通過移動層動畫實在是小巫見大巫。

+0

感謝您的回答,但這不會幫助我,我正在閱讀有關Quartz和CA的文檔,但同時我似乎無法找到一種方法來製作類似於您的教程的代碼, m不使用任何類型的UIImageView等等。 我需要使用我手動繪製的盒子,並以某種方式爲它製作動畫。 – 2013-04-11 11:37:27

+0

我的其他代碼中的圖像視圖是不相關的。遮蔽層可以在*後面的任何*處打孔。所以,您只需製作您的繪圖動畫,以及打孔的面具。 – matt 2013-04-11 14:18:13

+0

你是否明白,你的圓形繪圖動畫是非常容易的?如果沒有,先弄清楚,然後再擔心打孔。也許你可以修改你的問題來描述你正在考慮的動畫。 – matt 2013-04-11 14:20:48

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. 
} 
+0

是不是這個解決方案太重CPU? – 2013-04-11 11:09:15

+0

如果您在drawRect方法中設置繪製動畫的東西,那麼您將具有相對較高的CPU使用率。你是否可以避免這種效率低下取決於你需要做什麼。它的形狀是否會在每個動畫幀中改變?如果是這樣,那麼你需要在這個'drawRect'方法或者一個遮罩層的'drawInContext'方法中繪製該形狀。如果切口形狀不經常改變,只是位置,那麼使用遮罩層是更好的方法。請參閱http://stackoverflow.com/questions/15609170/get-image-pixels-using-mask/15609515#15609515 – 2013-04-11 18:49:56

+0

我在之前的評論中用完了房間,但使用面具方法的想法是,您可以繪製遮罩層的形狀一次(或者不經常),並且您將爲遮罩層的框架設置動畫以設置切口的位置。如果你只是動畫框架,你可以使用'[UIView animateWithDuration:...'方法,這將比重複觸發'drawRect'更加高效。 – 2013-04-11 18:55:00

相關問題