SkiaSharp 원형 그라데이션

Download Sample 샘플 다운로드

클래스는 SKShader 네 가지 유형의 그라데이션을 만드는 정적 메서드를 정의합니다. SkiaSharp 선형 그라데이션 문서에서는 이 메서드에 대해 CreateLinearGradient 설명합니다. 이 문서에서는 원을 기반으로 하는 다른 세 가지 유형의 그라데이션에 대해 설명합니다.

이 메서드는 CreateRadialGradient 원 가운데에서 나오는 그라데이션을 만듭니다.

Radial Gradient Sample

이 메서드는 CreateSweepGradient 원의 가운데를 스윕하는 그라데이션을 만듭니다.

Sweep Gradient Sample

그라데이션의 세 번째 유형은 매우 특이합니다. 2포인트 원뿔 그라데이션이라고 하며 메서드에 CreateTwoPointConicalGradient 의해 정의됩니다. 그라데이션은 한 원에서 다른 원으로 확장됩니다.

Conical Gradient Sample

두 원의 크기가 서로 다른 경우 그라데이션은 원뿔의 형태를 취합니다.

이 문서에서는 이러한 그라데이션을 자세히 살펴봅니다.

방사형 그라데이션

메서드 CreateRadialGradient 의 구문은 다음과 같습니다.

public static SKShader CreateRadialGradient (SKPoint center, 
                                             Single radius, 
                                             SKColor[] colors, 
                                             Single[] colorPos, 
                                             SKShaderTileMode mode)

오버로드에는 CreateRadialGradient 변환 매트릭스 매개 변수도 포함됩니다.

처음 두 인수는 원과 반지름의 중심을 지정합니다. 그라데이션은 해당 가운데에서 시작하여 픽셀에 대해 radius 바깥쪽으로 확장됩니다. 그 이상으로 radius 일어나는 일은 인수에 SKShaderTileMode 따라 달라집니다. colors 매개 변수는 선형 그라데이션 메서드와 마찬가지로 두 개 이상의 색 배열이며 colorPos 0~1 범위의 정수 배열입니다. 이러한 정수는 해당 radius 선을 따라 색의 상대 위치를 나타냅니다. 해당 인수를 색의 간격을 null 동일하게 설정할 수 있습니다.

원을 채우는 데 사용하는 CreateRadialGradient 경우 그라데이션의 중심을 원 가운데로 설정하고 그라데이션의 반지름을 원의 반지름으로 설정할 수 있습니다. 이 경우 SKShaderTileMode 인수는 그라데이션 렌더링에 영향을 주지 않습니다. 그러나 그라데이션으로 채워진 영역이 그라데이션 SKShaderTileMode 에 정의된 원보다 크면 인수가 원 외부에서 발생하는 일에 큰 영향을 미칩니다.

그 효과는 SKShaderMode SkiaSharpFormsDemos 샘플의 방사형 그라데이션 페이지에서 보여 줍니다. 이 페이지의 XAML 파일은 열거형의 SKShaderTileMode 세 멤버 중 하나를 선택할 수 있는 인스턴스화 Picker 합니다.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:skia="clr-namespace:SkiaSharp;assembly=SkiaSharp"
             xmlns:skiaforms="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
             x:Class="SkiaSharpFormsDemos.Effects.RadialGradientPage"
             Title="Radial Gradient">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <skiaforms:SKCanvasView x:Name="canvasView"
                                Grid.Row="0"
                                PaintSurface="OnCanvasViewPaintSurface" />

        <Picker x:Name="tileModePicker" 
                Grid.Row="1"
                Title="Shader Tile Mode" 
                Margin="10"
                SelectedIndexChanged="OnPickerSelectedIndexChanged">
            <Picker.ItemsSource>
                <x:Array Type="{x:Type skia:SKShaderTileMode}">
                    <x:Static Member="skia:SKShaderTileMode.Clamp" />
                    <x:Static Member="skia:SKShaderTileMode.Repeat" />
                    <x:Static Member="skia:SKShaderTileMode.Mirror" />
                </x:Array>
            </Picker.ItemsSource>

            <Picker.SelectedIndex>
                0
            </Picker.SelectedIndex>
        </Picker>
    </Grid>
