SkiaSharp 선형 그라데이션The SkiaSharp linear gradient

샘플 다운로드 샘플 다운로드Download Sample Download the sample

합니다 SKPaint 클래스 정의 Color 줄 스트로크 또는 단색으로 영역을 채우는 데 사용 되는 속성입니다.The SKPaint class defines a Color property that is used to stroke lines or fill areas with a solid color. 또는 줄 스트로크 또는 영역을 채울 수 있습니다 그라데이션을, 색의 점진적으로 혼합 된:You can alternatively stroke lines or fill areas with gradients, which are gradual blends of colors:

선형 그라데이션 샘플Linear Gradient Sample

그라데이션의 가장 기본적인 형식은 선형 그라데이션 합니다.The most basic type of gradient is a linear gradient. Blend 색의 줄에 발생 (호출을 그라데이션 선) 다른 한 지점에서.The blend of colors occurs on a line (called the gradient line) from one point to another. 수직 그라데이션 선으로 줄에는 동일한 색을 가집니다.Lines that are perpendicular to the gradient line have the same color. 선형 그라데이션 두 정적 중 하나를 사용 하 여 만든 SKShader.CreateLinearGradient 메서드.You create a linear gradient using one of the two static SKShader.CreateLinearGradient methods. 두 오버 로드 간의 차이점은 매트릭스 변환을 포함 한 다른 그렇지 않습니다.The difference between the two overloads is that one includes a matrix transform and the other does not.

이러한 메서드는 형식의 개체를 반환 SKShader 로 설정 하는 Shader 속성 SKPaint.These methods return an object of type SKShader that you set to the Shader property of SKPaint. 경우는 Shader 속성이 null이 아닌, 재정의 Color 속성입니다.If the Shader property is non-null, it overrides the Color property. 스트로크 하는 모든 줄 또는이 사용 하 여 채워진 SKPaint 단색을 나타내는 보다는 그라데이션에 개체를 기반으로 합니다.Any line that is stroked or any area that is filled using this SKPaint object is based on the gradient rather than the solid color.

참고

합니다 Shader 포함 하는 경우 속성은 무시 됩니다는 SKPaint 개체를 DrawBitmap 호출 합니다.The Shader property is ignored when you include an SKPaint object in a DrawBitmap call. 사용할 수는 Color 속성을 SKPaint 비트맵을 표시 하는 것에 대 한 투명도 수준을 설정 하려면 (문서에 설명 된 대로 SkiaSharp 표시 비트맵), 하지만 사용할 수 없습니다는 Shader 표시에 대 한 속성 그라데이션 투명도 사용 하 여 비트맵입니다.You can use the Color property of SKPaint to set a transparency level for displaying a bitmap (as described in the article Displaying SkiaSharp bitmaps), but you can't use the Shader property for displaying a bitmap with a gradient transparency. 다른 기술을 그라데이션 투명도 사용 하 여 비트맵을 표시 하기 위해 사용할 수 있습니다. 문서에 설명 된 이러한 SkiaSharp 순환 그라데이션 하 고 SkiaSharp 합치기 및 혼합 모드합니다.Other techniques are available for displaying bitmaps with gradient transparencies: These are described in the articles SkiaSharp circular gradients and SkiaSharp compositing and blend modes.

모퉁이가-그라데이션Corner-to-corner gradients

종종 선형 그라데이션 다른 영역의 한쪽 모퉁이에서 확장합니다.Often a linear gradient extends from one corner of a rectangle to another. 시작점을 사각형의 왼쪽 위 모퉁이 그라데이션 확장할 수 있습니다.If the start point is the upper-left corner of the rectangle, the gradient can extend:

  • 왼쪽 아래 모서리에 수직으로vertically to the lower-left corner
  • 오른쪽 위 모퉁이에 수평으로horizontally to the upper-right corner
  • 오른쪽 아래 모퉁이에 대각선 방향으로diagonally to the lower-right corner

대각선 선형 그라데이션의의 첫 번째 페이지에 설명 되어는 SkiaSharp 셰이더 및 기타 효과 섹션을 SkiaSharpFormsDemos 샘플입니다.The diagonal linear gradient is demonstrated in the first page in the SkiaSharp Shaders and Other Effects section of the SkiaSharpFormsDemos sample. 모퉁이가-그라데이션 를 만들고이 SKCanvasView 생성자에서.The Corner-to-Corner Gradient page creates an SKCanvasView in its constructor. 합니다 PaintSurface 처리기를 만듭니다를 SKPaint 개체는 using 문을 다음 캔버스의 가운데 300 픽셀 사각형 사각형을 정의:The PaintSurface handler creates an SKPaint object in a using statement and then defines a 300-pixel square rectangle centered in the canvas:

public class CornerToCornerGradientPage : ContentPage
{
    ···
    public CornerToCornerGradientPage ()
    {
        Title = "Corner-to-Corner 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())
        {
            // Create 300-pixel square centered rectangle
            float x = (info.Width - 300) / 2;
            float y = (info.Height - 300) / 2;
            SKRect rect = new SKRect(x, y, x + 300, y + 300);

            // Create linear gradient from upper-left to lower-right
            paint.Shader = SKShader.CreateLinearGradient(
                                new SKPoint(rect.Left, rect.Top),
                                new SKPoint(rect.Right, rect.Bottom),
                                new SKColor[] { SKColors.Red, SKColors.Blue },
                                new float[] { 0, 1 },
                                SKShaderTileMode.Repeat);

            // Draw the gradient on the rectangle
            canvas.DrawRect(rect, paint);
            ···
        }
    }
}

Shader 속성을 SKPaint 할당 되는 SKShader 정적에서 값을 반환 SKShader.CreateLinearGradient 메서드.The Shader property of SKPaint is assigned the SKShader return value from the static SKShader.CreateLinearGradient method. 다섯 개의 인수는 다음과 같습니다.The five arguments are as follows:

  • 그라데이션의 시작점 사각형의 왼쪽 위 모퉁이 여기로.The start point of the gradient, set here to the upper-left corner of the rectangle
  • 그라데이션의 끝점 사각형의 오른쪽 아래 모서리를 여기로.The end point of the gradient, set here to the lower-right corner of the rectangle
  • 두 개 이상의 색 그라데이션에 기여 하는 배열An array of two or more colors that contribute to the gradient
  • 배열을 float 색 그라데이션 선 내에서 상대 위치를 나타내는 값An array of float values indicating the relative position of the colors within the gradient line
  • 멤버는 SKShaderTileMode 그라데이션의 그라데이션 선 끝 외 동작 하는 방법을 나타내는 열거형A member of the SKShaderTileMode enumeration indicating how the gradient behaves beyond the ends of the gradient line

