Partager via


Dégradés circulaires SkiaSharp

La SKShader classe définit des méthodes statiques pour créer quatre types de dégradés différents. L’article de dégradé linéaire SkiaSharp décrit la CreateLinearGradient méthode. Cet article traite des trois autres types de dégradés, qui sont tous basés sur des cercles.

La CreateRadialGradient méthode crée un dégradé qui émane du centre d’un cercle :

Exemple de dégradé radial

La CreateSweepGradient méthode crée un dégradé qui balaye autour du centre d’un cercle :

Exemple de dégradé de balayage

Le troisième type de dégradé est assez inhabituel. Il est appelé dégradé conical à deux points et est défini par la CreateTwoPointConicalGradient méthode. Le dégradé s’étend d’un cercle à un autre :

Exemple de dégradé conical

Si les deux cercles sont de tailles différentes, le dégradé prend la forme d’un cône.

Cet article explore ces dégradés plus en détail.

Dégradé radial

La CreateRadialGradient méthode a la syntaxe suivante :

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

Une CreateRadialGradient surcharge inclut également un paramètre de matrice de transformation.

Les deux premiers arguments spécifient le centre d’un cercle et un rayon. Le dégradé commence à ce centre et s’étend vers l’extérieur pour radius les pixels. Ce qui se passe au-delà radius dépend de l’argument SKShaderTileMode . Le colors paramètre est un tableau de deux couleurs ou plus (comme dans les méthodes de dégradé linéaire) et colorPos est un tableau d’entiers de la plage de 0 à 1. Ces entiers indiquent les positions relatives des couleurs le long de cette radius ligne. Vous pouvez définir cet argument sur null un espace égal des couleurs.

Si vous utilisez CreateRadialGradient pour remplir un cercle, vous pouvez définir le centre du dégradé au centre du cercle et le rayon du dégradé sur le rayon du cercle. Dans ce cas, l’argument SKShaderTileMode n’a aucun effet sur le rendu du dégradé. Mais si la zone remplie par le dégradé est supérieure au cercle défini par le dégradé, l’argument SKShaderTileMode a un effet profond sur ce qui se passe en dehors du cercle.

L’effet est SKShaderMode illustré dans la page Dégradé radiale de l’exemple. Le fichier XAML de cette page instancie un Picker qui vous permet de sélectionner l’un des trois membres de l’énumération SKShaderTileMode :

<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>

Le fichier code-behind colore l’intégralité du canevas avec un dégradé radial. Le centre du dégradé est défini sur le centre du canevas, et le rayon est défini sur 100 pixels. Le dégradé se compose de deux couleurs, noir et blanc :

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);
        }
    }
}

Ce code crée un dégradé avec du noir au centre, ce qui se décolore progressivement à 100 pixels du centre. Ce qui se passe au-delà de ce rayon dépend de l’argument SKShaderTileMode :

Dégradé radial

Dans les trois cas, le dégradé remplit le canevas. Sur l’écran iOS à gauche, le dégradé au-delà du rayon continue avec la dernière couleur, qui est blanche. C’est le résultat de SKShaderTileMode.Clamp. L’écran Android affiche l’effet de SKShaderTileMode.Repeat: à 100 pixels du centre, le dégradé commence à nouveau par la première couleur, qui est noire. Le dégradé se répète toutes les 100 pixels de rayon.

L’écran plateforme Windows universelle à droite montre comment SKShaderTileMode.Mirror les dégradés sont des directions alternatives. Le premier dégradé est de noir au centre à blanc à un rayon de 100 pixels. La suivante est blanche du rayon de 100 pixels au noir à un rayon de 200 pixels, et le dégradé suivant est inversé à nouveau.

Vous pouvez utiliser plus de deux couleurs dans un dégradé radial. L’exemple Arc-en-ciel dégradé crée un tableau de huit couleurs correspondant aux couleurs de l’arc-en-ciel et se terminant par le rouge, ainsi qu’un tableau de huit valeurs de position :

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);
        }
    }
}

Supposons que le minimum de la largeur et de la hauteur du canevas soit 1 000, ce qui signifie que la rainbowWidth valeur est 250. Les outerRadius valeurs et innerRadius les valeurs sont définies respectivement sur 1 000 et 750. Ces valeurs sont utilisées pour calculer le positions tableau ; les huit valeurs vont de 0,75f à 1. La radius valeur est utilisée pour caresser le cercle. La valeur de 875 signifie que la largeur de trait de 250 pixels s’étend entre le rayon de 750 pixels et le rayon de 1 000 pixels :

Dégradé arc arc-en-ciel

