2014-03-13 161 views
5

我的目標是把一個模式像這樣沿路徑繪製圖案

enter image description here

,並多次繪製沿圓形路徑產生類似這樣的形象的東西:

enter image description here

我在其他問題和完整演示項目here中發現了幾個代碼示例,但結果如下:

enter image description here

我認爲兩幅圖像之間的差別很明顯,但我覺得很難形容(赦免我缺乏圖形詞彙)。結果似乎沒有圖案的期望的旋轉/變形平鋪。我認爲我可以忍受變形的缺乏,但輪換是關鍵。我認爲可能/應該修改draw drawback以包含輪換,但不能找出如何在回調點檢索/確定角度。

我考慮了一種手動變形/旋轉圖像的方法,並在中心點附近多次繪製它以達到我想要的效果,但我相信CoreGraphics可以以更高的效率和更少的代碼實現它。

有關如何實現我想要的結果的任何建議,將不勝感激。

下面是從ChalkCircle項目的相關代碼:

const float kPatternWidth = 8; 
const float kPatternHeight = 8; 

void DrawPatternCellCallback(void *info, CGContextRef cgContext) 
{ 
UIImage *patternImage = [UIImage imageNamed:@"chalk_brush.png"]; 
CGContextDrawImage(cgContext, CGRectMake(0, 0, kPatternWidth, kPatternHeight), patternImage.CGImage); 
} 

- (void)drawRect:(CGRect)rect { 
float startDeg = 0; // where to start drawing 
float endDeg = 360; // where to stop drawing 
int x = self.center.x; 
int y = self.center.y; 
int radius = (self.bounds.size.width > self.bounds.size.height ? self.bounds.size.height : self.bounds.size.width)/2 * 0.8; 
CGContextRef ctx = UIGraphicsGetCurrentContext(); 


const CGRect patternBounds = CGRectMake(0, 0, kPatternWidth, kPatternHeight); 
const CGPatternCallbacks kPatternCallbacks = {0, DrawPatternCellCallback, NULL}; 


CGAffineTransform patternTransform = CGAffineTransformIdentity; 
CGPatternRef strokePattern = CGPatternCreate(
NULL, 
patternBounds, 
patternTransform, 
kPatternWidth, // horizontal spacing 
kPatternHeight,// vertical spacing 
kCGPatternTilingNoDistortion, 
true, 
&kPatternCallbacks); 
CGFloat color1[] = {1.0, 1.0, 1.0, 1.0}; 


CGColorSpaceRef patternSpace = CGColorSpaceCreatePattern(NULL); 
CGContextSetStrokeColorSpace(ctx, patternSpace); 


CGContextSetStrokePattern(ctx, strokePattern, color1); 


CGContextSetLineWidth(ctx, 4.0); 


CGContextMoveToPoint(ctx, x, y - radius); 
CGContextAddArc(ctx, x, y, radius, (startDeg-90)*M_PI/180.0, (endDeg-90)*M_PI/180.0, 0); 
CGContextClosePath(ctx); 
CGContextDrawPath(ctx, kCGPathStroke); 


CGPatternRelease(strokePattern); 
strokePattern = NULL; 
CGColorSpaceRelease(patternSpace); 
patternSpace = NULL; 

} 

1552-1553薩姆

我修改Sam的解決方案來處理非方形圖案,中心的結果,並刪除硬編碼通過從傳入的圖像計算它們的數字:

#define MAX_CIRCLE_DIAMETER 290.0f 
#define OVERLAP 1.5f 