그라데이션 개체를 만든 후 합니다 DrawRect 메서드를 사용 하 여 300 픽셀 사각형 사각형을 그립니다는 SKPaint 셰이더를 포함 하는 개체입니다.After the gradient object is created, the DrawRect method draws the 300-pixel square rectangle using the SKPaint object that includes the shader. 여기 iOS, Android 및 유니버설 Windows 플랫폼 (UWP)에서 실행 합니다.Here it is running on iOS, Android, and the Universal Windows Platform (UWP):

모퉁이가-그라데이션Corner-to-Corner Gradient

그라데이션 선은 처음 두 인수로 지정 된 두 개의 점으로 정의 됩니다.The gradient line is defined by the two points specified as the first two arguments. 이러한 점을 기준으로 하는 캔버스하지 그라데이션을 사용 하 여 표시 된 그래픽 개체를 합니다.Notice that these points are relative to the canvas and not to the graphical object displayed with the gradient. 그라데이션 선을 따라 색으로 점차 오른쪽 아래에 파란색으로 왼쪽 위에 빨간색에서 전환.Along the gradient line, the color gradually transitions from red at the upper left to blue at the lower right. 그라데이션 선을에 수직인 모든 줄에 불변 색을 있습니다.Any line that is perpendicular to the gradient line has a constant color.

배열을 float 색의 배열 사용 하 여 일대일 대응이 네 번째 인수로 지정 된 값입니다.The array of float values specified as the fourth argument have a one-to-one correspondence with the array of colors. 값은 해당 색 발생 그라데이션 선 따라 상대 위치를 나타냅니다.The values indicate the relative position along the gradient line where those colors occur. 여기서 0은 즉 Red 그라데이션 줄의 시작 시 발생 즉 1 및 Blue 줄의 끝에 발생 합니다.Here, the 0 means that Red occurs at the start of the gradient line, and 1 means that Blue occurs at the end of the line. 숫자 오름차순 해야 및 0 ~ 1 범위에 있어야 합니다.The numbers must be ascending, and should be in the range of 0 to 1. 해당 범위의 그렇지 않은 경우 해당 범위에 포함 되도록 조정 됩니다.If they aren't in that range, they will be adjusted to be in that range.

배열의 두 값 0과 1 이외의 값으로 설정할 수 있습니다.The two values in the array can be set to something other than 0 and 1. 다음과 같이 해보세요.Try this:

new float[] { 0.25f, 0.75f }

이제 그라데이션 줄의 첫 번째 전체 분기는 순수한 빨간색 이며 마지막 분기 순수 파란색입니다.Now the whole first quarter of the gradient line is pure red, and the last quarter is pure blue. 빨강 및 파랑 조합 그라데이션 선 중앙 절반으로 제한 됩니다.The mix of red and blue is restricted to the central half of the gradient line.

일반적으로 이러한 위치 값이 동일 하 게 0에서에서 1 공간을 해야 합니다.Generally, you'll want to space these position values equally from 0 to 1. 하는 경우 제공할 수 있습니다 단순히 null 네 번째 인수로 CreateLinearGradient합니다.If that is the case, you can simply supply null as the fourth argument to CreateLinearGradient.

이 그라데이션 300 픽셀 사각형 영역의 두 모퉁이 사이 정의 된, 하지만 해당 사각형을 채우는 제한 하지 않습니다.Although this gradient is defined between two corners of the 300-pixel square rectangle, it isn't restricted to filling that rectangle. 합니다 모퉁이가-그라데이션 탭에 응답 하는 몇 가지 추가 코드를 포함 하는 페이지 또는 페이지의 마우스 클릭 합니다.The Corner-to-Corner Gradient page includes some extra code that responds to taps or mouse clicks on the page. 합니다 drawBackground 간의 필드 설정/해제 truefalse 각 탭을 사용 하 여 합니다.The drawBackground field is toggled between true and false with each tap. 값이 true, 해당 PaintSurface 처리기에서는 동일한 SKPaint 전체 캔버스를 채우도록 개체 및 다음 작은 사각형을 나타내는 검은 사각형을 그립니다.If the value is true, then the PaintSurface handler uses the same SKPaint object to fill the entire canvas, and then draws a black rectangle indicating the smaller rectangle:

public class CornerToCornerGradientPage : ContentPage
{
    bool drawBackground;

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

    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        ···
        using (SKPaint paint = new SKPaint())
        {
            ···
            if (drawBackground)
            {
                // Draw the gradient on the whole canvas
                canvas.DrawRect(info.Rect, paint);

                // Outline the smaller rectangle
                paint.Shader = null;
                paint.Style = SKPaintStyle.Stroke;
                paint.Color = SKColors.Black;
                canvas.DrawRect(rect, paint);
            }
        }
    }
}

화면을 누른 후 볼 수 있는 내용 다음과 같습니다.Here's what you'll see after tapping the screen:

모퉁이가-그라데이션 전체Corner-to-Corner Gradient Full

