Ios 沿路径绘制图案

Ios 沿路径绘制图案,ios,iphone,design-patterns,path,core-graphics,Ios,Iphone,Design Patterns,Path,Core Graphics,我的目标是采取这样的模式 并沿圆形路径反复绘制,以生成类似于此图像的内容: 我在其他问题和完整演示项目中找到了几个代码示例,但结果如下: 我认为这两幅图像之间的差异是显而易见的,但我发现很难描述(请原谅我缺乏图形词汇)。结果似乎是平铺而没有所需的图案旋转/变形。我想我可以在没有变形的情况下生活,但旋转是关键。我认为也许可以/应该修改draw回调以包含旋转,但不知道如何检索/确定回调点处的角度 我考虑了一种方法,手动变形/旋转图像,并围绕中心点绘制几次,以达到我想要的效果,但我相信CoreG

我的目标是采取这样的模式

并沿圆形路径反复绘制,以生成类似于此图像的内容:

我在其他问题和完整演示项目中找到了几个代码示例,但结果如下:

我认为这两幅图像之间的差异是显而易见的,但我发现很难描述(请原谅我缺乏图形词汇)。结果似乎是平铺而没有所需的图案旋转/变形。我想我可以在没有变形的情况下生活,但旋转是关键。我认为也许可以/应该修改draw回调以包含旋转,但不知道如何检索/确定回调点处的角度

我考虑了一种方法,手动变形/旋转图像,并围绕中心点绘制几次,以达到我想要的效果,但我相信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;

}
。来自SAM的解决方案

我修改了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;
}

使用Core Animation的replicator层,我成功创建了以下结果:

我想这很接近你想要的。在本例中,所有图像均为正方形,并对每个图像应用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;
#导入
//设置图像的数量和圆的直径(宽度)
int numberOfImages=30;
浮子直径=450.0f;
//获取半径、周长和图像大小
浮动半径=直径/2;
浮子周长=M_PI*直径;
浮动图像大小=周长/图像数;
//创建一个replicator层并将其添加到我们的视图中
CAReplicatorLayer*复制器=[CAReplicatorLayer层];
replicator.frame=CGRectMake(100.0f,100.0f,直径,直径);
[self.view.layer addSublayer:replicator];
//配置复制器
replicator.instanceCount=numberOfImages;
//为每个实例应用旋转变换
CATTransferorM3D transform=CATTransferorM3D实体;
transform=cattransform3drotate(transform,M_PI/(numberOfImages/2),0,0,1);
replicator.instanceTransform=转换;
//创建一个子层并将其放置在replicator中
CALayer*层=[CALayer层];
//框架将层置于复制器层的中间和复制器层的外部,使得该尺寸相对于圆周是准确的。
layer.frame=CGRectMake(半径-(imageSize/2),-imageSize/2,imageSize,imageSize);
layer.anchorPoint=CGPointMake(0.5,1);
[复制子添加子层:层];
//将透视变换应用于图层
CATTransferM3D透视变换=CATTransferM3D透视变换实体;
透视变换.m34=1.0f/-半径;
透视变换=CATTransferoM3Drotate(透视变换,(M_PI_4),-1,0,0);
layer.transform=透视变换;
//将图像设置为图层的内容
layer.contents=(uu桥id)[UIImage ImageName:@“WCR3Q”].CGImage;

恐怕您要做的是一件非常复杂的事情,因为图案是在圆圈内部压缩,在圆圈外部拉伸的。你可能需要下载到OpenGL来实现它。是的,我草拟了一些代码来完成从矩形到变形圆弧的转换,但是我希望不用写它。哈哈,你太棒了!我将推迟接受你的回答,直到我被允许(明天)给你一笔赏金。谢谢所以我不得不等了2天才能拿到奖金,现在我要等24小时才能拿到奖金!谢谢你的赏金,我很高兴代码能帮上忙。你让“不可能”成为可能。很高兴你愿意分享你的知识+1.