Si vous avez rempli le canevas entier avec ce dégradé, vous verrez qu’il est rouge dans le rayon intérieur. Cela est dû au fait que le positions tableau ne commence pas par 0. La première couleur est utilisée pour les décalages de 0 à la première valeur du tableau. Le dégradé est également rouge au-delà du rayon externe. C’est le résultat du mode vignette Clamp . Étant donné que le dégradé est utilisé pour caresser une ligne épaisse, ces zones rouges ne sont pas visibles.

Dégradés radials pour le masquage

Comme les dégradés linéaires, les dégradés radials peuvent incorporer des couleurs transparentes ou partiellement transparentes. Cette fonctionnalité est utile pour un processus appelé masquage, qui masque une partie d’une image pour accentuer une autre partie de l’image.

La page Masque de dégradé radial montre un exemple. Le programme charge l’une des bitmaps de ressources. Les champs et RADIUS les CENTER champs ont été déterminés à partir d’un examen de la bitmap et font référence à une zone qui doit être mise en surbrillance. Le PaintSurface gestionnaire commence par calculer un rectangle pour afficher l’image bitmap, puis l’afficher dans ce rectangle :

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);
        }
    }
}

Après avoir dessiné l’image bitmap, un code simple est CENTER converti et RADIUS vers center et radius, qui font référence à la zone mise en surbrillance dans la bitmap qui a été mise à l’échelle et décalée pour l’affichage. Ces valeurs sont utilisées pour créer un dégradé radial avec ce centre et ce rayon. Les deux couleurs commencent par transparentes au centre et pour les 60 % premiers du rayon. Le dégradé s’est ensuite fondu en blanc :

Masque de dégradé radial

Cette approche n’est pas la meilleure façon de masquer une bitmap. Le problème est que le masque a principalement une couleur de blanc, qui a été choisi pour correspondre à l’arrière-plan de la zone de dessin. Si l’arrière-plan est une autre couleur , ou peut-être un dégradé lui-même, il ne correspond pas. Une meilleure approche du masquage est présentée dans l’article SkiaSharp Porter-Duff modes de fusion.

Dégradés radials pour les surbrillances spéculaires

Lorsqu’une lumière frappe une surface arrondie, elle reflète la lumière dans de nombreuses directions, mais certaines de la lumière rebondissent directement dans l’œil de la visionneuse. Cela crée souvent l’apparence d’une zone blanche floue sur la surface appelée une surbrillance spéculaire.

Dans les graphiques à trois dimensions, les surbrillances spéculaires proviennent souvent des algorithmes utilisés pour déterminer les chemins d’accès lumineux et l’ombrage. Dans les graphiques à deux dimensions, les surbrillances spéculaires sont parfois ajoutées pour suggérer l’apparence d’une surface 3D. Une mise en surbrillance spéculaire peut transformer un cercle rouge plat en boule rouge ronde.

La page Mise en surbrillance spéculaire radiale utilise un dégradé radial pour le faire précisément. Le PaintSurface gestionnaire est en calculant un rayon pour le cercle, et deux SKPoint valeurs : un et un center offCenter demi-chemin entre le centre et le bord supérieur gauche du cercle :

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);
        }
    }
}

L’appel CreateRadialGradient crée un dégradé qui commence à ce offCenter point avec du blanc et se termine par rouge à une distance de la moitié du rayon. Voici à quoi il ressemble :

Surbrillance spéculaire radiale

Si vous examinez attentivement ce dégradé, vous pouvez décider qu’il est défectueux. Le dégradé est centré autour d’un point particulier, et vous pouvez souhaiter qu’il soit un peu moins symétrique pour refléter la surface arrondie. Dans ce cas, vous pouvez préférer la mise en surbrillance spéculaire indiquée ci-dessous dans la section Dégradés coniques pour les surbrillances spéculaires.

Dégradé de balayage

La CreateSweepGradient méthode a la syntaxe la plus simple de toutes les méthodes de création de dégradé :

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

Il s’agit simplement d’un centre, d’un tableau de couleurs et des positions de couleur. Le dégradé commence à droite du point central et balaye 360 degrés dans le sens des aiguilles d’une montre autour du centre. Notez qu’il n’existe aucun SKShaderTileMode paramètre.

Une CreateSweepGradient surcharge avec un paramètre de transformation de matrice est également disponible. Vous pouvez appliquer une transformation de rotation au dégradé pour modifier le point de départ. Vous pouvez également appliquer une transformation d’échelle pour changer la direction du sens des aiguilles d’une montre vers le sens inverse.

La page Dégradé de balayage utilise un dégradé de balayage pour colorer un cercle avec une largeur de trait de 50 pixels :