-(void) drawInCircle:(UIImage *)patternImage 
{ 
    int numberOfImages = 12; 
    float diameter = (MAX_CIRCLE_DIAMETER * numberOfImages * patternImage.size.width)/((2.0 * M_PI * patternImage.size.height) + (numberOfImages * patternImage.size.width)); 

    //get the radius, circumference and image size 
    CGRect replicatorFrame = CGRectMake((320-diameter)/2.0f, 60.0f, diameter, diameter); 
    float radius = diameter/2; 
    float circumference = M_PI * diameter; 
    float imageWidth = circumference/numberOfImages; 
    float imageHeight = imageWidth * patternImage.size.height/patternImage.size.width; 

    //create a replicator layer and add it to our view 
    CAReplicatorLayer *replicator = [CAReplicatorLayer layer]; 

    replicator.frame = replicatorFrame; 
    [self.view.layer addSublayer:replicator]; 

    //configure the replicator 
    replicator.instanceCount = numberOfImages; 

    //apply a rotation transform for each instance 
    CATransform3D transform = CATransform3DIdentity; 
    transform = CATransform3DRotate(transform, M_PI/(numberOfImages/2), 0, 0, 1); 
    replicator.instanceTransform = transform; 

    //create a sublayer and place it inside the replicator 
    CALayer *layer = [CALayer layer]; 
    //the frame places the layer in the middle of the replicator layer and on the outside of 
    //the replicator layer so that the the size is accurate relative to the circumference 
    layer.frame = CGRectMake(radius - (imageWidth/2.0) - (OVERLAP/2.0), -imageHeight/2.0, imageWidth+OVERLAP, imageHeight); 

    layer.anchorPoint = CGPointMake(0.5, 1); 
    [replicator addSublayer:layer]; 

    //apply a perspective transform to the layer 
    CATransform3D perspectiveTransform = CATransform3DIdentity; 
    perspectiveTransform.m34 = 1.0f/-radius; 
    perspectiveTransform = CATransform3DRotate(perspectiveTransform, (M_PI_4), -1, 0, 0); 
    layer.transform = perspectiveTransform; 

    //set the image as the layer's contents 
    layer.contents = (__bridge id)patternImage.CGImage; 
} 
+0

恐怕你要做的事情是一件非常複雜的事情,因爲模式是如何在圓圈內部被壓縮的並且在外面被拉伸。你可能不得不下降到OpenGL來實現它。 –

+0

是的,我畫出了一些代碼來做一個矩形到變形弧的轉換,但希望不必寫它大聲笑 –

回答

8

使用Core Animation的複製器圖層,我設法創造了這個結果: enter image description here

我認爲它接近你的期望。在這個例子中,所有圖像都是正方形的,每個圖像都應用3d X旋轉。

#import <QuartzCore/QuartzCore.h>  


//set the number of images and the diameter (width) of the circle 
int numberOfImages = 30; 
float diameter = 450.0f; 

//get the radius, circumference and image size 
float radius = diameter/2; 
float circumference = M_PI * diameter; 
float imageSize = circumference/numberOfImages; 

//create a replicator layer and add it to our view 
CAReplicatorLayer *replicator = [CAReplicatorLayer layer]; 
replicator.frame = CGRectMake(100.0f, 100.0f, diameter, diameter); 
[self.view.layer addSublayer:replicator]; 

//configure the replicator 
replicator.instanceCount = numberOfImages; 

//apply a rotation transform for each instance 
CATransform3D transform = CATransform3DIdentity; 
transform = CATransform3DRotate(transform, M_PI/(numberOfImages/2), 0, 0, 1); 
replicator.instanceTransform = transform; 

//create a sublayer and place it inside the replicator 
CALayer *layer = [CALayer layer]; 
//the frame places the layer in the middle of the replicator layer and on the outside of the replicator layer so that the the size is accurate relative to the circumference 
layer.frame = CGRectMake(radius - (imageSize/2), -imageSize/2, imageSize, imageSize); 
layer.anchorPoint = CGPointMake(0.5, 1); 
[replicator addSublayer:layer]; 

//apply a perspective transofrm to the layer 
CATransform3D perspectiveTransform = CATransform3DIdentity; 
perspectiveTransform.m34 = 1.0f/-radius; 
perspectiveTransform = CATransform3DRotate(perspectiveTransform, (M_PI_4), -1, 0, 0); 
layer.transform = perspectiveTransform; 

//set the image as the layer's contents 
layer.contents = (__bridge id)[UIImage imageNamed:@"WCR3Q"].CGImage; 
+0

山姆你搖滾!我會延遲接受你的答案,直到我被允許授予你獎金(明天)。謝謝! –

+0

所以我不得不等待2天來設定賞金,現在我必須等待24小時才能獲得獎勵!大聲笑 –

+0

感謝設置賞金,我只是很高興代碼幫助。 – Sam