</ContentPage>

코드 숨김 파일은 전체 캔버스에 방사형 그라데이션으로 색을 지정합니다. 그라데이션의 중심이 캔버스의 가운데로 설정되고 반지름은 100픽셀로 설정됩니다. 그라데이션은 흑백의 두 가지 색으로 구성됩니다.

public partial class RadialGradientPage : ContentPage
{
    public RadialGradientPage ()
    {
        InitializeComponent ();
    }

    void OnPickerSelectedIndexChanged(object sender, EventArgs args)
    {
        canvasView.InvalidateSurface();
    }

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        SKShaderTileMode tileMode =
            (SKShaderTileMode)(tileModePicker.SelectedIndex == -1 ?
                                        0 : tileModePicker.SelectedItem);

        using (SKPaint paint = new SKPaint())
        {
            paint.Shader = SKShader.CreateRadialGradient(
                                new SKPoint(info.Rect.MidX, info.Rect.MidY),
                                100,
                                new SKColor[] { SKColors.Black, SKColors.White },
                                null,
                                tileMode);

            canvas.DrawRect(info.Rect, paint);
        }
    }
}

이 코드는 중앙에 검은색 그라데이션을 만들어 서서히 가운데에서 흰색 100픽셀로 페이드합니다. 해당 반지름을 넘어서는 작업은 인수에 SKShaderTileMode 따라 달라집니다.

Radial Gradient

세 가지 경우 모두 그라데이션이 캔버스를 채웁니다. 왼쪽의 iOS 화면에서 반경을 벗어난 그라데이션은 흰색인 마지막 색으로 계속됩니다. 그 결과입니다 SKShaderTileMode.Clamp. Android 화면에는 중앙에서 100픽셀의 효과가 SKShaderTileMode.Repeat표시되며 그라데이션은 첫 번째 색인 검은색으로 다시 시작됩니다. 그라데이션은 반경 100픽셀마다 반복됩니다.

오른쪽의 유니버설 Windows 플랫폼 화면은 그라데이션이 대체 방향을 지정하는 방법을 SKShaderTileMode.Mirror 보여 줍니다. 첫 번째 그라데이션은 중앙의 검은색에서 반경 100픽셀의 흰색까지입니다. 다음은 100픽셀 반경에서 검은색으로 200픽셀 반경의 흰색이며, 다음 그라데이션은 다시 반전됩니다.

방사형 그라데이션에서 두 개 이상의 색을 사용할 수 있습니다. 레인보우 아크 그라데이션 샘플은 무지개 색과 빨간색으로 끝나는 8가지 색의 배열과 8개의 위치 값 배열을 만듭니다.

public class RainbowArcGradientPage : ContentPage
{
    public RainbowArcGradientPage ()
    {
        Title = "Rainbow Arc Gradient";

        SKCanvasView canvasView = new SKCanvasView();
        canvasView.PaintSurface += OnCanvasViewPaintSurface;
        Content = canvasView;
    }

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        using (SKPaint paint = new SKPaint())
        {
            float rainbowWidth = Math.Min(info.Width, info.Height) / 4f;

            // Center of arc and gradient is lower-right corner
            SKPoint center = new SKPoint(info.Width, info.Height);

            // Find outer, inner, and middle radius
            float outerRadius = Math.Min(info.Width, info.Height);
            float innerRadius = outerRadius - rainbowWidth;
            float radius = outerRadius - rainbowWidth / 2;

            // Calculate the colors and positions
            SKColor[] colors = new SKColor[8];
            float[] positions = new float[8];

            for (int i = 0; i < colors.Length; i++)
            {
                colors[i] = SKColor.FromHsl(i * 360f / 7, 100, 50);
                positions[i] = (i + (7f - i) * innerRadius / outerRadius) / 7f;
            }

            // Create sweep gradient based on center and outer radius
            paint.Shader = SKShader.CreateRadialGradient(center, 
                                                         outerRadius, 
                                                         colors, 
                                                         positions, 
                                                         SKShaderTileMode.Clamp);
            // Draw a circle with a wide line
            paint.Style = SKPaintStyle.Stroke;
            paint.StrokeWidth = rainbowWidth;

            canvas.DrawCircle(center, radius, paint);
        }
    }
}

