Transparencia de SkiaSharp
Como ha visto, la clase SKPaint
incluye una propiedad Color
de tipo SKColor
. SKColor
incluye un canal alfa, por lo que todo lo que se colorea con un valor SKColor
puede ser parcialmente transparente.
Se mostró la transparencia en cierta medida en el artículo Animación básica en SkiaSharp. En este artículo, se profundiza algo más en la transparencia para combinar varios objetos en una sola escena, una técnica a veces conocida como combinación. En los artículos de la sección Sombreadores de SkiaSharp, se tratan técnicas de combinación más avanzadas.
Puede establecer el nivel de transparencia al crear por primera vez un color mediante el constructor SKColor
de cuatro parámetros:
SKColor (byte red, byte green, byte blue, byte alpha);
Un valor alfa de 0 es totalmente transparente y un valor alfa de 0xFF es totalmente opaco. Los valores entre esos dos extremos crean colores que son parcialmente transparentes.
Además, SKColor
define un práctico método WithAlpha
que crea un nuevo color a partir de un color existente, pero con el nivel alfa especificado:
SKColor halfTransparentBlue = SKColors.Blue.WithAlpha(0x80);
El uso de texto parcialmente transparente se muestra en la página Code More Code del ejemplo. Esta página atenúa dos cadenas de texto de entrada y salida mediante la incorporación de transparencia en los valores SKColor
:
public class CodeMoreCodePage : ContentPage
{
SKCanvasView canvasView;
bool isAnimating;
Stopwatch stopwatch = new Stopwatch();
double transparency;
public CodeMoreCodePage ()
{
Title = "Code More Code";
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 = 5; // seconds
double progress = stopwatch.Elapsed.TotalSeconds % duration / duration;
transparency = 0.5 * (1 + Math.Sin(progress * 2 * Math.PI));
canvasView.InvalidateSurface();
return isAnimating;
}
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
canvas.Clear();
const string TEXT1 = "CODE";
const string TEXT2 = "MORE";
using (SKPaint paint = new SKPaint())
{
// Set text width to fit in width of canvas
paint.TextSize = 100;
float textWidth = paint.MeasureText(TEXT1);
paint.TextSize *= 0.9f * info.Width / textWidth;
// Center first text string
SKRect textBounds = new SKRect();
paint.MeasureText(TEXT1, ref textBounds);
float xText = info.Width / 2 - textBounds.MidX;
float yText = info.Height / 2 - textBounds.MidY;
paint.Color = SKColors.Blue.WithAlpha((byte)(0xFF * (1 - transparency)));
canvas.DrawText(TEXT1, xText, yText, paint);
// Center second text string
textBounds = new SKRect();
paint.MeasureText(TEXT2, ref textBounds);
xText = info.Width / 2 - textBounds.MidX;
yText = info.Height / 2 - textBounds.MidY;
paint.Color = SKColors.Blue.WithAlpha((byte)(0xFF * transparency));
canvas.DrawText(TEXT2, xText, yText, paint);
}
}
}
El campo transparency
se anima para variar de 0 a 1 y se devuelve a un ritmo sinusoidal. La primera cadena de texto se muestra con un valor alfa calculado al restar el valor transparency
de 1:
paint.Color = SKColors.Blue.WithAlpha((byte)(0xFF * (1 - transparency)));
El método WithAlpha
establece el componente alfa en un color existente, que aquí es SKColors.Blue
. La segunda cadena de texto usa un valor alfa calculado a partir del propio valor de transparency
:
paint.Color = SKColors.Blue.WithAlpha((byte)(0xFF * transparency));
En la animación, se alterna entre las dos palabras y se insta al usuario a "codificar más" (o quizás se solicite "más código"):
En el artículo anterior sobre conceptos básicos de mapa de bits en SkiaSharp, ha visto cómo mostrar mapas de bits mediante uno de los métodos DrawBitmap
de SKCanvas
. Todos los métodos DrawBitmap
incluyen un objeto SKPaint
como último parámetro. De forma predeterminada, este parámetro se establece en null
y puede omitirlo.
Como alternativa, puede establecer la propiedad Color
de este objeto SKPaint
para que muestre un mapa de bits con algún nivel de transparencia. Establecer un nivel de transparencia en la propiedad Color
de SKPaint
permite atenuar los mapas de bits dentro y fuera o disolver un mapa de bits en otro.
La transparencia del mapa de bits se muestra en la página Disolución de mapa de bits. El archivo XAML crea una instancia de SKCanvasView
y de Slider
:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:skia="clr-namespace:SkiaSharp.Views.Forms;assembly=SkiaSharp.Views.Forms"
x:Class="SkiaSharpFormsDemos.Effects.BitmapDissolvePage"
Title="Bitmap Dissolve">
<StackLayout>
<skia:SKCanvasView x:Name="canvasView"
VerticalOptions="FillAndExpand"
PaintSurface="OnCanvasViewPaintSurface" />
<Slider x:Name="progressSlider"
Margin="10"
ValueChanged="OnSliderValueChanged" />
</StackLayout>
</ContentPage>
El archivo de código subyacente carga dos recursos de mapa de bits. Estos mapas de bits no tienen el mismo tamaño, pero tienen la misma relación de aspecto:
public partial class BitmapDissolvePage : ContentPage
{
SKBitmap bitmap1;
SKBitmap bitmap2;
public BitmapDissolvePage()
{
InitializeComponent();
// Load two bitmaps
Assembly assembly = GetType().GetTypeInfo().Assembly;
using (Stream stream = assembly.GetManifestResourceStream(
"SkiaSharpFormsDemos.Media.SeatedMonkey.jpg"))
{
bitmap1 = SKBitmap.Decode(stream);
}
using (Stream stream = assembly.GetManifestResourceStream(
"SkiaSharpFormsDemos.Media.FacePalm.jpg"))
{
bitmap2 = SKBitmap.Decode(stream);
}
}
void OnSliderValueChanged(object sender, ValueChangedEventArgs args)
{
canvasView.InvalidateSurface();
}
void OnCanvasViewPaintSurface(object sender, SKPaintSurfaceEventArgs args)
{
SKImageInfo info = args.Info;
SKSurface surface = args.Surface;
SKCanvas canvas = surface.Canvas;
canvas.Clear();
// Find rectangle to fit bitmap
float scale = Math.Min((float)info.Width / bitmap1.Width,
(float)info.Height / bitmap1.Height);
SKRect rect = SKRect.Create(scale * bitmap1.Width,
scale * bitmap1.Height);
float x = (info.Width - rect.Width) / 2;
float y = (info.Height - rect.Height) / 2;
rect.Offset(x, y);
// Get progress value from Slider
float progress = (float)progressSlider.Value;
// Display two bitmaps with transparency
using (SKPaint paint = new SKPaint())
{
paint.Color = paint.Color.WithAlpha((byte)(0xFF * (1 - progress)));
canvas.DrawBitmap(bitmap1, rect, paint);
paint.Color = paint.Color.WithAlpha((byte)(0xFF * progress));
canvas.DrawBitmap(bitmap2, rect, paint);
}
}
}
La propiedad Color
del objeto SKPaint
se establece en dos niveles alfa complementarios para los dos mapas de bits. Cuando se usa SKPaint
con mapas de bits, no importa cuál es el resto del valor Color
. Lo único que importa es el canal alfa. El código aquí simplemente llama al método WithAlpha
en el valor predeterminado de la propiedad Color
.
Al mover el elemento Slider
, se disuelve un mapa de bits en el otro:
En los últimos artículos, ha visto cómo usar SkiaSharp para dibujar texto, círculos, elipses, rectángulos redondeados y mapas de bits. El siguiente paso es Líneas y trazados de SkiaSharp, en el que aprenderá a dibujar líneas conectadas en una ruta de gráficos.