그라데이션의 그라데이션 선을 정의 하는 점 이외의 동일한 패턴에 자체 반복 있는지 확인 합니다.Notice that the gradient repeats itself in the same pattern beyond the points defining the gradient line. 이 반복이 발생 하기 때문에 마지막 인수 CreateLinearGradientSKShaderTileMode.Repeat합니다.This repetition occurs because the last argument to CreateLinearGradient is SKShaderTileMode.Repeat. (있습니다 곧 확인 하겠지만 다른 옵션입니다.)(You'll see the other options shortly.)

또한 그라데이션 줄을 지정 하는 데 사용 하는 지점 고유 하지는 알 수 있습니다.Also notice that the points that you use to specify the gradient line aren't unique. 수직 그라데이션 선으로 줄 무한 같은 효과를 지정할 수 있는 그라데이션 선의 되므로 동일한 색을 가집니다.Lines that are perpendicular to the gradient line have the same color, so there are an infinite number of gradient lines that you can specify for the same effect. 예를 들어 가로 그라데이션을 사용 하 여 사각형을 채우는, 왼쪽 및 오른쪽 위 모서리 또는 왼쪽 및 오른쪽 아래 모서리를 사용한 경우라도 및 병렬 해당 줄으로 된 두 점을 지정할 수 있습니다.For example, when filling a rectangle with a horizontal gradient, you can specify the upper-left and upper-right corners, or the lower-left and lower-right corners, or any two points that are even with and parallel to those lines.

대화형으로 실험Interactively experiment

선형 그라데이션을 사용 하 여 대화형으로 테스트할 수 있습니다 합니다 대화형 선형 그라데이션 페이지입니다.You can interactively experiment with linear gradients with the Interactive Linear Gradient page. 이 페이지를 사용 합니다 InteractivePage 클래스의 기사에서 소개한 호를 그리려면 세 가지 방법으로합니다. InteractivePage 핸들 TouchEffect 이벤트의 컬렉션을 유지 하기 위해 TouchPoint 손가락이 나 마우스를 사용 하 여 이동할 수 있는 개체입니다.This page uses the InteractivePage class introduced in the article Three ways to draw an arc. InteractivePage handles TouchEffect events to maintain a collection of TouchPoint objects that you can move with your fingers or the mouse.

XAML 파일을 연결 합니다 TouchEffect 의 부모에는 SKCanvasView 도 포함을 Picker 의 세 멤버 중 하나를 선택할 수 있도록를 SKShaderTileMode 열거형:The XAML file attaches the TouchEffect to a parent of the SKCanvasView and also includes a Picker that allows you to select one of the three members of the SKShaderTileMode enumeration:

<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.InteractiveLinearGradientPage"
                       Title="Interactive Linear 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>

코드 숨김 파일에서 생성자 두 개 만듭니다 TouchPoint 선형 그라데이션의 시작점과 끝점에 대 한 개체입니다.The constructor in the code-behind file creates two TouchPoint objects for the start and end points of the linear gradient. 합니다 PaintSurface 처리기 (그라데이션 빨간색에서 녹색에서 파란색)에 대 한 세 가지 색의 배열을 정의 하 고 현재 가져옵니다 SKShaderTileMode 에서 Picker:The PaintSurface handler defines an array of three colors (for a gradient from red to green to blue) and obtains the current SKShaderTileMode from the Picker:

public partial class InteractiveLinearGradientPage : InteractivePage
{
    public InteractiveLinearGradientPage ()
    {
        InitializeComponent ();

        touchPoints = new TouchPoint[2];

        for (int i = 0; i < 2; i++)
        { 
            touchPoints[i] = new TouchPoint
            {
                Center = new SKPoint(100 + i * 200, 100 + i * 200)
            };
        }

        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.CreateLinearGradient(touchPoints[0].Center,
                                                         touchPoints[1].Center,
                                                         colors,
                                                         null,
                                                         tileMode);
            canvas.DrawRect(info.Rect, paint);
        }
        ···
    }
}

합니다 PaintSurface 처리기를 만듭니다를 SKShader 개체는 모든 정보에서 색 전체 캔버스를 사용 하 여 합니다.The PaintSurface handler creates the SKShader object from all that information, and uses it to color the entire canvas. 배열을 float 값으로 설정 됩니다 null합니다.The array of float values is set to null. 이 고, 그렇지 동일 하 게 세 가지 색 공간을 해당 매개 변수는 배열의 값이 0, 0.5, 1을 설정 합니다.Otherwise, to equally space three colors, you'd set that parameter to an array with the values 0, 0.5, and 1.

대량의 PaintSurface 처리기 개체를 여러 개 표시에 할애 되어: 윤곽 원, 그라데이션 줄 및 줄 수직 터치 포인트의 그라데이션 선으로 터치 지점:The bulk of the PaintSurface handler is devoted to displaying several objects: the touch points as outline circles, the gradient line, and the lines perpendicular to the gradient lines at the touch points:

public partial class InteractiveLinearGradientPage : InteractivePage
{
    ···
    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        ···
        // 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);
            }

            // Draw gradient line connecting touchpoints
            canvas.DrawLine(touchPoints[0].Center, touchPoints[1].Center, paint);

            // Draw lines perpendicular to the gradient line
            SKPoint vector = touchPoints[1].Center - touchPoints[0].Center;
            float length = (float)Math.Sqrt(Math.Pow(vector.X, 2) +
                                            Math.Pow(vector.Y, 2));
            vector.X /= length;
            vector.Y /= length;
            SKPoint rotate90 = new SKPoint(-vector.Y, vector.X);
            rotate90.X *= 200;
            rotate90.Y *= 200;

            canvas.DrawLine(touchPoints[0].Center, 
                            touchPoints[0].Center + rotate90, 
                            paint);

            canvas.DrawLine(touchPoints[0].Center,
                            touchPoints[0].Center - rotate90,
                            paint);

            canvas.DrawLine(touchPoints[1].Center,
                            touchPoints[1].Center + rotate90,
                            paint);

            canvas.DrawLine(touchPoints[1].Center,
                            touchPoints[1].Center - rotate90,
                            paint);
        }
    }
}

두 접점을 연결 하는 그라데이션 선을 그리려면, 간단 하지만 수직 줄은 몇 가지 더 많은 작업이 필요 합니다.The gradient line connecting the two touchpoints is easy to draw, but the perpendicular lines require some more work. 그라데이션 선 벡터를 변환할 하 고 단일 단위 길이 표준화 하 고 방향으로 90도 회전 됩니다.The gradient line is converted to a vector, normalized to have a length of one unit, and then rotated by 90 degrees. 벡터 200 픽셀의 길이 지정 합니다 됩니다.That vector is then given a length of 200 pixels. 수직 그라데이션 선으로 되도록 터치 포인트에서을 확장 하는 4 개의 선을 그리는 데 사용 됩니다.It's used to draw four lines that extend from the touch points to be perpendicular to the gradient line.

수직 줄 그라데이션의 시작과 끝과 일치합니다.The perpendicular lines coincide with the beginning and end of the gradient. 설정에 따라 선을 초과 어떤 일이 생기는 SKShaderTileMode 열거형:What happens beyond those lines depends on the setting of the SKShaderTileMode enumeration:

대화형 선형 그라데이션Interactive Linear Gradient

세 가지 값의 결과 표시 하는 세 개의 스크린 샷을 SKShaderTileMode 합니다.The three screenshots show the results of the three different values of SKShaderTileMode. IOS 스크린샷은 SKShaderTileMode.Clamp, 방금 그라데이션의 테두리의 색을 확장 합니다.The iOS screenshot shows SKShaderTileMode.Clamp, which just extends the colors on the border of the gradient. SKShaderTileMode.Repeat Android 스크린샷에 옵션 그라데이션 패턴 반복 되는 방법을 보여 줍니다.The SKShaderTileMode.Repeat option in the Android screenshot shows how the gradient pattern is repeated. SKShaderTileMode.Mirror UWP 스크린샷에 옵션 패턴을도 반복 되지만 패턴 반대로 매번 없는 색 불연속성 발생 합니다.The SKShaderTileMode.Mirror option in the UWP screenshot also repeats the pattern, but the pattern is reversed each time, resulting in no color discontinuities.