캔버스의 너비와 높이의 최소값이 1000이면 값이 rainbowWidth 250입니다. 값과 innerRadius 값은 outerRadius 각각 1000 및 750으로 설정됩니다. 이러한 값은 배열을 계산하는 positions 데 사용됩니다. 8개의 값 범위는 0.75f에서 1입니다. 이 radius 값은 원을 쓰다듬는 데 사용됩니다. 값이 875이면 250픽셀 스트로크 너비가 반경 750픽셀과 반경 1000픽셀 사이로 확장됩니다.

Rainbow Arc Gradient

전체 캔버스를 이 그라데이션으로 채운 경우 내부 반경 내에서 빨간색으로 표시됩니다. 배열이 positions 0으로 시작되지 않기 때문입니다. 첫 번째 색은 첫 번째 배열 값까지 0의 오프셋에 사용됩니다. 그라데이션은 외부 반경을 넘어 빨간색입니다. 타일 모드의 Clamp 결과입니다. 그라데이션은 두꺼운 선을 쓰다듬는 데 사용되므로 이러한 빨간색 영역은 표시되지 않습니다.

마스킹을 위한 방사형 그라데이션

선형 그라데이션과 마찬가지로 방사형 그라데이션은 투명하거나 부분적으로 투명한 색을 통합할 수 있습니다. 이 기능은 이미지의 다른 부분을 강조하기 위해 이미지의 일부를 숨기는 마스킹이라는 프로세스에 유용합니다.

방사형 그라데이션 마스크 페이지에 예제가 표시됩니다. 프로그램은 리소스 비트맵 중 하나를 로드합니다. CENTERRADIUS 필드는 비트맵 검사에서 결정되었으며 강조 표시해야 하는 영역을 참조합니다. PaintSurface 처리기는 비트맵을 표시하기 위해 직사각형을 계산한 다음 해당 사각형에 표시합니다.

public class RadialGradientMaskPage : ContentPage
{
    SKBitmap bitmap = BitmapExtensions.LoadBitmapResource(
        typeof(RadialGradientMaskPage),
        "SkiaSharpFormsDemos.Media.MountainClimbers.jpg");

    static readonly SKPoint CENTER = new SKPoint(180, 300);
    static readonly float RADIUS = 120;

    public RadialGradientMaskPage ()
    {
        Title = "Radial Gradient Mask";

        SKCanvasView canvasView = new SKCanvasView();
        canvasView.PaintSurface += OnCanvasViewPaintSurface;
        Content = canvasView;
    }

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        // Find rectangle to display bitmap
        float scale = Math.Min((float)info.Width / bitmap.Width,
                                (float)info.Height / bitmap.Height);

        SKRect rect = SKRect.Create(scale * bitmap.Width, scale * bitmap.Height);

        float x = (info.Width - rect.Width) / 2;
        float y = (info.Height - rect.Height) / 2;
        rect.Offset(x, y);

        // Display bitmap in rectangle
        canvas.DrawBitmap(bitmap, rect);

        // Adjust center and radius for scaled and offset bitmap
        SKPoint center = new SKPoint(scale * CENTER.X + x,
                                     scale * CENTER.Y + y);
        float radius = scale * RADIUS;

        using (SKPaint paint = new SKPaint())
        {
            paint.Shader = SKShader.CreateRadialGradient(
                                center,
                                radius,
                                new SKColor[] { SKColors.Transparent,
                                                SKColors.White },
                                new float[] { 0.6f, 1 },
                                SKShaderTileMode.Clamp);

            // Display rectangle using that gradient
            canvas.DrawRect(rect, paint);
        }
    }
}

