2012-03-22 8 views
2

私はコアグラフィックスを使用して、iphoneで丸い四角いフローティングダイアログを作成しています。ストロークを同心円の丸い矩形のパスに沿って適用すると、ストローク間のギャップが必ずコーナーに表示されます。これらの同じストロークは、直線セグメント上に並んで座っている。コアグラフィックス:ストローク時の丸いパス間のギャップ

コードから該当の抜粋(無関係なコードを除去):

-(void)drawRect:(CGRect)rect { 
    CGRect borderRect = CGRectInset(rect, 1.0, 1.0); 
    UIBezierPath *borderPath = [UIBezierPath bezierPathWithRoundedRect:borderRect cornerRadius:6.0]; 
    [...] 
    CGContextSetStrokeColorWithColor(context, bevelStrokeColor); 
    CGContextSetLineWidth(context, 2.0); 
    CGContextAddPath(context, borderPath.CGPath); 
    CGContextStrokePath(context); 
    [...] 
    CGRect inlayRect = CGRectInset(rect, inlayPathInset, inlayPathInset); 
    UIBezierPath *inlayPath = [UIBezierPath bezierPathWithRoundedRect:inlayRect cornerRadius:6.0]; 
    [...] 
    CGContextSetStrokeColorWithColor(context, inlayStrokeColor); 
    CGContextSetLineWidth(context, 2.0); 
    CGContextAddPath(context, inlayPath.CGPath); 
    CGContextStrokePath(context); 
    [...] 
} 

ここで、画像の:私は上記の投稿コードの異なるバージョンを試みた

enter image description here

。私はパスを手動で作成し、UIBezierPathインスタンスメソッドを使用して作成と描画を行いました。ビューのレイヤーとさまざまな組み合わせでいくつかのアイデアを使ってcornerRadiusを設定しました。彼らの中には問題を改善した人もいたが、その撤回は間に合わなかった。

私は境界線を使用していただけで気にしませんでしたが、いくつかの同心円の丸い四角形がありますので、このギャップも問題になります。

編集:転記時に発生したコードの入力ミスを修正しました。

+1

ちょうど私があなたのコードに問題が表示されていないと絵から言うことができないので、ここでは推測の話が、どのような値が変数 'cornerRadius'でインスタンス化するとき' inlayPath'?ボーダーパスのような6.0かもしれませんか? borderPathの内側の半径は外側よりも小さいことに注意してください。したがって、inlayPathsコーナー半径は6.0未満である必要があります。それ以上であれば、目に見える効果があります。 – pkluz

+0

私はそれを6.0に編集するのを忘れていました。私は他のパス初期化からそれを取り出した。彼らはどちらも6歳ですが、それは正しいことではありません。私は今、それの背後にある数学を導き出すことを試みています。私が何かを思い付くなら、私は分かち合う。 – RGuy8032

答えて

2

この場合、2番目のコーナー半径をinlaypathinsetで減算する必要があります。内側の半径は小さくなければならず、さもなければ円のセグメントは正確に同心円ではない。

同心円の隣に、丸い長方形の両方を接触させたい場合は、両方の線幅の平均値を挿入する必要があります。

+0

私は答えを見つけました。これは間違っています。半径は確かに減少しなければならないが、関係ははるかに数学的に美しい。私はSOが許しているときに3時間で私を郵送します。 – RGuy8032

+0

私は私の答えをかなり確信しているので、私は不思議です:-) –

+0

あなたは正しい道にあります。あなたが私が間違っていることを私に納得させることができれば、私はその点を喜んで認めます。すぐに私の答え。 – RGuy8032

2

lineWidthがすべてのストロークで同じ場合は、innerCornerRadiusから(outerCornerRadius - lineWidth)に設定すると効果が得られます。特別な場合です。あなたが次のことを信じていないなら、私はそれを試してみることをお勧めします。

リットル I =線が内側

リットル O =行が

内側外側

R I =コーナー半径幅幅:これを支配する実際の関係は以下のように思えます

r e =コーナー半径外側

リットル I/2 + R I = R O - L したがって/2

O: R I = R O - (L iは/2 + L/2 O

をL 場合、I = L O = 1:R I = R O - L

/* 
The following should be inserted into a UIView subclass that has a size of ~280, ~200. 

lineWidthInner/2 + radiusInner = radiusOuter - lineWidthOuter/2 
radiusInner = radiusOuter - (lineWidthOuter + lineWidthInner)/2 

That is to say that the inner corner radius is equal to the outer corner radius 
    minus the average of the lineWidth's. 


innerInsetMargin = outerInsetMargin + (lineWidthOuter + lineWidthInner)/2 

The amount a line must be inset (insetMargin) is the previous line's insetMargin + the 
    average of the previous and current lineWidth's. In the case in which the 
    outermost line's outer edge touches the bound of rect, the insetMargin is equal 
    to the sum of all previous lineWidth's plus half of the current lineWidth. 

Shutting off anti-aliasing is required to prevent alpha-blending of the non-rectilinear 
    parts of the line with the background. I am not sure how to gracefully sidestep this. 
    Insights into this would be appreciated. 
*/ 
-(void)drawRect:(CGRect)rect { 
    CGContextRef context = UIGraphicsGetCurrentContext(); 

    CGContextSetFillColorWithColor(context, UIColor.blackColor.CGColor); 
    CGContextFillRect(context, rect); 
    CGContextSetShouldAntialias(context,NO); 

    NSArray *colors = [NSArray arrayWithObjects: 
         (id)UIColor.greenColor.CGColor, 
         (id)UIColor.lightGrayColor.CGColor, 
         (id)UIColor.yellowColor.CGColor, 
         (id)UIColor.blueColor.CGColor, 
         (id)UIColor.redColor.CGColor, nil]; 

    //Change lineWidth, lineWidthIncrement, or currentCornerRadius as you see fit 
    CGFloat lineWidthIncrement = 1.0; 
    CGFloat lineWidth = 10.0; 
    CGFloat currentCornerRadius = 100.0; 
    CGFloat insetMargin = lineWidth/2; 

    do { 
     CGContextSaveGState(context); 
     CGContextSetStrokeColorWithColor(context, (CGColorRef)[colors objectAtIndex:(lcv % colors.count)]); 
     CGContextSetLineWidth(context, lineWidth); 
     CGContextAddPath(context, [UIBezierPath bezierPathWithRoundedRect:CGRectInset(rect, insetMargin, insetMargin) cornerRadius:currentCornerRadius].CGPath); 
     CGContextStrokePath(context); 
     CGContextRestoreGState(context); 

     lineWidth += lineWidthIncrement; 
     currentCornerRadius -= 0.5 * (lineWidth + (lineWidth - lineWidthIncrement));//-0.5*(lwi+lwo) 
     insetMargin += 0.5 * (lineWidth + (lineWidth - lineWidthIncrement)); 

    } while(currentCornerRadius>0); 

} 
関連する問題