SkiaSharp 透明度SkiaSharp transparency

下载示例下载示例Download Sample Download the sample

如您所见 SKPaint 类包括 Color 类型的属性 SKColor As you've seen, the SKPaint class includes a Color property of type SKColor. SKColor 包括 alpha 通道,因此,任何内容与着色SKColor值可以是部分透明。SKColor includes an alpha channel, so anything that you color with an SKColor value can be partially transparent.

中演示一些透明度 SkiaSharp 中的基本动画一文。Some transparency was demonstrated in the Basic Animation in SkiaSharp article. 本文将某种程度上更深入地探讨组合在一个场景,有时称为一种技术中的多个对象的透明度_混合_。This article goes somewhat deeper into transparency to combine multiple objects in a single scene, a technique sometimes known as blending. 更高级的混合技术的文章中讨论 SkiaSharp 着色器部分。More advanced blending techniques are discussed in the articles in the SkiaSharp shaders section.

首次创建使用四个参数的颜色时,可以设置的透明度级别 SKColor 构造函数:You can set the transparency level when you first create a color using the four-parameter SKColor constructor:

SKColor (byte red, byte green, byte blue, byte alpha);

Alpha 值为 0 是完全透明,完全不透明 alpha 值为 0xFF。An alpha value of 0 is fully transparent and an alpha value of 0xFF is fully opaque. 两个极端之间的值来创建部分透明的颜色。Values between those two extremes create colors that are partially transparent.

此外,SKColor定义方便 WithAlpha 从现有的颜色,但使用指定的 alpha 级别创建新颜色的方法:In addition, SKColor defines a handy WithAlpha method that creates a new color from an existing color but with the specified alpha level:

SKColor halfTransparentBlue = SKColors.Blue.WithAlpha(0x80);

使用部分透明的文本进行了演示代码更多代码页面 SkiaSharpFormsDemos 示例。The use of partially transparent text is demonstrated in the Code More Code page in the SkiaSharpFormsDemos sample. 此页淡两个文本字符串和缩小通过合并中的透明度SKColor值:This page fades two text strings in and out by incorporating transparency in the SKColor values:

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

transparency字段进行动画处理,以在 0 到 1 之间变化并切换回正弦节奏中。The transparency field is animated to vary from 0 to 1 and back again in a sinusoidal rhythm. 第一个文本字符串显示其 alpha 值中减去计算得出transparency取值范围为 1:The first text string is displayed with an alpha value calculated by subtracting the transparency value from 1:

paint.Color = SKColors.Blue.WithAlpha((byte)(0xFF * (1 - transparency)));

WithAlpha 方法的现有颜色,下面是上设置的 alpha 分量SKColors.BlueThe WithAlpha method sets the alpha component on an existing color, which here is SKColors.Blue. 第二个文本字符串使用计算出的 alpha 值transparency值本身:The second text string uses an alpha value calculated from the transparency value itself:

paint.Color = SKColors.Blue.WithAlpha((byte)(0xFF * transparency));

两个字,敦促用户"代码的详细信息"(或可能请求"更多代码") 之间交替动画:The animation alternates between the two words, urging the user to "code more" (or perhaps requesting "more code"):

代码更多的代码Code More Code

在上一篇文章中上 SkiaSharp 中的位图基础知识,了解了如何显示位图使用之一 DrawBitmap 方法的SKCanvasIn the previous article on Bitmap Basics in SkiaSharp, you saw how to display bitmaps using one of the DrawBitmap methods of SKCanvas. 所有DrawBitmap方法包括SKPaint对象作为最后一个参数。All the DrawBitmap methods include an SKPaint object as the last parameter. 默认情况下,此参数设置为null,可以忽略它。By default, this parameter is set to null and you can ignore it.

或者,可以设置Color属性的SKPaint对象来显示有一定的透明度的位图。Alternatively, you can set the Color property of this SKPaint object to display a bitmap with some level of transparency. 设置中的透明度级别Color属性的SKPaint允许您以淡入淡出中,位图或分解到另一个位图。Setting a level of transparency in the Color property of SKPaint allows you to fade bitmaps in and out, or to dissolve one bitmap into another.

中演示位图透明度位图消失页。Bitmap transparency is demonstrated in the Bitmap Dissolve page. XAML 文件实例化SKCanvasView和一个Slider:The XAML file instantiates an SKCanvasView and a 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>

代码隐藏文件加载两个位图资源。The code-behind file loads two bitmap resources. 这些位图不是大小相同,但它们是相同的纵横比:These bitmaps are not the same size, but they are the same aspect ratio:

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

Color属性的SKPaint对象设置为两个位图的两个互补 alpha 级别。The Color property of the SKPaint object is set to two complementary alpha levels for the two bitmaps. 使用时SKPaint与位图,它并不重要的其余Color值。When using SKPaint with bitmaps, it doesn't matter what the rest of the Color value is. 最重要的就是 alpha 通道。All that matters is the alpha channel. 下面的代码只是调用WithAlpha上的默认值的方法Color属性。The code here simply calls the WithAlpha method on the default value of the Color property.

移动Slider之间一个位图,另一个溶解以:Moving the Slider dissolves between one bitmap and the other:

位图消隐Bitmap Dissolve

在过去的几个文章中,已了解如何使用 SkiaSharp 绘制文本、 圆、 椭圆、 圆角的矩形和位图。In the past several articles, you have seen how to use SkiaSharp to draw text, circles, ellipses, rounded rectangles, and bitmaps. 下一步是SkiaSharp 线和路径在其中将学习如何相互连接的直线绘制图形路径中。The next step is SkiaSharp Lines and Paths in which you will learn how to draw connected lines in a graphics path.