비트맵을 그린 후 일부 간단한 코드는 비트맵에서 강조 표시된 영역을 변환 CENTER 하고 RADIUScenterradius표시하기 위해 이동한 영역을 나타냅니다. 이러한 값은 해당 가운데 및 반지름을 사용하여 방사형 그라데이션을 만드는 데 사용됩니다. 두 색은 가운데에서 투명하고 반경의 처음 60%에서 시작합니다. 그러면 그라데이션이 흰색으로 페이드됩니다.

Radial Gradient Mask

이 방법은 비트맵을 마스킹하는 가장 좋은 방법이 아닙니다. 문제는 마스크가 주로 캔버스의 배경과 일치하도록 선택된 흰색 색을 가지고 있다는 것입니다. 배경이 다른 색이거나 그라데이션 자체일 경우 일치하지 않습니다. 마스킹에 대한 더 나은 방법은 SkiaSharp 포터 더프 블렌드 모드 문서에 나와 있습니다.

반사 강조 표시에 대한 방사형 그라데이션

빛이 둥근 표면을 치는 경우 여러 방향으로 빛을 반사하지만 일부 빛은 뷰어의 눈에 직접 반사됩니다. 이것은 종종 반사 하이라이트라는 표면에 퍼지 흰색 영역의 모양을 만듭니다.

3차원 그래픽에서 반사 강조 표시는 조명 경로 및 음영을 결정하는 데 사용되는 알고리즘에서 발생하는 경우가 많습니다. 2차원 그래픽에서는 3D 표면의 모양을 제안하기 위해 반사 강조 표시가 추가되기도 합니다. 반사 강조 표시는 평평한 빨간색 원을 둥근 빨간색 공으로 변환할 수 있습니다.

방사형 반사 강조 표시 페이지는 방사형 그라데이션을 사용하여 정확하게 수행합니다. PaintSurface 처리기는 원의 반지름과 원의 가운데와 왼쪽 위 가장자리 사이의 중간인 두 SKPoint 값을 centeroffCenter 계산하여 존재합니다.

public class RadialSpecularHighlightPage : ContentPage
{
    public RadialSpecularHighlightPage()
    {
        Title = "Radial Specular Highlight";

        SKCanvasView canvasView = new SKCanvasView();
        canvasView.PaintSurface += OnCanvasViewPaintSurface;
        Content = canvasView;
    }

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        float radius = 0.4f * Math.Min(info.Width, info.Height);
        SKPoint center = new SKPoint(info.Rect.MidX, info.Rect.MidY);
        SKPoint offCenter = center - new SKPoint(radius / 2, radius / 2);

        using (SKPaint paint = new SKPaint())
        {
            paint.Shader = SKShader.CreateRadialGradient(
                                offCenter,
                                radius / 2,
                                new SKColor[] { SKColors.White, SKColors.Red },
                                null,
                                SKShaderTileMode.Clamp);

            canvas.DrawCircle(center, radius, paint);
        }
    }
}

호출은 CreateRadialGradient 해당 offCenter 지점에서 흰색으로 시작하여 반경의 절반 거리에서 빨간색으로 끝나는 그라데이션을 만듭니다. 다음과 같이 나타납니다.

Radial Specular Highlight

이 그라데이션을 자세히 살펴보면 결함이 있다고 판단할 수 있습니다. 그라데이션은 특정 지점을 중심으로 하며 둥근 표면을 반사하는 대칭이 조금 적었으면 좋겠습니다. 이 경우 반사 강조 표시를 위해 Conical 그라데이션 섹션 에 아래 표시된 반사 강조 표시를 선호할 수 있습니다.

스윕 그라데이션

메서드 CreateSweepGradient 에는 모든 그라데이션 생성 메서드의 가장 간단한 구문이 있습니다.