Dégradé de balayage

La SweepGradientPage classe définit un tableau de huit couleurs avec des valeurs de teinte différentes. Notez que le tableau commence et se termine par rouge (valeur de teinte de 0 ou 360), qui apparaît à l’extrême droite dans les captures d’écran :

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);
            }
        }
    }
}

Le programme implémente également un TapGestureRecognizer qui active du code à la fin du PaintSurface gestionnaire. Ce code utilise le même dégradé pour remplir le canevas :

Dégradé de balayage complet

Ces captures d’écran montrent que le dégradé remplit la zone de couleur. Si le dégradé ne commence pas et se termine par la même couleur, il y aura une discontinuité à droite du point central.

Dégradé conical à deux points

La CreateTwoPointConicalGradient méthode a la syntaxe suivante :

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

Les paramètres commencent par les points centraux et les rayons pour deux cercles, appelés cercle de début et cercle de fin . Les trois autres paramètres sont les mêmes que pour CreateLinearGradient et CreateRadialGradient. Une CreateTwoPointConicalGradient surcharge inclut une transformation de matrice.

Le dégradé commence au cercle de début et se termine au cercle de fin. Le SKShaderTileMode paramètre régit ce qui se passe au-delà des deux cercles. Le dégradé conical à deux points est le seul dégradé qui ne remplit pas entièrement une zone. Si les deux cercles ont le même rayon, le dégradé est limité à un rectangle avec une largeur identique au diamètre des cercles. Si les deux cercles ont des rayons différents, le dégradé forme un cône.

Il est probable que vous souhaitez expérimenter le dégradé conical à deux points, de sorte que la page dégradé conicale dérive de InteractivePage pour permettre à deux points tactiles d’être déplacés pour les deux rayons du cercle :

<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>

Le fichier code-behind définit les deux TouchPoint objets avec un rayon fixe de 50 et 100 :

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);
            }
        }
    }
}

Le colors tableau est rouge, vert et bleu. Le code vers le bas du PaintSurface gestionnaire dessine les deux points tactiles sous forme de cercles noirs afin qu’ils n’obstruent pas le dégradé.

Notez que l’appel DrawRect utilise le dégradé pour colorer l’intégralité du canevas. Dans le cas général, cependant, une grande partie de la zone de dessin reste non colorée par le dégradé. Voici le programme montrant trois configurations possibles :

Dégradé conical

L’écran iOS à gauche affiche l’effet du SKShaderTileMode paramètre de Clamp. Le dégradé commence par le rouge à l’intérieur du bord du plus petit cercle qui est opposé au côté le plus proche du deuxième cercle. La Clamp valeur provoque également le rouge jusqu’au point du cône. Le dégradé se termine par du bleu au bord extérieur du cercle plus grand qui est le plus proche du premier cercle, mais continue avec le bleu dans ce cercle et au-delà.

L’écran Android est similaire mais avec un SKShaderTileMode de Repeat. Maintenant, il est plus clair que le dégradé commence à l’intérieur du premier cercle et se termine à l’extérieur du deuxième cercle. Le Repeat paramètre entraîne la répétition du dégradé avec du rouge à l’intérieur du cercle plus grand.

L’écran UWP montre ce qui se passe lorsque le cercle plus petit est déplacé entièrement à l’intérieur du cercle plus grand. Le dégradé s’arrête en tant que cône et remplit plutôt toute la zone. L’effet est similaire au dégradé radial, mais il est asymétrique si le cercle plus petit n’est pas exactement centré dans le cercle plus grand.

Vous pouvez douter de l’utilité pratique du dégradé quand un cercle est imbriqué dans un autre, mais il est idéal pour une mise en surbrillance spéculaire.

Dégradés coniques pour les surbrillances spéculaires

Plus haut dans cet article, vous avez vu comment utiliser un dégradé radial pour créer une mise en surbrillance spéculaire. Vous pouvez également utiliser le dégradé conical à deux points à cet effet, et vous pouvez préférer la façon dont il ressemble :

Mise en surbrillance spéculaire conique

L’apparence asymétrique suggère mieux la surface arrondie de l’objet.

Le code de dessin dans la page Mise en surbrillance spéculaire conicale est identique à la page Mise en surbrillance spéculaire radiale, à l’exception du nuanceur :

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);
        }
    }
}

Les deux cercles ont des centres de offCenter et center. Le cercle centré à center est associé à un rayon qui englobe la boule entière, mais le cercle centré à a offCenter un rayon d’un seul pixel. Le dégradé commence efficacement à ce point et se termine au bord de la balle.