Xamarin Forms中FFImageLoading SVG能否无SkiaSharp实现混合?及XAML整合方案
FFImageLoading SVG混合效果与SkiaSharp结合方案
一、FFImageLoading SVG原生支持混合模式吗?
不支持。SvgCachedImage本身没有内置像素级混合模式的属性或默认Transformation,你当前的叠加方式只是简单的层级覆盖,无法实现Opacity之外的复杂混合效果(比如正片叠底、滤色这类)。
二、XAML中结合SkiaSharp与FFImageLoading实现低代码复用?
完全零后台代码的方案做不到,因为SkiaSharp的混合逻辑依赖SKCanvas的绘制上下文操作。但可以通过两种方式实现高度复用的XAML代码:
方案1:自定义FFImageLoading Transformation
写一个继承自TransformationBase的自定义变换,内部用SkiaSharp实现混合逻辑,之后就能在XAML中直接引用,无需重复编写后台代码。
public class BlendTransformation : TransformationBase { public SKBlendMode BlendMode { get; set; } = SKBlendMode.Multiply; public string OverlaySvgPath { get; set; } protected override SKBitmap Transform(SKBitmap sourceBitmap, string path) { var overlaySvg = new SKSvg(); overlaySvg.Load(OverlaySvgPath); var overlayBitmap = overlaySvg.ToBitmap(sourceBitmap.Width, sourceBitmap.Height); using var canvas = new SKCanvas(sourceBitmap); using var paint = new SKPaint { BlendMode = BlendMode }; canvas.DrawBitmap(overlayBitmap, 0, 0, paint); return sourceBitmap; } public override string Key => $"Blend:{BlendMode};Overlay:{OverlaySvgPath}"; }
XAML中使用(先在资源中声明):
<ContentPage.Resources> <local:BlendTransformation x:Key="StarBlend" BlendMode="Screen" OverlaySvgPath="resource://uCue_Silver.Resources.SVGs.star_m.svg"/> </ContentPage.Resources> <svg:SvgCachedImage Source="resource://uCue_Silver.Resources.SVGs.star_m.svg" WidthRequest="200" HeightRequest="200"> <svg:SvgCachedImage.Transformations> <fftransformations:TintTransformation HexColor="#FFFFFF" EnableSolidColor="True"/> <local:BlendTransformation BlendMode="Multiply" OverlaySvgPath="resource://uCue_Silver.Resources.SVGs.s2.svg"/> </svg:SvgCachedImage.Transformations> </svg:SvgCachedImage>
方案2:封装SkiaSharp自定义View
直接用SKCanvasView封装一个可复用的混合绘制控件,后台只写一次绘制逻辑,XAML中直接引用这个控件即可:
<!-- 封装后的自定义View --> <ContentView 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="YourNamespace.BlendedSvgView"> <skia:SKCanvasView x:Name="CanvasView" PaintSurface="CanvasView_PaintSurface"/> </ContentView>
后台代码(仅编写一次):
private void CanvasView_PaintSurface(object sender, SKPaintSurfaceEventArgs e) { var canvas = e.Surface.Canvas; canvas.Clear(); var size = e.Info.Size; // 绘制第一个星星(白色,无混合) var star1 = new SKSvg(); star1.Load("resource://uCue_Silver.Resources.SVGs.star_m.svg"); using var star1Paint = new SKPaint { Color = SKColor.Parse("#FFFFFF") }; canvas.DrawPicture(star1.Picture, SKMatrix.MakeScale(size.Width / star1.Picture.CullRect.Width, size.Height / star1.Picture.CullRect.Height), star1Paint); // 绘制第二个星星(黄色,正片叠底混合) var star2 = new SKSvg(); star2.Load("resource://uCue_Silver.Resources.SVGs.star_m.svg"); using var star2Paint = new SKPaint { Color = SKColor.Parse("#FFFF00"), BlendMode = SKBlendMode.Multiply }; var star2Scale = 0.8f; canvas.DrawPicture(star2.Picture, SKMatrix.MakeScale(size.Width * star2Scale / star2.Picture.CullRect.Width, size.Height * star2Scale / star2.Picture.CullRect.Height), star2Paint); // 绘制第三个SVG(白色,滤色混合,翻转) var s2 = new SKSvg(); s2.Load("resource://uCue_Silver.Resources.SVGs.s2.svg"); using var s2Paint = new SKPaint { Color = SKColor.Parse("#FFFFFF"), BlendMode = SKBlendMode.Screen }; var flipScale = 0.8f; var flipMatrix = SKMatrix.MakeScale(-flipScale, flipScale); flipMatrix.TransX = size.Width; // 修正翻转后的偏移 canvas.DrawPicture(s2.Picture, flipMatrix, s2Paint); }
之后在任意XAML页面直接引用:
<local:BlendedSvgView WidthRequest="200" HeightRequest="200"/>
总结
- FFImageLoading SVG原生没有混合模式支持,必须借助SkiaSharp扩展实现。
- 完全无后台代码的XAML方案不可行,但通过自定义Transformation或封装SkiaSharp控件,可以实现高度复用的XAML代码。
内容的提问来源于stack exchange,提问作者ThisQRequiresASpecialist
相关产品推荐
相关产品推荐