public static SKShader CreateSweepGradient (SKPoint center, 
                                            SKColor[] colors, 
                                            Single[] colorPos)

단지 가운데, 색 배열 및 색 위치일 뿐입니다. 그라데이션은 중심점의 오른쪽에서 시작하여 중심을 시계 방향으로 360도 비춥니다. 매개 변수가 없습니다 SKShaderTileMode .

CreateSweepGradient 행렬 변환 매개 변수가 있는 오버로드도 사용할 수 있습니다. 그라데이션에 회전 변환을 적용하여 시작점을 변경할 수 있습니다. 눈금 변환을 적용하여 방향을 시계 방향에서 시계 반대 방향으로 변경할 수도 있습니다.

스윕 그라데이션 페이지는 스윕 그라데이션을 사용하여 스트로크 너비가 50픽셀인 원에 색을 지정합니다.

Sweep Gradient

클래스는 SweepGradientPage 서로 다른 색조 값을 가진 8가지 색의 배열을 정의합니다. 배열이 시작되고 빨간색(0 또는 360의 색조 값)으로 끝나며 스크린샷의 맨 오른쪽에 표시됩니다.

public class SweepGradientPage : ContentPage
{
    bool drawBackground;

    public SweepGradientPage ()
    {
        Title = "Sweep Gradient";

        SKCanvasView canvasView = new SKCanvasView();
        canvasView.PaintSurface += OnCanvasViewPaintSurface;
        Content = canvasView;

        TapGestureRecognizer tap = new TapGestureRecognizer();
        tap.Tapped += (sender, args) =>
        {
            drawBackground ^= true;
            canvasView.InvalidateSurface();
        };
        canvasView.GestureRecognizers.Add(tap);
    }

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        using (SKPaint paint = new SKPaint())
        {
            // Define an array of rainbow colors
            SKColor[] colors = new SKColor[8];

            for (int i = 0; i < colors.Length; i++)
            {
                colors[i] = SKColor.FromHsl(i * 360f / 7, 100, 50);
            }

            SKPoint center = new SKPoint(info.Rect.MidX, info.Rect.MidY);

            // Create sweep gradient based on center of canvas
            paint.Shader = SKShader.CreateSweepGradient(center, colors, null);

            // Draw a circle with a wide line
            const int strokeWidth = 50;
            paint.Style = SKPaintStyle.Stroke;
            paint.StrokeWidth = strokeWidth;

            float radius = (Math.Min(info.Width, info.Height) - strokeWidth) / 2;
            canvas.DrawCircle(center, radius, paint);

            if (drawBackground)
            {
                // Draw the gradient on the whole canvas
                paint.Style = SKPaintStyle.Fill;
                canvas.DrawRect(info.Rect, paint);
            }
        }
    }
}

또한 이 프로그램은 처리기의 끝에 일부 코드를 사용하도록 설정하는 A를 구현 TapGestureRecognizer 합니다 PaintSurface . 이 코드는 동일한 그라데이션을 사용하여 캔버스를 채웁니다.

Sweep Gradient Full

이러한 스크린샷은 그라데이션이 색이 지정된 영역을 채우는 것을 보여 줍니다. 그라데이션이 동일한 색으로 시작되고 끝나지 않으면 가운데점 오른쪽에 불연속성이 있습니다.

2포인트 원뿔형 그라데이션

메서드 CreateTwoPointConicalGradient 의 구문은 다음과 같습니다.

public static SKShader CreateTwoPointConicalGradient (SKPoint startCenter, 
                                                      Single startRadius, 
                                                      SKPoint endCenter, 
                                                      Single endRadius, 
                                                      SKColor[] colors, 
                                                      Single[] colorPos, 
                                                      SKShaderTileMode mode)

매개 변수는 시작 원과 끝 원이라고 하는 두 개의 원에 대한 중심점 및 반지름으로 시작합니다. 다시 기본 세 개의 매개 변수는 for CreateLinearGradientCreateRadialGradient.와 동일합니다. 오버로드에는 CreateTwoPointConicalGradient 행렬 변환이 포함됩니다.