그라데이션에서 그라데이션Gradients on gradients

합니다 SKShader 없는 공용 속성 또는 메서드를 제외 하 고 클래스 정의 Dispose합니다.The SKShader class defines no public properties or methods except for Dispose. SKShader 개체의 정적 메서드를 통해 생성 되므로 변경할 수 없습니다.The SKShader objects that created by its static methods are therefore immutable. 두 개의 다른 개체에 대 한 동일한 그라데이션을 사용 하는 경우에 가능성이 그라데이션의 약간 변경 하는 것이 좋습니다.Even if you use the same gradient for two different objects, it's likely you'll want to vary the gradient slightly. 이렇게 하려면 새 해야 SKShader 개체입니다.To do that, you'll need to create a new SKShader object.

합니다 그라데이션 텍스트 텍스트와 유사한 그라데이션으로 색은 백그라운드 페이지에 표시 됩니다.The Gradient Text page displays text and a brackground that are both colored with similar gradients:

그라데이션 텍스트Gradient Text

그라데이션에서 유일한 차이점은 시작 및 끝점.The only differences in the gradients are the start and end points. 텍스트 표시에 사용 되는 그라데이션의 텍스트의 경계 사각형의 모퉁이에 있는 두 점 기반으로 합니다.The gradient used for displaying text is based on two points on the corners of the bounding rectangle for the text. 백그라운드에 대 한 두 가지 시점은 전체 캔버스를 기반으로 합니다.For the background, the two points are based on the entire canvas. 코드는 다음과 같습니다.Here's the code:

public class GradientTextPage : ContentPage
{
    const string TEXT = "GRADIENT";

    public GradientTextPage ()
    {
        Title = "Gradient Text";

        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())
        {
            // Create gradient for background
            paint.Shader = SKShader.CreateLinearGradient(
                                new SKPoint(0, 0),
                                new SKPoint(info.Width, info.Height),
                                new SKColor[] { new SKColor(0x40, 0x40, 0x40),
                                                new SKColor(0xC0, 0xC0, 0xC0) },
                                null,
                                SKShaderTileMode.Clamp);

            // Draw background
            canvas.DrawRect(info.Rect, paint);

            // Set TextSize to fill 90% of width
            paint.TextSize = 100;
            float width = paint.MeasureText(TEXT);
            float scale = 0.9f * info.Width / width;
            paint.TextSize *= scale;

            // Get text bounds
            SKRect textBounds = new SKRect();
            paint.MeasureText(TEXT, ref textBounds);

            // Calculate offsets to center the text on the screen
            float xText = info.Width / 2 - textBounds.MidX;
            float yText = info.Height / 2 - textBounds.MidY;

            // Shift textBounds by that amount
            textBounds.Offset(xText, yText);

            // Create gradient for text
            paint.Shader = SKShader.CreateLinearGradient(
                                new SKPoint(textBounds.Left, textBounds.Top),
                                new SKPoint(textBounds.Right, textBounds.Bottom),
                                new SKColor[] { new SKColor(0x40, 0x40, 0x40),
                                                new SKColor(0xC0, 0xC0, 0xC0) },
                                null,
                                SKShaderTileMode.Clamp);

            // Draw text
            canvas.DrawText(TEXT, xText, yText, paint);
        }
    }
}

합니다 Shader 의 속성을 SKPaint 개체 배경을 설명 하는 그라데이션을 표시할 가장 먼저 설정 됩니다.The Shader property of the SKPaint object is set first to display a gradient to cover the background. 그라데이션 지점 캔버스의 왼쪽 및 오른쪽 아래 모서리에 설정 됩니다.The gradient points are set to the upper-left and lower-right corners of the canvas.

코드 집합을 TextSize 의 속성을 SKPaint 캔버스 너비의 90% 텍스트가 표시 되도록 개체입니다.The code sets the TextSize property of the SKPaint object so that the text is displayed at 90% of the width of the canvas. 텍스트 범위를 사용 하 여을 계산 xText 하 고 yText 에 전달할 값을 DrawText 텍스트를 가운데 메서드.The text bounds are used to calculate xText and yText values to pass to the DrawText method to center the text.

그러나 그라데이션의 두 번째 지점 CreateLinearGradient 호출이 표시 되 면 캔버스를 기준으로 텍스트의 왼쪽 및 오른쪽 아래 모퉁이를 참조 해야 합니다.However, the gradient points for the second CreateLinearGradient call must refer to the upper-left and lower-right corner of the text relative to the canvas when it's displayed. 이동 하 여 이렇게 합니다 textBounds 동일한 사각형 xTextyText 값:This is accomplished by shifting the textBounds rectangle by the same xText and yText values:

textBounds.Offset(xText, yText);

사각형의 왼쪽 및 오른쪽 아래 모퉁이 그라데이션의 시작점과 끝점을 설정 하는 데 사용 될 수 있습니다.Now the upper-left and lower-right corners of the rectangle can be used to set the start and end points of the gradient.

그라데이션에 애니메이션 적용Animating a gradient

그라데이션에 애니메이션을 적용 하는 방법은 여러 가지가 있습니다.There are several ways to animate a gradient. 한 가지 방법은 시작점과 끝점을 애니메이션 효과를 주는 하는 것입니다.One approach is to animate the start and end points. 합니다 그라데이션 애니메이션 페이지 이동 두 점 중점을 두는 원 안에 캔버스에서.The Gradient Animation page moves the two points around in a circle that is centered on the canvas. 이 원의 반지름을 절반 너비 또는 캔버스의 높이 더 작은 값입니다.The radius of this circle is half the width or height of the canvas, whichever is smaller. 시작 점과 끝이이 원에 서로 반대 되는 및 그라데이션을 사용 하 여 검정색 흰색에서 이동 된 Mirror 타일 모드:The start and end points are opposite each other on this circle, and the gradient goes from white to black with a Mirror tile mode:

그라데이션 애니메이션Gradient Animation

생성자는 만듭니다는 SKCanvasView합니다.The constructor creates the SKCanvasView. 합니다 OnAppearingOnDisappearing 애니메이션 논리를 처리 하는 메서드:The OnAppearing and OnDisappearing methods handle the animation logic:

