1

私はクォーツの描画の経験がありません。

コールアウトビューに長方形を描画する必要があります。私はそれを描くためのいくつかのサンプルコードを見つけました。

そのための私の現在のコードは

- (void)drawRect:(CGRect)rect {
    CGFloat stroke = 1.0;
    CGFloat radius = 7.0;
    CGMutablePathRef path = CGPathCreateMutable();
    UIColor *color;
    CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGFloat parentX = [self relativeParentXPosition];

    //Determine Size
    rect = self.bounds;
    rect.size.width -= stroke + 14;
    rect.size.height -= stroke + 14 + CalloutMapAnnotationViewHeightAboveParent;
    rect.origin.x += stroke / 2.0 + 7;
    rect.origin.y += stroke / 2.0 + 7;

    //Create Path For Callout Bubble
    CGPathMoveToPoint(path, NULL, rect.origin.x, rect.origin.y + radius);
    CGPathAddLineToPoint(path, NULL, rect.origin.x, rect.origin.y + rect.size.height - radius);
    CGPathAddArc(path, NULL, rect.origin.x + radius, rect.origin.y + rect.size.height - radius, radius, 0.0f, M_PI / 2, 1);
    CGPathAddLineToPoint(path, NULL, parentX - 15, rect.origin.y + rect.size.height);
    CGPathAddLineToPoint(path, NULL, parentX, rect.origin.y + rect.size.height + 15);
    CGPathAddLineToPoint(path, NULL, parentX + 15, rect.origin.y + rect.size.height);
    CGPathAddLineToPoint(path, NULL, rect.origin.x + rect.size.width - radius, rect.origin.y + rect.size.height);
    CGPathAddArc(path, NULL, rect.origin.x + rect.size.width - radius, rect.origin.y + rect.size.height - radius, radius, M_PI / 2, 0.0f, 1);
    CGPathAddLineToPoint(path, NULL, rect.origin.x + rect.size.width, rect.origin.y + radius);
    CGPathAddArc(path, NULL, rect.origin.x + rect.size.width - radius, rect.origin.y + radius, radius, 0.0f, -M_PI / 2, 1);
    CGPathAddLineToPoint(path, NULL, rect.origin.x + radius, rect.origin.y);
    CGPathAddArc(path, NULL, rect.origin.x + radius, rect.origin.y + radius, radius, -M_PI / 2, M_PI, 1);
    CGPathCloseSubpath(path);

    //Fill Callout Bubble & Add Shadow
    color = [[UIColor blackColor] colorWithAlphaComponent:.6];
    [color setFill];
    CGContextAddPath(context, path);
    CGContextSaveGState(context);
    CGContextSetShadowWithColor(context, CGSizeMake (0, self.yShadowOffset), 6, [UIColor colorWithWhite:0 alpha:.5].CGColor);
    CGContextFillPath(context);
    CGContextRestoreGState(context);

    //Stroke Callout Bubble
    color = [[UIColor darkGrayColor] colorWithAlphaComponent:.9];
    [color setStroke];
    CGContextSetLineWidth(context, stroke);
    CGContextSetLineCap(context, kCGLineCapSquare);
    CGContextAddPath(context, path);
    CGContextStrokePath(context);

    //Determine Size for Gloss
    CGRect glossRect = self.bounds;
    glossRect.size.width = rect.size.width - stroke;
    glossRect.size.height = (rect.size.height - stroke) / 2;
    glossRect.origin.x = rect.origin.x + stroke / 2;
    glossRect.origin.y += rect.origin.y + stroke / 2;

    CGFloat glossTopRadius = radius - stroke / 2;
    CGFloat glossBottomRadius = radius / 1.5;

    //Create Path For Gloss


    CGMutablePathRef glossPath = CGPathCreateMutable();
    CGPathMoveToPoint(glossPath, NULL, glossRect.origin.x, glossRect.origin.y + glossTopRadius);
    CGPathAddLineToPoint(glossPath, NULL, glossRect.origin.x, glossRect.origin.y + glossRect.size.height - glossBottomRadius);
    CGPathAddArc(glossPath, NULL, glossRect.origin.x + glossBottomRadius, glossRect.origin.y + glossRect.size.height - glossBottomRadius, glossBottomRadius, M_PI, M_PI / 2, 1);
    CGPathAddLineToPoint(glossPath, NULL, glossRect.origin.x + glossRect.size.width - glossBottomRadius, glossRect.origin.y + glossRect.size.height);
    CGPathAddArc(glossPath, NULL, glossRect.origin.x + glossRect.size.width - glossBottomRadius, glossRect.origin.y + glossRect.size.height - glossBottomRadius, glossBottomRadius, M_PI / 2, 0.0f, 1);
    CGPathAddLineToPoint(glossPath, NULL, glossRect.origin.x + glossRect.size.width, glossRect.origin.y + glossTopRadius);
    CGPathAddArc(glossPath, NULL, glossRect.origin.x + glossRect.size.width - glossTopRadius, glossRect.origin.y + glossTopRadius, glossTopRadius, 0.0f, -M_PI / 2, 1);
    CGPathAddLineToPoint(glossPath, NULL, glossRect.origin.x + glossTopRadius, glossRect.origin.y);
    CGPathAddArc(glossPath, NULL, glossRect.origin.x + glossTopRadius, glossRect.origin.y + glossTopRadius, glossTopRadius, -M_PI / 2, M_PI, 1);
    CGPathCloseSubpath(glossPath);

    //Fill Gloss Path   
    CGContextAddPath(context, glossPath);
    CGContextClip(context);
    CGFloat colors[] =
    {
        1, 1, 1, .3,
        1, 1, 1, .1,
    };
    CGFloat locations[] = { 0, 1.0 };
    CGGradientRef gradient = CGGradientCreateWithColorComponents(space, colors, locations, 2);
    CGPoint startPoint = glossRect.origin;
    CGPoint endPoint = CGPointMake(glossRect.origin.x, glossRect.origin.y + glossRect.size.height);
    CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);

    //Gradient Stroke Gloss Path    
    CGContextAddPath(context, glossPath);
    CGContextSetLineWidth(context, 2);
    CGContextReplacePathWithStrokedPath(context);
    CGContextClip(context);
    CGFloat colors2[] =
    {
        1, 1, 1, .3,
        1, 1, 1, .1,
        1, 1, 1, .0,
    };
    CGFloat locations2[] = { 0, .1, 1.0 };
    CGGradientRef gradient2 = CGGradientCreateWithColorComponents(space, colors2, locations2, 3);
    CGPoint startPoint2 = glossRect.origin;
    CGPoint endPoint2 = CGPointMake(glossRect.origin.x, glossRect.origin.y + glossRect.size.height);
    CGContextDrawLinearGradient(context, gradient2, startPoint2, endPoint2, 0);

    //Cleanup
    CGPathRelease(path);
    CGPathRelease(glossPath);
    CGColorSpaceRelease(space);
    CGGradientRelease(gradient);
    CGGradientRelease(gradient2);
}

これは私が得ている現在のコールアウトです

これは私が取得している現在のコールアウトですが、長方形の上部の端にその三角形を描く必要があります。

変更する必要があるこれらの2つの2行をスタッズすることによって

CGPathAddLineToPoint(path, NULL, parentX - 15, rect.origin.y + rect.size.height);
        CGPathAddLineToPoint(path, NULL, parentX, rect.origin.y + rect.size.height + 15);

しかし、私はクォーツグラフィックが苦手です。

必要なコールアウトは下の画像のようです

ここに画像の説明を入力してください

三角形は、コールアウトビューの上方にある必要があります。

クォーツグラフィックの知識がある人は私を助けてください。

4

1 に答える 1

1

さて、あなたが一番上にあるコールアウトを探しているなら、これを試してください。コールアウトバブルのパスを次のように置き換えます。

//Determine Size
    rect = self.bounds;
    rect.size.width -= stroke + 14;
    rect.size.height -= stroke + 14 + CalloutMapAnnotationViewHeightAboveParent;
    rect.origin.x += stroke / 2.0 + 7;
    rect.origin.y += stroke / 2.0 + 7 + 14;    

//Create Path For Callout Bubble
        CGPathMoveToPoint(path, NULL, rect.origin.x, rect.origin.y + radius);
        CGPathAddLineToPoint(path, NULL, rect.origin.x, rect.origin.y + rect.size.height - radius); //Left line
        CGPathAddArc(path, NULL, rect.origin.x + radius, rect.origin.y + rect.size.height - radius, radius, 0.0f, M_PI / 2, 1); //Bottom left arc
    //    CGPathAddLineToPoint(path, NULL, parentX - 15, rect.origin.y + rect.size.height); //bottom to callout line
    //    CGPathAddLineToPoint(path, NULL, parentX, rect.origin.y + rect.size.height + 15); //callout left
    //    CGPathAddLineToPoint(path, NULL, parentX + 15, rect.origin.y + rect.size.height); //callout right
        CGPathAddLineToPoint(path, NULL, rect.origin.x + rect.size.width - radius, rect.origin.y + rect.size.height); //bottom to right line
        CGPathAddArc(path, NULL, rect.origin.x + rect.size.width - radius, rect.origin.y + rect.size.height - radius, radius, M_PI / 2, 0.0f, 1); //bottom right
        CGPathAddLineToPoint(path, NULL, rect.origin.x + rect.size.width, rect.origin.y + radius); //right line
        CGPathAddArc(path, NULL, rect.origin.x + rect.size.width - radius, rect.origin.y + radius, radius, 0.0f, -M_PI / 2, 1); //top right
        CGPathAddLineToPoint(path, NULL, parentX + 15, rect.origin.y); //top right to right callout
        CGPathAddLineToPoint(path, NULL, parentX, rect.origin.y - 15); //callout right
        CGPathAddLineToPoint(path, NULL, parentX - 15, rect.origin.y); //callout left
        CGPathAddLineToPoint(path, NULL, rect.origin.x + radius, rect.origin.y); //top left callout to top left
        CGPathAddArc(path, NULL, rect.origin.x + radius, rect.origin.y + radius, radius, -M_PI / 2, M_PI, 1); //top left
        CGPathCloseSubpath(path); //Path closed, no line draw

