0

我正在使用带有 angular 4 模板的 asp.net-core 构建一个 Web 应用程序,并使用 svg-edit 允许用户在移动设备上绘制/加载/保存图像,特别是在 IOS 设备/android 设备上。svg-edit 可以很好地满足我的需要,但我在 IOS 设备上遇到了一个关于生成/将用户绘图(svg)转换为另一种格式(png base64)的问题,该格式将作为 api 的一部分发布保存过程。

我使用以下代码使用 html canvas 将 svg 转换为 png base64

svg-editor.js

editor.getDrawingPngBase64 = function (svgString) {
            if (!$('#export_canvas').length) {
                $('<canvas>', { id: 'export_canvas' }).hide().appendTo('body');
            }

            var canvas = $('#export_canvas')[0];
            canvas.width = $("#svgcanvas").width();  // svgCanvas.contentW;
            canvas.height = $("#svgcanvas").height();  // svgCanvas.contentH;
            var ctx = canvas.getContext("2d");

            var promise = new Promise(function (resolve, reject) {
                function drawInlineSVG(ctx, rawSVG, callback) {
                    var svg = new Blob([rawSVG], { type: "image/svg+xml;charset=utf-8" }),
                        domURL = self.URL || self.webkitURL || self,
                        url = domURL.createObjectURL(svg),
                        img = new Image;

                    img.onload = function () {
                        ctx.drawImage(this, 0, 0);
                        var base64 = canvas.toDataURL("image/png");
                       resolve(base64);
                    };

                    img.src = url;
                } 

                drawInlineSVG(ctx, svgString);
            });

            return promise;
        }

但是,这只适用于使用 chrome 或 safari 浏览器的 IOS 设备。onload 方法根本没有被调用。我猜 svg 图像可能太大而无法转换。

我也尝试过这种方法,它也不能可靠地工作......

editor.getDrawingPngBase64 = function (svgString) {
            if (!$('#export_canvas').length) {
                $('<canvas>', { id: 'export_canvas' }).hide().appendTo('body');
            }

            var canvas = $('#export_canvas')[0];
            canvas.width = svgCanvas.contentW;
            canvas.height = svgCanvas.contentH;
            var ctx = canvas.getContext("2d");

            var promise = new Promise(function (resolve, reject) {
                function webkitNamespaceBugWorkaround(pText) {
                    var lText = pText.replace(/\ xlink=/g, " xmlns:xlink=", "g");
                    lText = lText.replace(/\ href=/g, " xlink:href=", "g");
                    return lText;
                }

                canvg(canvas, webkitNamespaceBugWorkaround(svgString), {
                    renderCallback: function () {
                        var base64 = canvas.toDataURL("image/png");
                        resolve(base64);
                    }
                });
            });

            return promise;
        }

我也试过canvg库,它也不能可靠地工作

这些方法由 angular4 component.ts 调用

    public save() {
const svgString: String = svgEditor.getSvgString();
(<any>window).svgEditor.getDrawingPngBase64(svgString).then(pngBase64: string) => {
             // Call api and save the image
         }
     }

我在客户端将 svg 转换为 png 的原因是因为我无法在 dotnet-core 解决方案(https://www.nuget.org/packages/Svg/)上安装 C# SVG 渲染库

请帮忙!

4

1 回答 1

0

我以前在 dotnetcore 解决方案上遇到过同样的问题,只是我没有使用 svg-edit。这是我针对此问题的解决方法....

使用 dotnet 框架创建一个新的控制台应用程序...并在包管理器上安装 Svg 库

>> Install-Package Svg -Version 2.3.0

在控制台应用程序的 Program.cs 中,读取 svg 文件并使用 Svg 库将其转换为 png 并使用 Console.WriteLine 输出

class Program
{
    static void Main(string[] args)
    {
        if (args.Length == 0)
            return;

        using (var oStream = new System.IO.MemoryStream())
        {
            string svgPath = args[0];

            if (string.IsNullOrWhiteSpace(svgPath))
                return;

            var text = System.IO.File.ReadAllText(svgPath);
            using (var xmlStream = new MemoryStream(Encoding.ASCII.GetBytes(text)))
            {
                xmlStream.Position = 0;
                var svgDocument = Svg.SvgDocument.Open<SvgDocument>(xmlStream);

                SetupThumbnailImage(svgDocument, out Bitmap bitmap, out Graphics graphics, 250, 120);
                svgDocument.Draw(graphics);

                bitmap.Save(oStream, ImageFormat.Png);

                string pngBase64String = Convert.ToBase64String(oStream.ToArray());
                Console.WriteLine(pngBase64String);
            }
        }
    }
}

在您的 dotnet-core 端,您需要将 SVG 发布回 api,将其保存在服务器上,将 consoleApp.exe 作为进程运行并从 StandardOutput 读取 base64。

private async Task<string> SaveThumbnailImage(string svgString)
{
    // Save the svg
    var filePath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "SvgHelper", Path.Combine(Guid.NewGuid() + ".svg"));
    using (StreamWriter streamWriter = System.IO.File.CreateText(filePath))
    {
        streamWriter.WriteLine(svgString);
    }

    Process process = new Process();
    process.StartInfo.FileName = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "SvgHelper", "lib.svgToPng.exe");
    process.StartInfo.Arguments = filePath;
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardOutput = true;
    process.StartInfo.CreateNoWindow = true;
    process.Start();

    // Read the base64String from StandardOutput
    string base64String = process.StandardOutput.ReadToEnd();
    process.WaitForExit();

    // Clean up the file
    System.IO.File.Delete(filePath);
}
于 2018-06-05T15:43:25.297 回答