public class GradientAnimationPage : ContentPage
{
    SKCanvasView canvasView;
    bool isAnimating;
    double angle;
    Stopwatch stopwatch = new Stopwatch();

    public GradientAnimationPage()
    {
        Title = "Gradient Animation";

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

    protected override void OnAppearing()
    {
        base.OnAppearing();

        isAnimating = true;
        stopwatch.Start();
        Device.StartTimer(TimeSpan.FromMilliseconds(16), OnTimerTick);
    }

    protected override void OnDisappearing()
    {
        base.OnDisappearing();

        stopwatch.Stop();
        isAnimating = false;
    }

    bool OnTimerTick()
    {
        const int duration = 3000;
        angle = 2 * Math.PI * (stopwatch.ElapsedMilliseconds % duration) / duration;
        canvasView.InvalidateSurface();

        return isAnimating;
    }
    ···
}

합니다 OnTimerTick 메서드를 계산는 angle 애니메이션 효과가 적용 됩니다 0에서 2 π 매 3 초입니다.The OnTimerTick method calculates an angle value that is animated from 0 to 2π every 3 seconds.

두 개의 그라데이션 점을 계산 하는 한 가지 방법은 다음과 같습니다.Here's one way to calculate the two gradient points. SKPoint 라는 값 vector 원의 반지름의 지점에 캔버스의 가운데에서 확장으로 계산 됩니다.An SKPoint value named vector is calculated to extend from the center of the canvas to a point on the radius of the circle. 이 벡터의 방향 각도의 사인 및 코사인 값을 기반으로 합니다.The direction of this vector is based on the sine and cosine values of the angle. 두 개의 반대 그라데이션 지점 계산 됩니다. 1 포인트는 center 지점에서 해당 벡터를 빼서 계산 하 고 다른 중심점에 벡터를 추가 하 여 계산 됩니다.The two opposite gradient points are then calculated: One point is calculated by subtracting that vector from the center point, and other point is calculated by adding the vector to the center point:

public class GradientAnimationPage : ContentPage
{
    ···
    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())
        {
            SKPoint center = new SKPoint(info.Rect.MidX, info.Rect.MidY);
            int radius = Math.Min(info.Width, info.Height) / 2;
            SKPoint vector = new SKPoint((float)(radius * Math.Cos(angle)),
                                         (float)(radius * Math.Sin(angle)));

            paint.Shader = SKShader.CreateLinearGradient(
                                center - vector,
                                center + vector,
                                new SKColor[] { SKColors.White, SKColors.Black },
                                null,
                                SKShaderTileMode.Mirror);

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

다소 다른 접근 방법이 더 적은 코드에 필요합니다.A somewhat different approach requires less code. 이 접근 방식을 이용 합니다 SKShader.CreateLinearGradient 마지막 인수로 매트릭스 변환 사용 하 여 메서드를 오버 로드 합니다.This approach makes use of the SKShader.CreateLinearGradient overload method with a matrix transform as the last argument. 이 방법은 버전을 SkiaSharpFormsDemos 샘플:This approach is the version in the SkiaSharpFormsDemos sample:

public class GradientAnimationPage : ContentPage
{
    ···
    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())
        {
            paint.Shader = SKShader.CreateLinearGradient(
                                new SKPoint(0, 0),
                                info.Width < info.Height ? new SKPoint(info.Width, 0) : 
                                                           new SKPoint(0, info.Height),
                                new SKColor[] { SKColors.White, SKColors.Black },
                                new float[] { 0, 1 },
                                SKShaderTileMode.Mirror,
                                SKMatrix.MakeRotation((float)angle, info.Rect.MidX, info.Rect.MidY));

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

캔버스의 너비가 높이 보다 작은 경우 두 개의 그라데이션 지점으로 설정 됩니다 (0, 0) 및 (info.Width, 0).If the width of the canvas is less than the height, then the two gradient points are set to (0, 0) and (info.Width, 0). 마지막 인수로 전달 된 회전 변환을 CreateLinearGradient 화면의 가운데를 기준으로 두 지점을 효과적으로 회전 합니다.The rotation transform passed as the last argument to CreateLinearGradient effectively rotates those two points around the center of the screen.

각도 0, 회전 안 되며 두 그라데이션 점 캔버스의 왼쪽 위 모퉁이 오른쪽 위 모서리는 경우는 note 합니다.Note that if the angle is 0, there's no rotation, and the two gradient points are the upper-left and upper-right corners of the canvas. 해당 지점에 없는 이전에 표시 된 대로 계산 그라데이션 선만 CreateLinearGradient 호출 합니다.Those points aren't the same gradient points calculated as shown in the previous CreateLinearGradient call. 아니지만 이러한 지점이 병렬 그라데이션 가로줄을 캔버스의 가운데 bisects는 및를 동일한 그라데이션 발생 합니다.But these points are parallel to the horizontal gradient line that bisects the center of the canvas, and they result in an identical gradient.

Rainbow 그라데이션Rainbow Gradient

합니다 Rainbow 그라데이션 페이지 캔버스의 왼쪽 위 모퉁이에서 오른쪽 아래 모퉁이에 rainbow을 그립니다.The Rainbow Gradient page draws a rainbow from the upper-left corner of the canvas to the lower-right corner. 하지만이 레인 보우 그라데이션 실제 rainbow 같은 하지 않습니다.But this rainbow gradient isn't like a real rainbow. 곡선을 보다는 직선 있지만 기반으로 360 색상 값 0에서 순환 의해 결정 되는 8 개의 HSL (색상-채도-명도) 색:It's straight rather than curved, but it's based on eight HSL (hue-saturation-luminosity) colors that are determined by cycling through hue values from 0 to 360:

SKColor[] colors = new SKColor[8];

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

코드의 일부임을 PaintSurface 아래에 표시 된 처리기입니다.That code is part of the PaintSurface handler shown below. 처리기는 오른쪽 아래 모서리를 캔버스의 왼쪽 위 모퉁이에서 확장 하는 6 면 다각형을 정의 하는 경로 만들어 시작 합니다.The handler begins by creating a path that defines a six-sided polygon that extends from the upper-left corner of the canvas to the lower-right corner:

public class RainbowGradientPage : ContentPage
{
    public RainbowGradientPage ()
    {
        Title = "Rainbow 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 (SKPath path = new SKPath())
        {
            float rainbowWidth = Math.Min(info.Width, info.Height) / 2f;

            // Create path from upper-left to lower-right corner
            path.MoveTo(0, 0);
            path.LineTo(rainbowWidth / 2, 0);
            path.LineTo(info.Width, info.Height - rainbowWidth / 2);
            path.LineTo(info.Width, info.Height);
            path.LineTo(info.Width - rainbowWidth / 2, info.Height);
            path.LineTo(0, rainbowWidth / 2);
            path.Close();

            using (SKPaint paint = new SKPaint())
            {
                SKColor[] colors = new SKColor[8];

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

                paint.Shader = SKShader.CreateLinearGradient(
                                    new SKPoint(0, rainbowWidth / 2), 
                                    new SKPoint(rainbowWidth / 2, 0),
                                    colors,
                                    null,
                                    SKShaderTileMode.Repeat);

                canvas.DrawPath(path, paint);
            }
        }
    }
}

두 그라데이션 점은 CreateLinearGradient 메서드 두이 경로 정의 하는 지점을 기반으로 합니다. 두 지점 왼쪽 위 모퉁이 가까워질 합니다.The two gradient points in the CreateLinearGradient method are based on two of the points that define this path: Both points are close to the upper-left corner. 첫 번째는 캔버스의 위쪽 가장자리에서 이며 두 번째 캔버스의 왼쪽된 가장자리입니다.The first is on the upper edge of the canvas and the second is on the left edge of the canvas. 결과 다음과 같습니다.Here's the result:

잘못 된 rainbow 그라데이션Rainbow Gradient Faulty

이 흥미로운 이미지로 이지만 의도 상당히 아닙니다.This is an interesting image, but it's not quite the intent. 문제는 선형 그라데이션을 만들 때 고정 색상의 줄을 수직 그라데이션 선으로.The problem is that when creating a linear gradient, the lines of constant color are perpendicular to the gradient line. 그라데이션 선은 그림 위쪽 및 왼쪽 면에 닿으면 해당 줄이 그림의 오른쪽 아래 모서리를 확장 하는 가장자리에 수직인 일반적으로 요소를 기반으로 합니다.The gradient line is based on the points where the figure touches the top and left sides, and that line is generally not perpendicular to the edges of the figure that extend to the bottom-right corner. 이 방법은 캔버스 제곱 된 경우에 작동 합니다.This approach would work only if the canvas were square.

적절 한 레인 보우 그라데이션을 만들려면 그라데이션 선을 무지개의 가장자리에 수직 이어야 합니다.To create a proper rainbow gradient, the gradient line must be perpendicular to the edge of the rainbow. 더 복잡된 한 계산입니다.That's a more involved calculation. 벡터 그림의 옆에 병렬 되는 정의 되어야 합니다.A vector must be defined that is parallel to the long side of the figure. 벡터는 쪽에 수직인 있도록 90도 회전된 합니다.The vector is rotated 90 degrees so that it's perpendicular to that side. 다음 그림의 너비와 곱하여 수를 늘리는 rainbowWidth합니다.It is then lengthened to be the width of the figure by multiplying by rainbowWidth. 벡터와 해당 시점 및 그림에서 어느 지점에서 두 그라데이션 점 기반 계산 됩니다.The two gradient points are calculated based on a point on the side of the figure, and that point plus the vector. 여기에 표시 되는 코드를 Rainbow 그라데이션 페이지에 SkiaSharpFormsDemos 샘플:Here is the code that appears in the Rainbow Gradient page in the SkiaSharpFormsDemos sample:

public class RainbowGradientPage : ContentPage
{
    ···
    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        ···
        using (SKPath path = new SKPath())
        {
            ···
            using (SKPaint paint = new SKPaint())
            {
                ···
                // Vector on lower-left edge, from top to bottom 
                SKPoint edgeVector = new SKPoint(info.Width - rainbowWidth / 2, info.Height) - 
                                     new SKPoint(0, rainbowWidth / 2);

                // Rotate 90 degrees counter-clockwise:
                SKPoint gradientVector = new SKPoint(edgeVector.Y, -edgeVector.X);

                // Normalize
                float length = (float)Math.Sqrt(Math.Pow(gradientVector.X, 2) +
                                                Math.Pow(gradientVector.Y, 2));
                gradientVector.X /= length;
                gradientVector.Y /= length;

                // Make it the width of the rainbow
                gradientVector.X *= rainbowWidth;
                gradientVector.Y *= rainbowWidth;

                // Calculate the two points
                SKPoint point1 = new SKPoint(0, rainbowWidth / 2);
                SKPoint point2 = point1 + gradientVector;

                paint.Shader = SKShader.CreateLinearGradient(point1,
                                                             point2,
                                                             colors,
                                                             null,
                                                             SKShaderTileMode.Repeat);

                canvas.DrawPath(path, paint);
            }
        }
    }
}

이제 무지개 색 그림에 맞춰집니다.Now the rainbow colors are aligned with the figure:

Rainbow 그라데이션Rainbow Gradient

무한대 색Infinity Colors

Rainbow 그라데이션에도 사용 합니다 무한대 색 페이지입니다.A rainbow gradient is also used in the Infinity Colors page. 이 페이지는 문서에 설명 된 경로 개체를 사용 하는 무한대 기호를 그립니다 베 지 어 곡선의 세 가지 형식합니다.This page draws an infinity sign using a path object described in the article Three Types of Bézier Curves. 다음 이미지는 이미지에서 지속적으로 추가 하는 애니메이션된 rainbow 그라데이션 색이 지정 됩니다.The image is then colored with an animated rainbow gradient that continuously sweeps across the image.

생성자는 만듭니다는 SKPath 무한대 기호를 설명 하는 개체입니다.The constructor creates the SKPath object describing the infinity sign. 경로 만든 후 생성자 경로의 사각형 범위를 가져올 수도 있습니다.After the path is created, the constructor can also obtain the rectangular bounds of the path. 그런 다음 이라고 하는 값을 계산 gradientCycleLength합니다.It then calculates a value called gradientCycleLength. 그라데이션이 왼쪽 및 오른쪽 아래 모퉁이 기반으로 하는 경우는 pathBounds 사각형이 gradientCycleLength 값이 그라데이션 패턴의 전체 가로 너비:If a gradient is based on the upper-left and lower-right corners of the pathBounds rectangle, this gradientCycleLength value is the total horizontal width of the gradient pattern:

public class InfinityColorsPage : ContentPage
{
    ···
    SKCanvasView canvasView;

    // Path information 
    SKPath infinityPath;
    SKRect pathBounds;
    float gradientCycleLength;

    // Gradient information
    SKColor[] colors = new SKColor[8];
    ···

    public InfinityColorsPage ()
    {
        Title = "Infinity Colors";

        // Create path for infinity sign
        infinityPath = new SKPath();
        infinityPath.MoveTo(0, 0);                                  // Center
        infinityPath.CubicTo(  50,  -50,   95, -100,  150, -100);   // To top of right loop
        infinityPath.CubicTo( 205, -100,  250,  -55,  250,    0);   // To far right of right loop
        infinityPath.CubicTo( 250,   55,  205,  100,  150,  100);   // To bottom of right loop
        infinityPath.CubicTo(  95,  100,   50,   50,    0,    0);   // Back to center  
        infinityPath.CubicTo( -50,  -50,  -95, -100, -150, -100);   // To top of left loop
        infinityPath.CubicTo(-205, -100, -250,  -55, -250,    0);   // To far left of left loop
        infinityPath.CubicTo(-250,   55, -205,  100, -150,  100);   // To bottom of left loop
        infinityPath.CubicTo( -95,  100, - 50,   50,    0,    0);   // Back to center
        infinityPath.Close();

        // Calculate path information 
        pathBounds = infinityPath.Bounds;
        gradientCycleLength = pathBounds.Width +
            pathBounds.Height * pathBounds.Height / pathBounds.Width;

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

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

생성자도 만듭니다는 colors 무지개, 배열 및 SKCanvasView 개체입니다.The constructor also creates the colors array for the rainbow, and the SKCanvasView object.

재정의 된 OnAppearingOnDisappearing 메서드 애니메이션에 대 한 오버 헤드를 수행 합니다.Overrides of the OnAppearing and OnDisappearing methods perform the overhead for the animation. 합니다 OnTimerTick 메서드 애니메이션을 적용 합니다 offset 0에서 필드 gradientCycleLength 2 초 마다:The OnTimerTick method animates the offset field from 0 to gradientCycleLength every two seconds:

public class InfinityColorsPage : ContentPage
{
    ···
    // For animation
    bool isAnimating;
    float offset;
    Stopwatch stopwatch = new Stopwatch();
    ···

    protected override void OnAppearing()
    {
        base.OnAppearing();

        isAnimating = true;
        stopwatch.Start();
        Device.StartTimer(TimeSpan.FromMilliseconds(16), OnTimerTick);
    }

    protected override void OnDisappearing()
    {
        base.OnDisappearing();

        stopwatch.Stop();
        isAnimating = false;
    }

    bool OnTimerTick()
    {
        const int duration = 2;     // seconds
        double progress = stopwatch.Elapsed.TotalSeconds % duration / duration;
        offset = (float)(gradientCycleLength * progress);
        canvasView.InvalidateSurface();

        return isAnimating;
    }
    ···
}

마지막으로 PaintSurface 처리기의 무한대 기호를 렌더링 합니다.Finally, the PaintSurface handler renders the infinity sign. 경로의 중심점을 둘러싼 음수 및 양수 좌표를 포함 하기 때문에 (0, 0)을 Translate 캔버스에서 변환 센터로 이동 됩니다.Because the path contains negative and positive coordinates surrounding a center point of (0, 0), a Translate transform on the canvas is used to shift it to the center. 좌표 이동 변환 뒤를 Scale 무한대 기호를 캔버스의 높이 및 너비의 95% 내에서 계속 하면서 최대한 늘릴 수 있습니다 하는 배율 인수를 적용 하는 변환입니다.The translate transform is followed by a Scale transform that applies a scaling factor that makes the infinity sign as large as possible while still staying within 95% of the width and height of the canvas.

다음에 유의 합니다 STROKE_WIDTH 상수 경로 경계 사각형의 높이 너비에 추가 됩니다.Notice that the STROKE_WIDTH constant is added to the width and height of the path bounding rectangle. 네 면 모두 해당 너비의 절반으로 렌더링 된 무한대 크기의 크기가 증가 하므로이 너비의 줄을 사용 하 여 경로 스트로크는:The path will be stroked with a line of this width, so the size of the rendered infinity size is increased by half that width on all four sides:

public class InfinityColorsPage : ContentPage
{
    const int STROKE_WIDTH = 50;
    ···
    void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
    {
        SKImageInfo info = args.Info;
        SKSurface surface = args.Surface;
        SKCanvas canvas = surface.Canvas;

        canvas.Clear();

        // Set transforms to shift path to center and scale to canvas size
        canvas.Translate(info.Width / 2, info.Height / 2);
        canvas.Scale(0.95f * 
            Math.Min(info.Width / (pathBounds.Width + STROKE_WIDTH),
                     info.Height / (pathBounds.Height + STROKE_WIDTH)));

        using (SKPaint paint = new SKPaint())
        {
            paint.Style = SKPaintStyle.Stroke;
            paint.StrokeWidth = STROKE_WIDTH;
            paint.Shader = SKShader.CreateLinearGradient(
                                new SKPoint(pathBounds.Left, pathBounds.Top),
                                new SKPoint(pathBounds.Right, pathBounds.Bottom),
                                colors,
                                null,
                                SKShaderTileMode.Repeat,
                                SKMatrix.MakeTranslation(offset, 0));

            canvas.DrawPath(infinityPath, paint);
        }
    }
}

처음 두 인수로 전달 된 점을 살펴볼 SKShader.CreateLinearGradient합니다.Look at the points passed as the first two arguments of SKShader.CreateLinearGradient. 해당 지점에 경계 사각형의 원래 경로 기반으로 합니다.Those points are based on the original path bounding rectangle. 첫 번째 점은 (–250, –100)이 고 두 번째 (250, 100).The first point is (–250, –100) and the second is (250, 100). SkiaSharp 내부 해당 지점에 종속 됩니다 현재 캔버스 변환을 표시 무한대 기호를 사용 하 여 올바르게 정렬 되도록 합니다.Internal to SkiaSharp, those points are subjected to the current canvas transform so they align correctly with the displayed infinity sign.

마지막 인수 없이 CreateLinearGradient, 왼쪽 위 무한대 기호 아래로 순서 대로 오른쪽에서 확장 된 rainbow 그라데이션이 표시 됩니다.Without the last argument to CreateLinearGradient, you'd see a rainbow gradient that extends from the upper left of the infinity sign to the lower right. (실제로 그라데이션의 확장 왼쪽 위 모서리에서 경계 사각형의 오른쪽 아래 모퉁이에 있습니다.(Actually, the gradient extends from the upper-left corner to the lower-right corner of the bounding rectangle. 렌더링 된 무한대 기호를 절반으로 경계 사각형을 보다는 STROKE_WIDTH 모든 양쪽 값입니다.The rendered infinity sign is greater than the bounding rectangle by half the STROKE_WIDTH value on all sides. 그라데이션의 시작과 끝에 빨간색 그라데이션을 사용 하 여 만들어집니다. 때문에 SKShaderTileMode.Repeat, 차이 눈에 띄는 되지 않습니다.)Because the gradient is red at both the beginning and end, and the gradient is created with SKShaderTileMode.Repeat, the difference isn't noticeable.)

해당 마지막 인수를 사용 하 여 CreateLinearGradient, 이미지에서 그라데이션 패턴을 지속적으로 추가 합니다.With that last argument to CreateLinearGradient, the gradient pattern continuously sweeps across the image:

무한대 색상Infinity Colors

투명도 및 그라데이션과Transparency and gradients

그라데이션에 영향을 주는 색 투명도 통합할 수 있습니다.The colors that contribute to a gradient can incorporate transparency. 다른 색에서 간의 페이드 그라데이션을 대신 그라데이션의 투명 색에서 페이드 수 있습니다.Instead of a gradient that fades from one color to another, the gradient can fade from a color to transparent.

몇 가지 흥미로운 효과 대 한이 기법을 사용할 수 있습니다.You can use this technique for some interesting effects. 클래식 예제 중 하나는 리플렉션 사용 하 여 그래픽 개체를 보여 줍니다.One of the classic examples shows a graphical object with its reflection:

리플렉션 그라데이션Reflection Gradient

거꾸로 된 텍스트를 50% 맨 아래에 완전히 투명 하 게 맨 위에 있는 투명 한 그라데이션 색입니다.The text that is upside-down is colored with a gradient that is 50% transparent at the top to fully transparent at the bottom. 이러한 수준의 투명도 0x80의 알파 값 및 0와 연결 됩니다.These levels of transparency are associated with alpha values of 0x80 and 0.

합니다 PaintSurface 처리기에는 리플렉션 그라데이션 페이지 캔버스 너비의 90% 텍스트의 크기를 조정 합니다.The PaintSurface handler in the Reflection Gradient page scales the size of the text to 90% of the width of the canvas. 그런 다음 계산 xTextyText 가로 가운데 맞춤 될 텍스트를 배치 하는 값 이지만 페이지의 세로 가운데에 해당 하는 기준에서:It then calculates xText and yText values to position the text to be horizontally centered but sitting on a baseline corresponding to the vertical center of the page:

public class ReflectionGradientPage : ContentPage
{
    const string TEXT = "Reflection";

    public ReflectionGradientPage ()
    {
        Title = "Reflection 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())
        {
            // Set text color to blue
            paint.Color = SKColors.Blue;

            // Set text size to fill 90% of width
            paint.TextSize = 100;
            float width = paint.MeasureText(TEXT);
            float scale = 0.9f * info.Width / width;
            paint.TextSize *= scale;

            // Get text bounds
            SKRect textBounds = new SKRect();
            paint.MeasureText(TEXT, ref textBounds);

            // Calculate offsets to position text above center
            float xText = info.Width / 2 - textBounds.MidX;
            float yText = info.Height / 2;

            // Draw unreflected text
            canvas.DrawText(TEXT, xText, yText, paint);

            // Shift textBounds to match displayed text
            textBounds.Offset(xText, yText);

            // Use those offsets to create a gradient for the reflected text
            paint.Shader = SKShader.CreateLinearGradient(
                                new SKPoint(0, textBounds.Top),
                                new SKPoint(0, textBounds.Bottom),
                                new SKColor[] { paint.Color.WithAlpha(0),
                                                paint.Color.WithAlpha(0x80) },
                                null,
                                SKShaderTileMode.Clamp);

            // Scale the canvas to flip upside-down around the vertical center
            canvas.Scale(1, -1, 0, yText);

            // Draw reflected text
            canvas.DrawText(TEXT, xText, yText, paint);
        }
    }
}

이러한 xTextyText 값은 동일한 값에 반영 된 텍스트를 표시 하는 데 사용 합니다 DrawText 맨 아래에 호출를 PaintSurface 처리기.Those xText and yText values are the same values used to display the reflected text in the DrawText call at the bottom of the PaintSurface handler. 그러나 해당 코드를 직전 표시에 대 한 호출을 Scale 메서드의 SKCanvas합니다.Just before that code, however, you'll see a call to the Scale method of SKCanvas. Scale 메서드는 수평적으로 확장 (아무 작업도 수행 하지)는 1에서 세로로 하지만 여 –1 효과적으로 모든 거꾸로 대칭이 되도록 합니다.This Scale method scales horizontally by 1 (which does nothing) but vertically by –1, which effectively flips everything upside-down. 회전 중심의 지점으로 설정 됩니다 (0 yText), 여기서 yText 는 원래 계산 캔버스의 세로 가운데 info.Height 2로 나눈 결과입니다.The center of rotation is set to the point (0, yText), where yText is the vertical center of the canvas, originally calculated as info.Height divided by 2.

Skia 그라데이션을 사용 하 여 캔버스 변환 하기 전에 그래픽 개체에 색을 염두에 두어야 합니다.Keep in mind that Skia uses the gradient to color graphical objects prior to the canvas transforms. Unreflected 텍스트를 가져온 후의 textBounds 사각형에 표시 된 텍스트에 해당 하므로 전부가 이동 됩니다.After the unreflected text is drawn, the textBounds rectangle is shifted so it corresponds to the displayed text:

textBounds.Offset(xText, yText);

CreateLinearGradient 호출에는 사각형의 위쪽에서 아래쪽으로 향하는 그라데이션을 정의 합니다.The CreateLinearGradient call defines a gradient from the top of that rectangle to the bottom. 기울기가 완전히 투명 한 파랑 (paint.Color.WithAlpha(0))을 50% 투명 한 파랑 (paint.Color.WithAlpha(0x80)).The gradient is from a completely transparent blue (paint.Color.WithAlpha(0)) to a 50% transparent blue (paint.Color.WithAlpha(0x80)). 캔버스 변환을 50% 투명 한 파랑 기준선에서 시작 하 고 텍스트의 맨 위에 있는 투명 하 게 되므로 거꾸로 텍스트를 대칭 이동 합니다.The canvas transform flips the text upside-down, so the 50% transparent blue starts at the baseline, and becomes transparent at the top of the text.