如何在Xamarin表单上使用SkiaSharp加载.svg文件?

问题描述 投票:0回答:2

如何在Xamarin Forms(Android和iOS)上用.svg加载文件SkiaSharp

我尝试过Load SVG file in Xamarin with SkiaSharp,但无法加载。

我尝试使用SkiaSharp.Extended并参考他们的演示,但仍然无法加载它。

我做错什么了吗?

请帮助我!

xamarin xamarin.forms xamarin.android xamarin.ios skiasharp
2个回答
0
投票

B1] >>在项目Images中创建一个文件夹Xamarin forms,并在此保存图像.svg。确保选择Build Action作为“嵌入资源”

EmbeddedResource

B2] >>下载所需的库,例如:SkiaSharpSkiaSharp.Views.FormsSkiaSharp.Extended.Svg

B3] >>在behind code处,对Page的构造器使用LoadSvg(xCanvasView.AutomationId)方法(Example:Page为ListNewConversationPage)。并声明所需的功能:

 private SKSvg svg;

        // Get file .svg to folder Images
    private static Stream GetImageStream(string svgName)
    {
        var type = typeof(ListNewConversationPage).GetTypeInfo();
        var assembly = type.Assembly;

        var abc = assembly.GetManifestResourceStream($"{assembly.GetName().Name}.Images.{svgName}");
        return abc;
    }


        private void LoadSvg(string svgName)
    {
        // create a new SVG object
        svg = new SKSvg();

        // load the SVG document from a stream
        using (var stream = GetImageStream(svgName))
            svg.Load(stream);
    }


        private void OnPageAppearing(object sender, EventArgs e)
    {
        svg = null;

        var page = (ContentPage)sender;
        LoadSvg(page.AutomationId);

        var canvas = (SKCanvasView)page.Content;
        canvas.InvalidateSurface();
    }

        private void OnPainting(object sender, SKPaintSurfaceEventArgs e)
    {
        try
        {
            var surface = e.Surface;
            var canvas = surface.Canvas;

            var width = e.Info.Width;
            var height = e.Info.Height;

            // clear the surface
            canvas.Clear(SKColors.White);

            // the page is not visible yet
            if (svg == null)
                return;

            // calculate the scaling need to fit to screen
            float scaleX = width / svg.Picture.CullRect.Width;
            float scaleY = height / svg.Picture.CullRect.Height;
            var matrix = SKMatrix.MakeScale(scaleX, scaleY);

            // draw the svg
            canvas.DrawPicture(svg.Picture, ref matrix);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex);
        }
    }

B4] >>在.xaml文件中,将其与.svg图像一起使用,即image_part_circle.svg

                   <forms:SKCanvasView x:Name="xCanvasView"
                                   PaintSurface="OnPainting"
                                   HorizontalOptions="FillAndExpand"
                                   VerticalOptions="FillAndExpand"
                                   BackgroundColor="Blue"
                                   AutomationId="image_part_circle.svg" />

请在SkiaSharp.Extended查看更多信息>

需要安装以下软件包SkiaSharp.Views.FormsSkiaSharp.ExtendedSkiaSharp.Svg。从那里我创建了一个自定义Xamarin.Forms控件,如下所示:

    public class SvgImage : SKCanvasView
    {
        public static readonly BindableProperty SourceProperty = BindableProperty.Create(nameof(Source), typeof(string), typeof(SvgImage), default(string), propertyChanged: OnPropertyChanged);

        public string Source
        {
            get => (string)GetValue(SourceProperty);
            set => SetValue(SourceProperty, value);
        }

        public static readonly BindableProperty AssemblyNameProperty = BindableProperty.Create(nameof(AssemblyName), typeof(string), typeof(SvgImage), default(string), propertyChanged: OnPropertyChanged);

        public string AssemblyName
        {
            get => (string)GetValue(AssemblyNameProperty);
            set => SetValue(AssemblyNameProperty, value);
        }

        static void OnPropertyChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var skCanvasView = bindable as SKCanvasView;
            skCanvasView?.InvalidateSurface();
        }

        protected override void OnBindingContextChanged()
        {
            base.OnBindingContextChanged();

            InvalidateSurface();
        }

        protected override void OnSizeAllocated(double width, double height)
        {
            base.OnSizeAllocated(width, height);

            InvalidateSurface();
        }

        protected override void OnPaintSurface(SKPaintSurfaceEventArgs e)
        {
            base.OnPaintSurface(e);

            try
            {
                var surface = e.Surface;
                var canvas = surface.Canvas;

                canvas.Clear();

                if (string.IsNullOrEmpty(Source) || string.IsNullOrEmpty(AssemblyName))
                    return;

                var currentAssembly = Assembly.Load(AssemblyName);
                using (var stream = currentAssembly.GetManifestResourceStream(AssemblyName + "." + Source))
                {
                    var skSvg = new SKSvg();
                    skSvg.Load(stream);

                    var skImageInfo = e.Info;
                    canvas.Translate(skImageInfo.Width / 2f, skImageInfo.Height / 2f);

                    var skRect = skSvg.ViewBox;
                    float xRatio = skImageInfo.Width / skRect.Width;
                    float yRatio = skImageInfo.Height / skRect.Height;

                    float ratio = Math.Min(xRatio, yRatio);

                    canvas.Scale(ratio);
                    canvas.Translate(-skRect.MidX, -skRect.MidY);

                    canvas.DrawPicture(skSvg.Picture);
                }
            }
            catch (Exception exc)
            {
                Console.WriteLine("OnPaintSurface Exception: " + exc);
            }
        }
    }