그라데이션은 시작 원에서 시작하여 끝 원에서 끝납니다. 매개 변수는 SKShaderTileMode 두 원을 넘어서는 동작을 제어합니다. 2포인트 원뿔 그라데이션은 영역을 완전히 채우지 않는 유일한 그라데이션입니다. 두 원의 반지름이 같으면 그라데이션은 원의 지름과 동일한 너비의 사각형으로 제한됩니다. 두 원의 반지름이 다르면 그라데이션이 원뿔을 형성합니다.

2포인트 원뿔 그라데이션을 실험하려고 할 수 있으므로 원뿔 그라데이션 페이지는 두 원 반경에 대해 두 개의 터치 포인트를 이동할 수 있도록 파생 InteractivePage 됩니다.

<local:InteractivePage xmlns="http://xamarin.com/schemas/2014/forms"
                       xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                       xmlns:local="clr-namespace:SkiaSharpFormsDemos"
                       xmlns:skia="clr-namespace:SkiaSharp;assembly=SkiaSharp"
                       xmlns:skiaforms="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
                       xmlns:tt="clr-namespace:TouchTracking"
                       x:Class="SkiaSharpFormsDemos.Effects.ConicalGradientPage"
                       Title="Conical Gradient">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>
        
        <Grid BackgroundColor="White"
              Grid.Row="0">
            <skiaforms:SKCanvasView x:Name="canvasView"
                                    PaintSurface="OnCanvasViewPaintSurface" />
            <Grid.Effects>
                <tt:TouchEffect Capture="True"
                                TouchAction="OnTouchEffectAction" />
            </Grid.Effects>
        </Grid>

        <Picker x:Name="tileModePicker" 
                Grid.Row="1"
                Title="Shader Tile Mode" 
                Margin="10"
                SelectedIndexChanged="OnPickerSelectedIndexChanged">
            <Picker.ItemsSource>
                <x:Array Type="{x:Type skia:SKShaderTileMode}">
                    <x:Static Member="skia:SKShaderTileMode.Clamp" />
                    <x:Static Member="skia:SKShaderTileMode.Repeat" />
                    <x:Static Member="skia:SKShaderTileMode.Mirror" />
                </x:Array>
            </Picker.ItemsSource>

            <Picker.SelectedIndex>
                0
            </Picker.SelectedIndex>
        </Picker>
    </Grid>
</local:InteractivePage>

코드 숨김 파일은 고정된 반지름이 50과 100인 두 TouchPoint 개체를 정의합니다.

public partial class ConicalGradientPage : InteractivePage
{
    const int RADIUS1 = 50;
    const int RADIUS2 = 100;

    public ConicalGradientPage ()
    {
        touchPoints = new TouchPoint[2];

        touchPoints[0] = new TouchPoint
        {
            Center = new SKPoint(100, 100),
            Radius = RADIUS1
        };

        touchPoints[1] = new TouchPoint
        {
            Center = new SKPoint(300, 300),
            Radius = RADIUS2
        };

        InitializeComponent();
        baseCanvasView = canvasView;
    }

    void OnPickerSelectedIndexChanged(object sender, EventArgs args)
    {
        canvasView.InvalidateSurface();
    }

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        SKColor[] colors = { SKColors.Red, SKColors.Green, SKColors.Blue };
        SKShaderTileMode tileMode = 
            (SKShaderTileMode)(tileModePicker.SelectedIndex == -1 ? 
                                        0 : tileModePicker.SelectedItem);

        using (SKPaint paint = new SKPaint())
        {
            paint.Shader = SKShader.CreateTwoPointConicalGradient(touchPoints[0].Center,
                                                                  RADIUS1,
                                                                  touchPoints[1].Center,
                                                                  RADIUS2,
                                                                  colors,
                                                                  null,
                                                                  tileMode);
            canvas.DrawRect(info.Rect, paint);
        }

