简体   繁体   中英

How to load file .svg with SkiaSharp on Xamarin forms?

How to load file .svg with SkiaSharp on Xamarin Forms (Android and iOS).

I tried Load SVG file in Xamarin with SkiaSharp , but i can't load it.

I tried to use SkiaSharp.Extended and refer to their Demos, but still cannot load it.

Am I doing anything wrong?

please help me!

B1 > Create a folder Images in your project Xamarin forms and save image .svg at this. Make sure you select Build Action as "EmbeddedResource"

嵌入式资源

B2 > Download the required libraries like: SkiaSharp , SkiaSharp.Views.Forms , SkiaSharp.Extended.Svg

B3 > At behind code , use method LoadSvg(xCanvasView.AutomationId) at contructor of Page ( Example : Page is ListNewConversationPage ). And declare the required functions:

 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 > At .xaml file, use it with .svg image is image_part_circle.svg

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

Please see more at SkiaSharp.Extended

The following packages need to be installed SkiaSharp.Views.Forms , SkiaSharp.Extended , and SkiaSharp.Svg . From there I created a custom Xamarin.Forms control like so:

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

I did have to specify the assembly and the folder path to the Svg image for it to find the image and any Svg images should be set to EmbeddedResource . Then to use the control in Xaml:

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

The entire opensource test project I created can be viewed on Github . Also, that repo could probably be improved but that was my first runabout using SkiaSharp Svg images and testing everything out.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM