27

簡単な線を引く方法を知っています:

CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextMoveToPoint(context, x, y);
CGContextAddLineToPoint(context, x2, y2);
CGContextStrokePath(context);

そして、グラデーションの長方形を作成する方法を知っています.ig:

CGColorSpaceRef myColorspace=CGColorSpaceCreateDeviceRGB();
size_t num_locations = 2;
CGFloat locations[2] = { 1.0, 0.0 };
CGFloat components[8] = { 0.0, 0.0, 0.0, 1.0,    1.0, 1.0, 1.0, 1.0 };

CGGradientRef myGradient = CGGradientCreateWithColorComponents(myColorspace, components, locations, num_locations);

CGPoint myStartPoint, myEndPoint;
myStartPoint.x = 0.0;
myStartPoint.y = 0.0;
myEndPoint.x = 0.0;
myEndPoint.y = 10.0;
CGContextDrawLinearGradient (context, myGradient, myStartPoint, myEndPoint, 0);

しかし、どうすればグラデーションで線を描くことができますか?

4

7 に答える 7

35

グラデーション、またはパターンなどのその他の塗りつぶし効果を使用して、任意のパスをストロークすることができます。

おわかりのように、ストローク パスは現在のグラデーションではレンダリングされません。塗りつぶされたパスのみがグラデーションを使用します (パスをクリップにしてからグラデーションを描画する場合)。

ただし、Core Graphics には、ストロークしようとしているパスを、塗りつぶしたときに同等CGContextReplacePathWithStrokedPathのパスに変換する驚くほどクールな手順があります。

バックグラウンドで、CGContextReplacePathWithStrokedPathストローク パスの周囲にエッジ ポリゴンを構築し、定義したパスに切り替えます。Core Graphics レンダリング エンジンはおそらくCGContextStrokePath.

これに関するAppleのドキュメントは次のとおりです。

Quartz は、現在のグラフィックス コンテキストのパラメータを使用してストローク パスを作成します。新しいパスが作成されるため、塗りつぶすと元のパスをストロークするのと同じピクセルが描画されます。このパスは、任意のコンテキストのパスを使用するのと同じ方法で使用できます。たとえば、この関数を呼び出してから関数 CGContextClip を呼び出すと、パスのストローク バージョンにクリップできます。

したがって、パスを塗りつぶせるものに変換し、それをクリップに変換してから、グラデーションを描画します。グラデーションでパスをなぞったような効果が得られます。

コード

次のようになります…</p>

    // Get the current graphics context.
    //
    const CGContextRef context = UIGraphicsGetCurrentContext();

    // Define your stroked path. 
    //
    // You can set up **anything** you like here.
    //
    CGContextAddRect(context, yourRectToStrokeWithAGradient);

    // Set up any stroking parameters like line.
    //
    // I'm setting width. You could also set up a dashed stroke
    // pattern, or whatever you like.
    //
    CGContextSetLineWidth(context, 1);

    // Use the magical call.
    //
    // It turns your _stroked_ path in to a **fillable** one.
    //
    CGContextReplacePathWithStrokedPath(context);

    // Use the current _fillable_ path in to define a clipping region.
    //
    CGContextClip(context);

    // Draw the gradient.
    //
    // The gradient will be clipped to your original path.
    // You could use other fill effects like patterns here.
    //
    CGContextDrawLinearGradient(
      context, 
      yourGradient, 
      gradientTop, 
      gradientBottom, 
      0
    );

その他の注意事項

上記のドキュメントの一部を強調する価値があります。

Quartz は、現在のグラフィック コンテキストのパラメータを使用してストローク パスを作成します。

明らかなパラメータは線幅です。ただし、ストローク パターン、マイター リミット、ライン ジョイン、キャップ、ダッシュ パターンなど、すべての線描画状態が使用されます。これにより、アプローチは非常に強力になります。

詳細については、この SO questionのこの回答を参照してください。

于 2014-07-30T10:47:21.633 に答える
20

何度か試した結果、グラデーションがストロークに影響を与えないことがわかったので、 でグラデーション線を描くことは不可能だと思いますCGContextStrokePath()。水平線と垂直線の場合、解決策はCGContextAddRect()代わりに使用することです。幸いなことに、これが必要です。交換しました

CGContextMoveToPoint(context, x, y);
CGContextAddLineToPoint(context, x2, y2);
CGContextStrokePath(context);

CGContextSaveGState(context);
CGContextAddRect(context, CGRectMake(x, y, width, height));
CGContextClip(context);
CGContextDrawLinearGradient (context, gradient, startPoint, endPoint, 0);
CGContextRestoreGState(context);

すべてが正常に動作します。重要なヒントをくれた Brad Larson に感謝します。

于 2009-08-20T16:42:52.920 に答える
8

線を引いた後、呼び出すことができます

CGContextClip(context);

さらに描画をライン領域にクリップします。グラデーションを描画すると、線の領域内に含まれるようになります。グラデーションを表示したいだけで、その下の線ではなく、線に透明な色を使用する必要があることに注意してください。

線が細すぎてグラデーションが表示されない可能性があります。その場合は、 を使用CGContextAddRect()してより太い領域を定義できます。

ここでの回答で、このコンテキスト クリッピングを使用したより精巧な例を示します。

于 2009-08-20T12:50:31.683 に答える
8

Core Animation レイヤーを使用できます。path プロパティを設定することにより、ラインにCAShaperLayerを使用できます。次に、 CAGradientLayerをシェープ レイヤーのレイヤー マスクとして使用して、ラインをフェードさせることができます。

CGContext... 呼び出しを CGPath... 呼び出しに置き換えて、ライン パスを作成します。そのパスを使用してレイヤーにパス フィールドを設定します。次に、グラデーションレイヤーで、使用する色(おそらく黒から白)を指定し、次のようにマスクを線レイヤーに設定します。

 [gradientLayer setMask:lineLayer];

グラデーション レイヤーの優れた点は、グラデーションが停止する場所のリストを指定できるため、フェード インとフェード アウトできることです。線形グラデーションのみをサポートしていますが、ニーズに合うように思えます。

説明が必要な場合はお知らせください。

編集:考えてみると、希望する線の幅/高さである単一の CAGradientLayer を作成するだけです。グラデーション カラー (黒から白、または黒からクリア カラー) と startPoint および endtPoints を指定すると、必要なものが得られます。

于 2009-08-20T04:28:01.843 に答える
0
CGContextMoveToPoint(context, frame.size.width-200, frame.origin.y+10);
CGContextAddLineToPoint(context, frame.size.width-200, 100-10);
CGFloat colors[16] = { 0,0, 0, 0,
    0, 0, 0, .8,
    0, 0, 0, .8,
    0, 0,0 ,0 };
CGColorSpaceRef baseSpace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColorComponents(baseSpace, colors, NULL, 4);

CGContextSaveGState(context);
CGContextAddRect(context, CGRectMake(frame.size.width-200,10, 1, 80));
CGContextClip(context);
CGContextDrawLinearGradient (context, gradient, CGPointMake(frame.size.width-200, 10), CGPointMake(frame.size.width-200,80), 0);
CGContextRestoreGState(context);

私のための仕事。

于 2012-05-30T06:55:31.130 に答える