        // Display the touch points here rather than by TouchPoint
        using (SKPaint paint = new SKPaint())
        {
            paint.Style = SKPaintStyle.Stroke;
            paint.Color = SKColors.Black;
            paint.StrokeWidth = 3;

            foreach (TouchPoint touchPoint in touchPoints)
            {
                canvas.DrawCircle(touchPoint.Center, touchPoint.Radius, paint);
            }
        }
    }
}

배열은 colors 빨강, 녹색 및 파랑입니다. 처리기 아래쪽에 PaintSurface 있는 코드는 그라데이션을 방해하지 않도록 두 터치 포인트를 검은색 원으로 그립니다.

호출은 DrawRect 그라데이션을 사용하여 전체 캔버스에 색을 지정합니다. 그러나 일반적으로 캔버스의 대부분은 그라데이션에 의해 색이 지정되지 기본. 세 가지 가능한 구성을 보여 주는 프로그램은 다음과 같습니다.

Conical Gradient

왼쪽의 iOS 화면에는 설정ClampSKShaderTileMode 효과가 표시됩니다. 그라데이션은 두 번째 원과 가장 가까운 측면 맞은편에 있는 작은 원의 가장자리 안쪽에 빨간색으로 시작합니다. 또한 이 값은 Clamp 빨간색이 원뿔 지점으로 계속 진행되도록 합니다. 그라데이션은 첫 번째 원에 가장 가깝지만 해당 원 안과 그 너머에서 파란색으로 계속되는 큰 원의 바깥쪽 가장자리에 파란색으로 끝납니다.

Android 화면은 비슷하지만 다음을 Repeat사용합니다SKShaderTileMode. 이제 그라데이션이 첫 번째 원 내에서 시작하여 두 번째 원 바깥쪽에서 끝나는 것이 더 분명해졌습니다. 이 Repeat 설정을 사용하면 그라데이션이 더 큰 원 안에 빨간색으로 다시 반복됩니다.

UWP 화면에는 작은 원을 큰 원 내부로 완전히 이동할 때 발생하는 작업이 표시됩니다. 그라데이션이 원뿔이 되는 것을 멈추고 대신 전체 영역을 채웁니다. 효과는 방사형 그라데이션과 비슷하지만 작은 원이 더 큰 원 내에서 정확히 가운데에 있지 않은 경우 비대칭입니다.

한 원이 다른 원에 중첩될 때 그라데이션의 실질적인 유용성을 의심할 수 있지만 반사 강조 표시에 이상적입니다.

반사 강조 표시에 대한 원뿔형 그라데이션

이 문서의 앞부분에서는 방사형 그라데이션을 사용하여 반사 강조를 만드는 방법을 알아보았습니다. 이 용도로 2포인트 원뿔형 그라데이션을 사용할 수도 있으며 다음과 같은 모양을 선호할 수 있습니다.

Conical Specular Highlight

비대칭 모양은 개체의 둥근 표면을 더 잘 나타냅니다.

원뿔형 반사 강조 표시 페이지의 그리기 코드는 셰이더를 제외하고 방사형 반사 강조 표시 페이지와 동일합니다.

public class ConicalSpecularHighlightPage : ContentPage
{
    ···
    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        ···
        using (SKPaint paint = new SKPaint())
        {
            paint.Shader = SKShader.CreateTwoPointConicalGradient(
                                offCenter,
                                1,
                                center,
                                radius,
                                new SKColor[] { SKColors.White, SKColors.Red },
                                null,
                                SKShaderTileMode.Clamp);

            canvas.DrawCircle(center, radius, paint);
        }
    }
}

두 원의 중심 offCenter 은 다음과 같습니다 center. 가운데에 있는 center 원은 전체 볼을 포괄하는 반경과 연결되지만 가운데에 있는 offCenter 원의 반경은 1픽셀에 불과합니다. 그라데이션은 해당 지점에서 효과적으로 시작하여 공의 가장자리에서 끝납니다.