2011-01-25 29 views
1

我一直試圖弄清楚爲什麼這不起作用,一直在撞牆撞牆。將CGGradient剪切到CGPath

基本上,我想用CGPath繪製圖形(圖表),然後用它來剪裁漸變。最終效果應該與iPhone附帶的股票應用程序一樣。

漸變和路徑分別作爲兩個分層(未剪切)元素單獨繪製。但是,如果我註釋掉CGContextDrawPath,線條和漸變都不會畫到屏幕上。

這裏是我的drawRect代碼:

CGContextRef context = UIGraphicsGetCurrentContext(); 

[[UIColor whiteColor] set]; 
CGContextSetLineWidth(context, 2.0f); 
CGPoint lastDrawnPt = [[points objectAtIndex:0] CGPointValue]; 
CGPoint firstDrawnPt = lastDrawnPt; 
//create the path for the gradient 
CGMutablePathRef thePath = CGPathCreateMutable(); 
CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, self.bounds.size.height); // bottom left 
CGPathAddLineToPoint(thePath, NULL, lastDrawnPt.x, lastDrawnPt.y); 


for (int i=0; i<(points.count-1); i++) { 
    //CGPoint pt1 = [[points objectAtIndex:i] CGPointValue]; 
    CGPoint pt2 = [[points objectAtIndex:i+1] CGPointValue]; 
    if (pt2.x > lastDrawnPt.x+2) { 
     // only draw if we've moved sunstantially to the right 

     //for the gradient 
     CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, lastDrawnPt.y); 
     CGPathAddLineToPoint(thePath, NULL, pt2.x, pt2.y); 


     lastDrawnPt = pt2; 
    } 
} 

//finish the gradient clipping path 
CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, lastDrawnPt.y); 
CGPathAddLineToPoint(thePath, NULL, lastDrawnPt.x, self.bounds.size.height); // bottom right 
CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, self.bounds.size.height); 
CGPathAddLineToPoint(thePath, NULL, firstDrawnPt.x, self.bounds.size.height); // bottom right 

CGPathCloseSubpath(thePath); 

//add the gradient clipping path to the context 
CGContextSaveGState(context); 
CGContextAddPath(context, thePath); 

//draw the path 
float components[4] = {1.0, 1.0, 1.0, 1.0}; 
CGContextSetStrokeColor(context, components); 
CGContextDrawPath(context,kCGPathStroke); 

//clip the path 
CGContextClip(context); 


//Draw Gradient 
UIColor *topColor = [UIColor colorWithRed: 1.0 green:1.0 blue:1.0 alpha:1.0]; 
UIColor *bottomColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.0]; 
CGColorRef colorRef[] = { [topColor CGColor], [bottomColor CGColor] }; 
CFArrayRef colors = CFArrayCreate(NULL, (const void**)colorRef, sizeof(colorRef)/sizeof(CGColorRef), &kCFTypeArrayCallBacks); 

CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, colors, NULL); 
CFRelease(colorSpace); 
CFRelease(colors); 

// Draw a linear gradient from top to bottom 
CGPoint gradStartPoint = CGPointMake(50.0, self.bounds.size.height); 
CGPoint gradEndPoint = CGPointMake(50.0, 0.0); 
CGContextDrawLinearGradient(context, gradient, gradStartPoint, gradEndPoint, 0); 

CFRelease(gradient); 

// Cleanup 
CGColorSpaceRelease(colorSpace); 

CGContextRestoreGState(context); 
+0

你嘗試過CGContextFlush還是CGContextSynchronize ...我想這可能與分層有關。在繪製漸變之後,請嘗試移動CGContextClip ... – namar0x0309 2011-01-25 23:18:44

+0

感謝您的想法,但它們似乎沒有幫助。 – avance 2011-01-25 23:28:22

回答

1
CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, self.bounds.size.height); // bottom left 
CGPathAddLineToPoint(thePath, NULL, lastDrawnPt.x, lastDrawnPt.y); 


for (int i=0; i<(points.count-1); i++) { 
    //CGPoint pt1 = [[points objectAtIndex:i] CGPointValue]; 
    CGPoint pt2 = [[points objectAtIndex:i+1] CGPointValue]; 
    if (pt2.x > lastDrawnPt.x+2) { 
     // only draw if we've moved sunstantially to the right 

     //for the gradient 
     CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, lastDrawnPt.y); 
     CGPathAddLineToPoint(thePath, NULL, pt2.x, pt2.y); 


     lastDrawnPt = pt2; 
    } 
} 

//finish the gradient clipping path 
CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, lastDrawnPt.y); 
CGPathAddLineToPoint(thePath, NULL, lastDrawnPt.x, self.bounds.size.height); // bottom right 
CGPathMoveToPoint(thePath, NULL, lastDrawnPt.x, self.bounds.size.height); 
CGPathAddLineToPoint(thePath, NULL, firstDrawnPt.x, self.bounds.size.height); // bottom right 

這只是繪製了一系列線段。對於某些點值,它可能看起來像這樣:

| |||| | 

它不繪製一個連續的形狀。因此,這條路徑對剪輯沒有用處,因爲它實際上是空的;正如你所看到的那樣,裁切它將導致裁剪路徑內沒有進一步的繪圖。

每個lineto,curveto,arc,等等從當前點起作用。您設置最初moveto,但每個linetocurvetoarc等不明確目前來看,它更新它。因此,要創建單個形狀,請先執行一個moveto,然後再執行lineto(或curvetoarc),最後執行closepath

說到closepath ...

CGPathCloseSubpath(thePath); 

這會在路徑中唯一封閉的形狀,但由於該形狀具有零區(即只折回到自身線段),它對裁剪目的仍然沒有幫助。

我懷疑你所要做的只是刪除至少一個moveto段(循環中的一個,如果不是那個循環之一)。然後,可以簡化循環使用數組中的快速枚舉,而不是使用索引,並切斷跟蹤「最後繪製的點」。

此外,NSArray索引的正確類型是NSUInteger,而不是int。保持你的類型匹配 - 它避免了以後的痛苦。