Die SkiaSharp Kreisläufe
Die SKShader
Klasse definiert statische Methoden, um vier verschiedene Arten von Farbverläufen zu erstellen. Im Linearverlaufsartikel "SkiaSharp" wird die CreateLinearGradient
Methode erläutert. In diesem Artikel werden die anderen drei Arten von Farbverläufen behandelt, die alle auf Kreisen basieren.
Die CreateRadialGradient
Methode erstellt einen Farbverlauf, der von der Mitte eines Kreises ausgeht:
Die CreateSweepGradient
Methode erstellt einen Farbverlauf, der sich um die Mitte eines Kreises bewegt:
Der dritte Farbverlaufstyp ist ziemlich ungewöhnlich. Er wird als zweizeihigen konischen Farbverlauf bezeichnet und wird durch die CreateTwoPointConicalGradient
Methode definiert. Der Farbverlauf erstreckt sich von einem Kreis zu einem anderen:
Wenn die beiden Kreise unterschiedliche Größen aufweisen, nimmt der Farbverlauf die Form eines Kegels an.
In diesem Artikel werden diese Farbverläufe ausführlicher behandelt.
Radialer Farbverlauf
Die CreateRadialGradient
Methode weist die folgende Syntax auf:
public static SKShader CreateRadialGradient (SKPoint center,
Single radius,
SKColor[] colors,
Single[] colorPos,
SKShaderTileMode mode)
Eine CreateRadialGradient
Überladung enthält auch einen Transformationsmatrixparameter.
Die ersten beiden Argumente geben die Mitte eines Kreises und einen Radius an. Der Farbverlauf beginnt in dieser Mitte und erstreckt sich nach außen für radius
Pixel. Was darüber hinaus radius
geschieht, hängt von dem SKShaderTileMode
Argument ab. Der colors
Parameter ist ein Array von zwei oder mehr Farben (genau wie bei den linearen Farbverlaufsmethoden) und colorPos
ein Array von ganzzahligen Zahlen im Bereich von 0 bis 1. Diese ganzzahligen Zahlen geben die relativen Positionen der Farben entlang dieser radius
Linie an. Sie können dieses Argument null
auf einen gleichmäßigen Abstand der Farben festlegen.
Wenn Sie CreateRadialGradient
einen Kreis ausfüllen, können Sie die Mitte des Farbverlaufs auf die Mitte des Kreises und den Radius des Farbverlaufs auf den Radius des Kreises festlegen. In diesem Fall hat das SKShaderTileMode
Argument keine Auswirkungen auf das Rendern des Farbverlaufs. Wenn der durch den Farbverlauf gefüllte Bereich jedoch größer als der durch den Farbverlauf definierte Kreis ist, hat das SKShaderTileMode
Argument einen tiefen Einfluss auf das, was außerhalb des Kreises geschieht.
Der Effekt SKShaderMode
wird auf der Radialverlaufsseite im Beispiel veranschaulicht. Die XAML-Datei für diese Seite instanziiert ein Picker
Element, mit dem Sie eines der drei Elemente der SKShaderTileMode
Enumeration auswählen können:
<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>
Die CodeBehind-Datei farben den gesamten Zeichenbereich mit einem radialen Farbverlauf. Die Mitte des Farbverlaufs wird auf die Mitte des Zeichenbereichs festgelegt, und der Radius wird auf 100 Pixel festgelegt. Der Farbverlauf besteht aus nur zwei Farben, Schwarzweiß:
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);
}
}
}
Dieser Code erstellt einen Farbverlauf mit Schwarz in der Mitte, der allmählich von der Mitte auf weiße 100 Pixel verblassen wird. Was über diesen Radius hinaus geschieht, hängt von dem SKShaderTileMode
Argument ab:
In allen drei Fällen füllt der Farbverlauf den Zeichenbereich. Auf dem iOS-Bildschirm links wird der Farbverlauf über den Radius mit der letzten Farbe fortgesetzt, die weiß ist. Das ist das Ergebnis von SKShaderTileMode.Clamp
. Der Android-Bildschirm zeigt den Effekt von SKShaderTileMode.Repeat
: Bei 100 Pixeln von der Mitte beginnt der Farbverlauf erneut mit der ersten Farbe, die schwarz ist. Der Farbverlauf wiederholt alle 100 Pixel Radius.
Der Universelle Windows-Plattform Bildschirm rechts zeigt, wie SKShaderTileMode.Mirror
die Farbverläufe zu alternativen Richtungen führen. Der erste Farbverlauf ist von Schwarz in der Mitte bis weiß mit einem Radius von 100 Pixel. Die nächste ist weiß vom Radius von 100 Pixeln bis schwarz bei einem Radius von 200 Pixeln, und der nächste Farbverlauf wird wieder umgekehrt.
Sie können mehr als zwei Farben in einem Radialverlauf verwenden. Das Rainbow Arc Gradient-Beispiel erstellt ein Array von acht Farben, die den Farben des Regenbogens entsprechen und mit Rot enden, und außerdem ein Array von acht Positionswerten:
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);
}
}
}
Angenommen, das Minimum der Breite und Höhe des Zeichenbereichs beträgt 1000, was bedeutet, dass der rainbowWidth
Wert 250 ist. Die outerRadius
Werte innerRadius
werden auf 1000 bzw. 750 festgelegt. Diese Werte werden für die Berechnung des positions
Arrays verwendet; die acht Werte reichen von 0,75f bis 1. Der radius
Wert wird zum Streichen des Kreises verwendet. Der Wert von 875 bedeutet, dass die 250-Pixel-Strichbreite zwischen dem Radius von 750 Pixel und dem Radius von 1000 Pixeln erweitert wird:
Wenn Sie den gesamten Zeichenbereich mit diesem Farbverlauf gefüllt haben, sehen Sie, dass er innerhalb des inneren Radius rot ist. Dies liegt daran, dass das positions
Array nicht mit 0 beginnt. Die erste Farbe wird für Offsets von 0 bis zum ersten Arraywert verwendet. Der Farbverlauf ist auch rot über den äußeren Radius hinaus. Das ist das Ergebnis des Clamp
Kachelmodus. Da der Farbverlauf zum Streichen einer dicken Linie verwendet wird, sind diese roten Bereiche nicht sichtbar.
Radiale Farbverläufe für die Maskierung
Wie lineare Farbverläufe können radiale Farbverläufe transparente oder teilweise transparente Farben enthalten. Dieses Feature ist nützlich für einen Prozess namens Maskierung, der einen Teil eines Bilds ausblendet, um einen anderen Teil des Bilds hervorzuheben.
Die Seite "Radialverlaufsmaske " zeigt ein Beispiel. Das Programm lädt eine der Ressourcenbitmaps. Die Felder und RADIUS
Felder CENTER
wurden aus einer Untersuchung der Bitmap bestimmt und verweisen auf einen Bereich, der hervorgehoben werden soll. Der PaintSurface
Handler beginnt mit der Berechnung eines Rechtecks zum Anzeigen der Bitmap und zeigt es dann in diesem Rechteck an:
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);
}
}
}
Nach dem Zeichnen der Bitmap werden einige einfache Code konvertiert CENTER
und RADIUS
in center
und radius
, die auf den hervorgehobenen Bereich in der Bitmap verweisen, die für die Anzeige skaliert und verschoben wurde. Diese Werte werden verwendet, um einen radialen Farbverlauf mit dieser Mitte und dem Radius zu erstellen. Die beiden Farben beginnen in der Mitte transparent und für die ersten 60 % des Radius. Der Farbverlauf wird dann auf Weiß ausgeblendet:
Dieser Ansatz ist nicht die beste Methode zum Maskieren einer Bitmap. Das Problem besteht darin, dass die Maske hauptsächlich eine Farbe weiß hat, die dem Hintergrund des Zeichenbereichs entspricht. Wenn der Hintergrund eine andere Farbe ( oder vielleicht ein Farbverlauf selbst ) aufweist, stimmt er nicht überein. Ein besserer Ansatz zur Maskierung wird im Artikel SkiaSharp Porter-Duff Blend Modi gezeigt.
Radiale Farbverläufe für Glanzlichter
Wenn ein Licht auf eine abgerundete Oberfläche trifft, spiegelt es Licht in viele Richtungen wider, aber einige des Lichts springt direkt ins Auge des Betrachters. Dies erzeugt oft das Erscheinungsbild eines fuzzy weißen Bereichs auf der Oberfläche, der als glanzhafte Hervorhebung bezeichnet wird.
In dreidimensionalen Grafiken ergeben sich glanzförmige Hervorhebungen häufig aus den Algorithmen, die verwendet werden, um Lichtpfade und Schattierung zu bestimmen. In zweidimensionalen Grafiken werden glanzförmige Hervorhebungen manchmal hinzugefügt, um die Darstellung einer 3D-Oberfläche vorzuschlagen. Eine glanzförmige Hervorhebung kann einen flachen roten Kreis in einen runden roten Ball umwandeln.
Auf der Seite "Radiale Glanzherhebung " wird ein radialer Farbverlauf verwendet, um genau dies zu tun. Der PaintSurface
Handler wird durch Berechnen eines Radius für den Kreis und zwei SKPoint
Werte - ein center
und ein offCenter
Halbweg zwischen der Mitte und dem oberen linken Rand des Kreises:
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);
}
}
}
Der CreateRadialGradient
Aufruf erstellt einen Farbverlauf, der an offCenter
diesem Punkt mit weiß beginnt und mit Rot in einem Abstand von der Hälfte des Radius endet. Das Fenster sieht so aus:
Wenn Sie diesen Farbverlauf genau betrachten, können Sie entscheiden, dass er fehlerhaft ist. Der Farbverlauf ist um einen bestimmten Punkt zentriert, und Sie möchten, dass er etwas weniger symmetrisch war, um die abgerundete Oberfläche widerzuspiegeln. In diesem Fall bevorzugen Sie möglicherweise die glanzliche Hervorhebung unten im Abschnitt Conical Gradients für Glanzlichter.
Der Aufräumverlauf
Die CreateSweepGradient
Methode weist die einfachste Syntax aller Farbverlaufsmethoden auf:
public static SKShader CreateSweepGradient (SKPoint center,
SKColor[] colors,
Single[] colorPos)
Es handelt sich nur um eine Mitte, ein Array von Farben und die Farbpositionen. Der Farbverlauf beginnt rechts vom Mittelpunkt und reißt um 360 Grad im Uhrzeigersinn um die Mitte. Beachten Sie, dass kein SKShaderTileMode
Parameter vorhanden ist.
Eine CreateSweepGradient
Überladung mit einem Matrixtransformationsparameter ist ebenfalls verfügbar. Sie können eine Drehungstransformation auf den Farbverlauf anwenden, um den Ausgangspunkt zu ändern. Sie können auch eine Skalierungstransformation anwenden, um die Richtung vom Uhrzeigersinn in den Uhrzeigersinn zu ändern.
Die Seite "Farbverlauf aufräumen" verwendet einen Aufräumenfarbverlauf, um einen Kreis mit einer Strichbreite von 50 Pixeln zu färben:
Die SweepGradientPage
Klasse definiert ein Array von acht Farben mit unterschiedlichen Farbtonwerten. Beachten Sie, dass das Array mit Rot beginnt und endet (farbtonwert 0 oder 360), der ganz rechts in den Screenshots angezeigt wird:
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);
}
}
}
}
Das Programm implementiert außerdem einen TapGestureRecognizer
Code, der am Ende des PaintSurface
Handlers Code ermöglicht. Dieser Code verwendet denselben Farbverlauf, um den Zeichenbereich auszufüllen:
Diese Screenshots veranschaulichen, dass der Farbverlauf den von ihr gefärbten Bereich ausfüllt. Wenn der Farbverlauf nicht beginnt und mit derselben Farbe endet, wird rechts neben dem Mittelpunkt eine Einstellung angezeigt.
Der konische Farbverlauf mit zwei Punkten
Die CreateTwoPointConicalGradient
Methode weist die folgende Syntax auf:
public static SKShader CreateTwoPointConicalGradient (SKPoint startCenter,
Single startRadius,
SKPoint endCenter,
Single endRadius,
SKColor[] colors,
Single[] colorPos,
SKShaderTileMode mode)
Die Parameter beginnen mit Mittelpunkten und Radien für zwei Kreise, die als Startkreis und Endkreis bezeichnet werden. Die neu Standard drei Parameter sind identisch mit und CreateLinearGradient
CreateRadialGradient
. Eine CreateTwoPointConicalGradient
Überladung enthält eine Matrixtransformation.
Der Farbverlauf beginnt am Anfangskreis und endet am Endkreis. Der SKShaderTileMode
Parameter steuert, was über die beiden Kreise hinaus geschieht. Der zweizeige konische Farbverlauf ist der einzige Farbverlauf, der einen Bereich nicht vollständig ausfüllt. Wenn die beiden Kreise denselben Radius aufweisen, wird der Farbverlauf auf ein Rechteck mit einer Breite beschränkt, die dem Durchmesser der Kreise entspricht. Wenn die beiden Kreise unterschiedliche Radien aufweisen, bildet der Farbverlauf einen Kegel.
Es ist wahrscheinlich, dass Sie mit dem zweizeigen konischen Farbverlauf experimentieren möchten, sodass die Seite "Konischer Farbverlauf " abgeleitet InteractivePage
wird, um zwei Berührungspunkte für die zwei Kreisradien zu verschieben:
<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>
Die CodeBehind-Datei definiert die beiden TouchPoint
Objekte mit festen Radien von 50 und 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);
}
}
}
}
Das colors
Array ist rot, grün und blau. Der Code am unteren Rand des PaintSurface
Handlers zeichnet die beiden Berührungspunkte als schwarze Kreise, sodass sie den Farbverlauf nicht behindern.
Beachten Sie, dass DrawRect
der Aufruf den Farbverlauf verwendet, um den gesamten Zeichenbereich zu färben. Im allgemeinen ist jedoch ein Großteil der Canvas neu Standard durch den Farbverlauf nicht eingefärbt. Hier ist das Programm mit drei möglichen Konfigurationen:
Der iOS-Bildschirm links zeigt den Effekt der SKShaderTileMode
Einstellung von Clamp
. Der Farbverlauf beginnt mit Rot am Rand des kleineren Kreises, der sich gegenüber der Seite befindet, die dem zweiten Kreis am nächsten kommt. Der Clamp
Wert bewirkt auch, dass rot zum Punkt des Kegels fortgesetzt wird. Der Farbverlauf endet mit Blau am äußeren Rand des größeren Kreises, der dem ersten Kreis am nächsten kommt, aber weiter mit Blau innerhalb dieses Kreises und darüber hinaus.
Der Android-Bildschirm ist ähnlich, aber mit einer SKShaderTileMode
von Repeat
. Jetzt ist es klarer, dass der Farbverlauf innerhalb des ersten Kreises beginnt und außerhalb des zweiten Kreises endet. Die Repeat
Einstellung bewirkt, dass der Farbverlauf erneut mit Rot innerhalb des größeren Kreises wiederholt wird.
Der UWP-Bildschirm zeigt, was passiert, wenn der kleinere Kreis vollständig innerhalb des größeren Kreises verschoben wird. Der Farbverlauf stoppt als Kegel und füllt stattdessen den gesamten Bereich. Der Effekt ähnelt dem radialen Farbverlauf, ist aber asymmetrisch, wenn der kleinere Kreis nicht genau innerhalb des größeren Kreises zentriert ist.
Vielleicht zweifeln Sie an der praktischen Nützlichkeit des Farbverlaufs, wenn ein Kreis in einem anderen geschachtelt ist, aber es ist ideal für eine glanzliche Hervorhebung.
Konische Farbverläufe für Glanzlichter
Weiter oben in diesem Artikel haben Sie erfahren, wie Sie einen radialen Farbverlauf verwenden, um eine glanzförmige Hervorhebung zu erstellen. Sie können auch den zweizeigen konischen Farbverlauf für diesen Zweck verwenden, und Sie können es vorziehen, wie es aussieht:
Das asymmetrische Erscheinungsbild schlägt die abgerundete Oberfläche des Objekts besser vor.
Der Zeichencode auf der Seite "Konische Glanzvorhebung " entspricht der Seite "Radiale Glanzmarkierungen ", mit Ausnahme des Shaders:
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);
}
}
}
Die beiden Kreise haben Mittelpunkte offCenter
und center
. Der kreiszentrierte Kreis center
ist einem Radius zugeordnet, der den gesamten Ball umfasst, der kreiszentriert jedoch offCenter
einen Radius von nur einem Pixel hat. Der Farbverlauf beginnt effektiv an diesem Punkt und endet am Ballrand.