我确实必须指定程序集和Svg图像的文件夹路径才能找到该图像,并且任何Svg图像均应设置为EmbeddedResource。然后在Xaml中使用控件:

<controls:SvgImage AssemblyName="SkiaSharpSvgImage" Source="Resources.tux1.svg" />

我创建的整个开源测试项目都可以在Github上查看。另外,该仓库可能会得到改进,但这是我第一次使用SkiaSharp Svg图像并测试所有内容。


1
投票

需要安装以下软件包SkiaSharp.Views.FormsSkiaSharp.ExtendedSkiaSharp.Svg。从那里我创建了一个自定义Xamarin.Forms控件,如下所示:

    public class SvgImage : SKCanvasView
    {
        public static readonly BindableProperty SourceProperty = BindableProperty.Create(nameof(Source), typeof(string), typeof(SvgImage), default(string), propertyChanged: OnPropertyChanged);

        public string Source
        {
            get => (string)GetValue(SourceProperty);
            set => SetValue(SourceProperty, value);
        }

        public static readonly BindableProperty AssemblyNameProperty = BindableProperty.Create(nameof(AssemblyName), typeof(string), typeof(SvgImage), default(string), propertyChanged: OnPropertyChanged);

        public string AssemblyName
        {
            get => (string)GetValue(AssemblyNameProperty);
            set => SetValue(AssemblyNameProperty, value);
        }

        static void OnPropertyChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var skCanvasView = bindable as SKCanvasView;
            skCanvasView?.InvalidateSurface();
        }

        protected override void OnBindingContextChanged()
        {
            base.OnBindingContextChanged();

            InvalidateSurface();
        }

        protected override void OnSizeAllocated(double width, double height)
        {
            base.OnSizeAllocated(width, height);

            InvalidateSurface();
        }

        protected override void OnPaintSurface(SKPaintSurfaceEventArgs e)
        {
            base.OnPaintSurface(e);

            try
            {
                var surface = e.Surface;
                var canvas = surface.Canvas;

                canvas.Clear();

                if (string.IsNullOrEmpty(Source) || string.IsNullOrEmpty(AssemblyName))
                    return;

                var currentAssembly = Assembly.Load(AssemblyName);
                using (var stream = currentAssembly.GetManifestResourceStream(AssemblyName + "." + Source))
                {
                    var skSvg = new SKSvg();
                    skSvg.Load(stream);

                    var skImageInfo = e.Info;
                    canvas.Translate(skImageInfo.Width / 2f, skImageInfo.Height / 2f);

                    var skRect = skSvg.ViewBox;
                    float xRatio = skImageInfo.Width / skRect.Width;
                    float yRatio = skImageInfo.Height / skRect.Height;

                    float ratio = Math.Min(xRatio, yRatio);

                    canvas.Scale(ratio);
                    canvas.Translate(-skRect.MidX, -skRect.MidY);

                    canvas.DrawPicture(skSvg.Picture);
                }
            }
            catch (Exception exc)
            {
                Console.WriteLine("OnPaintSurface Exception: " + exc);
            }
        }
    }

我确实必须指定程序集和Svg图像的文件夹路径才能找到该图像,并且任何Svg图像均应设置为EmbeddedResource。然后在Xaml中使用控件:

<controls:SvgImage AssemblyName="SkiaSharpSvgImage" Source="Resources.tux1.svg" />
© www.soinside.com 2019 - 2024. All rights reserved.