2014-03-13 121 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