我的目標是把一個模式像這樣沿路徑繪製圖案
,並多次繪製沿圓形路徑產生類似這樣的形象的東西:
我在其他問題和完整演示項目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;
}
恐怕你要做的事情是一件非常複雜的事情,因爲模式是如何在圓圈內部被壓縮的並且在外面被拉伸。你可能不得不下降到OpenGL來實現它。 –
是的,我畫出了一些代碼來做一個矩形到變形弧的轉換,但希望不必寫它大聲笑 –