Blazor入门-简单svg绘制+导出图像

参考:
SVG 教程 | 菜鸟教程
https://www.runoob.com/svg/svg-tutorial.html

本地环境:win10, visual studio 2022 community


注意:本文只给出思路和框架,对于具体的计算细节,考虑到日后会写入软件著作权和专利文书,因此不会展示。(虽然大概率要经过修改后才会放进文书,但是考虑到隐私保护,还是不写了。不过基本都是三角函数)

效果

在这里插入图片描述
导出效果:
在这里插入图片描述

实现

思路

<svg>标签内,首先绘制两个圆,形成圆环;然后再使用循环,每次绘制一组<path><line><text>。需要着重考虑的是:

  • <path>的数据属性(d)、<line>中起终点坐标和<text>坐标的计算(这部分是三角函数,不展开)
  • 导出按钮的onclick函数编写
  • 实际的导出函数(js)

前端

    <div>
        <svg id="mySvg" width="100%" xmlns="http://www.w3.org/2000/svg" style="display:none">
            <rect  width="100%" height="100%" fill="white" />
            <circle cx="@cx" cy="@cy" r="@outerRadius" fill="#ccc" stroke="#ccc" stroke-width="1" />
            <circle cx="@cx" cy="@cy" r="@innerRadius" fill="#fff" stroke="#ccc" stroke-width="1" />
            @foreach (DisplayPart p in v.Parts)
            {
                <g>
                    <path d="@p.PathData" opacity="0.5" fill="@p.Color" stroke="black" stroke-width="2" data-toggle="tooltip" title="@p.Name" />
                    <line x1="@p.Lcx" y1="@p.Lcy" x2="@p.Tcx" y2="@p.Tcy" stroke="black" stroke-width="1" />
                    <text x="@p.Tcx" y="@p.Tcy" fill="black">@p.Name</text>
                </g>
                
            }
        </svg>
    </div>

    <div id="exportBtnDiv" style="display:none">
        <button value="" class="btn btn-primary" id="ExportSvgBtn" @onclick="ExportSvg">
            导出图谱
        </button>
    </div>

注意:

  • <rect width="100%" height="100%" fill="white" />是为svg增加白色背景
  • 其中@开头的变量都是在code中定义的
  • v.PartsList<DisplayPart>DisplayPart是自定义的一个类型

随后,在@code{}块中,实现ExportSvgBtn

    private async Task ExportSvg()
    {
        var svgElement = await JsRuntime.InvokeAsync<IJSObjectReference>("document.getElementById", "mySvg");
        await module.InvokeVoidAsync("exportSvgToImage", svgElement, "png");
    }

其中JsRuntime是:

@inject IJSRuntime JsRuntime

而module在前面定义过,这里用它可以调用在别处定义的js函数。
参考:
Blazor入门-调用js+例子-CSDN博客
https://blog.csdn.net/pxy7896/article/details/138670348

跟这篇文章里一样设置即可。

下载svg图像的js代码

export function exportSvgToImage(svgElement, format) {
    if (format == null)
        return;
    var svgXml = new XMLSerializer().serializeToString(svgElement);
    var imageUrl = "data:image/svg+xml;base64," + btoa(svgXml);
    var canvas = document.createElement("canvas");
    var ctx = canvas.getContext("2d");
    var img = new Image();
    img.onload = function () {
        canvas.width = img.width;
        canvas.height = img.height;
        ctx.drawImage(img, 0, 0);
        var a = document.createElement("a");
        a.download = "exported_image." + format;
        a.href = canvas.toDataURL("image/" + format);
        a.click();
    };
    img.src = imageUrl;
}

注意:函数前面写export的原因已在上一节的参考文章里解释。

报错

Error: Microsoft.JSInterop.JSException: Failed to execute ‘btoa’ on ‘Window’: The string to be encoded contains characters outside of the Latin1 range.

这个错误通常发生是因为要编码的字符串中包含了Latin1范围之外的字符。解决方案是修改 exportSvgToImage 函数的这句:

var imageUrl = "data:image/svg+xml;base64," + btoa(svgXml);

改为:

var utf8 = unescape(encodeURIComponent(svgXml));
var imageUrl = "data:image/svg+xml;base64," + btoa(utf8);

下载svg图像时,只显示一部分

使用上面下载图像的js代码时,输出的图像可能只有一部分,如下图所示:
在这里插入图片描述
解决方案是将canvas的宽高设置为跟svg元素一致:

    canvas.width = svgElement.clientWidth;
    canvas.height = svgElement.clientHeight;

改进

未来会通过算法调整label的位置和line的线形,以避免label重叠。如果可以的话,会再写:)

写了,但是写得有限,希望能有所启发吧。

Blazor入门-svg绘制-碰撞检测和图形坐标调整-CSDN博客
https://blog.csdn.net/pxy7896/article/details/139261297

  • 32
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vite是一个用于快速构建现代化的Web项目的构建工具,它专注于开发阶段的快速热重载,并使用ES模块作为原生的开发模式。Vue3是Vue.js的最新版本,它在性能、开发体验和可维护性上都有所提升。 针对你提到的具体的库和框架: - Vue Router是Vue.js官方的路由管理器,用于实现页面之间的导航和路由控制。你可以通过npm安装vue-router,并在项目中进行配置和使用。 - Pinia是Vue.js的状态管理库,它提供了一种简单而强大的方式来管理应用程序的状态。你可以集成Pinia到你的Vue项目中,以便更好地组织和共享你的应用程序状态。 - Axios是一个基于Promise的HTTP客户端,用于通过网络发送异步请求。你可以使用Axios来处理与服务器的通信,并获取数据来更新你的Vue应用程序。 - Element Plus是一套基于Vue3的组件库,包含了丰富的UI组件,可以帮助你快速搭建漂亮的用户界面。你可以在项目中安装和使用Element Plus来实现各种交互效果和用户界面。 如果你想使用Vite、Vue3和以上提到的库和框架来创建一个项目,你可以按照以下步骤进行: 1. 安装Vite:通过npm全局安装Vite,然后使用Vite命令初始化一个新的项目。 2. 配置Vite:根据你的项目需求,在Vite的配置文件中添加Vue Router、Pinia、Axios和Element Plus的相关配置。 3. 安装和配置Vue Router:通过npm安装Vue Router,并在项目中配置和使用Vue Router来管理应用程序的路由。 4. 集成Pinia:通过npm安装Pinia,并在项目中引入和配置Pinia,以便在应用程序中使用Pinia来管理状态。 5. 使用Axios:通过npm安装Axios,并在项目中引入和配置Axios,以便进行网络请求和数据获取。 6. 引入Element Plus:通过npm安装Element Plus,并在项目中按需引入和使用Element Plus的组件,以搭建漂亮的用户界面。 希望以上信息对你有帮助,祝你在使用Vite、Vue3和这些库和框架时取得成功!<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [vite-vue-ts精简模版集成pinia+svg+router+@src](https://download.csdn.net/download/ldy889/85018930)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [vite+vue3+ts+vue-router+pinia+axios+element-plus](https://blog.csdn.net/zy_080400/article/details/127125359)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值