ios - 沿路径绘制图案

标签 ios iphone design-patterns path core-graphics

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

enter image description here

并沿着圆形路径重复绘制它以产生类似于此图像的东西:

enter image description here

我在其他问题中找到了几个代码示例和一个完整的演示项目 here但结果是这样的:

enter image description here

我认为两个图像之间的区别很明显,但我发现很难描述(请原谅我缺乏图形词汇)。结果似乎是平铺,没有所需的图案旋转/变形。我想我可以忍受没有变形,但旋转是关键。我认为也许可以/应该修改绘制回调以包括旋转,但无法弄清楚如何检索/确定回调点的角度。

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

关于ios - 沿路径绘制图案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22386910/

相关文章:

ios - ios应用程序在后台运行时如何打开sqlite数据库

iOS 刷新 map View 上的注释

java - 子类如何在双胞胎设计模式中进行交流?

c# - 在已经正常运行的应用程序中的 WPF/C# 中撤消重做

ios - 快速在特定数组元素中添加值

ios - 使用 Storyboard 时使用 UITabBarController 在 View 之间传递数据

iphone - mac上的iOS模拟器运行的是i386架构,不是armv7?

iphone - 核心数据列表实体名称

iphone - 如果我在调用 textFieldShouldReturn 时返回 "YES"或 "NO"有什么区别

java双重双重检查单例实例错误