私はこれがうまくいくはずだと信じています(まだテストしていません)。ただし、グロスパスは、使用されているコールアウトrectに依存しているため、他のすべては正常に機能するはずです。

ちなみに、Core Graphicsには、一枚の紙に描くようなパスを描くことが含まれます。CGPathMoveToPointには、鉛筆を下に置くことが含まれます。その後はすべて、線または円弧を順番に描画します。あなたがする必要があるのは、線/曲線が描かれている点を読むことだけです。円弧は曲線に変換されますが、それらを読み取るには、pi、pi / 2、およびpi/4が単位円のどこにあるかを知る必要があることに注意してください。これにより、円弧が描画されている場所がわかります。ただし、一般に、(少なくともこの場合は)円弧は前の線が引かれた実際のコーナーに対応していると想定できます。ボックスのどの部分にどのパス要素が対応するかを示すコメントを追加しました。また、下部のコールアウトを削除するのではなくコメントアウトしました。コメントを外して、一番下のコールアウトを再度描画することはできますが、上部をコメントアウトし、rectを上にシフトすることを忘れないでください(私はそれを14シフトしました)。また、コールアウトのサイズ(15)などの「マジックナンバー」の使用を避け、代わりに次のようなものをファイルに入れることを検討してください。

#define CalloutSize 15.0f

これをCalloutSize実行してコードに挿入するのではなく、15使用されている各インスタンスを検索しなくても、サイズを簡単に変更できます。

于 2012-05-01T15:22:50.657 に答える