ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

CAD图纸以SVG形式插入TinyMCE保持矢量清晰的完整方案

CAD图纸以SVG形式插入TinyMCE保持矢量清晰的完整方案 1. 为什么 CAD 图纸“粘贴”进 TinyMCE 会变成位图芯片制造企业的内部系统里TinyMCE 经常被用来做设备平面图、洁净室布局图、二次配管说明这类文档的在线编辑入口。很多 IT 同学上来就遇到一个问题工程师在 CAD 里选中图纸CtrlC切到 TinyMCE 的编辑区CtrlV粘贴出来的图确实能显示但一旦放大就糊成一片打印出来更是没法看。更麻烦的是后端拿到的内容是长长一串 Base64 的 PNG根本不是矢量数据后续没法做版本对比、不能拾取坐标也不能做文字检索。这个问题的根源不在 TinyMCE而是在“剪贴板到底传了什么”。1.1 剪贴板里到底放了什么CAD 软件在 Windows 上复制实体时并不是只放一张图片。以 AutoCAD 为例执行 COPY 或者 CtrlC 之后剪贴板里会同时包含多种格式AutoCAD 自己的图元数据、Enhanced MetafileEMF、Bitmap有的版本还会带 HTML 格式。这套机制和 Office 是配合好的所以你把图纸粘到 Word、PPT 里时Word 会优先取 EMF/WMF图形依然是矢量缩放不模糊。但浏览器不是这么工作的。Chrome、Edge、Firefox 在响应 paste 事件时能从系统剪贴板读取的数据种类很有限图像格式基本只认 PNG、JPEG、BMP 这类位图映射EMF/WMF 这种 Windows 专属的矢量图元格式浏览器拿不到也不会去解析。于是 CAD 明明往剪贴板里放了一份矢量数据浏览器看到的只有那张低分辨率位图TinyMCE 再把这张位图转成 data URL最终保存进数据库的就是img srcdata:image/png;base64,...。你在这个瞬间已经丢掉了矢量信息后面无论怎么调 TinyMCE 的配置都救不回来。1.2 TinyMCE 把粘贴内容当成了什么TinyMCE 的 paste 插件默认会拦截粘贴事件然后把剪贴板里的 HTML、纯文本、图片分别处理。图片会被转成 Base64 或交给images_upload_handler上传。对 CAD 粘贴过来的这种场景TinyMCE 拿到的图像如果不是 PNG浏览器会自动转码成 PNG最终插入的内容就是一张普通位图。这里有一个很容易误导人的点你在编辑区看到“一张图”并不代表它保留了矢量属性。很多系统里工程人员把贴进去的图无限放大看到边缘出现马赛克和锯齿第一反应是“TinyMCE 渲染能力不行”其实不是。TinyMCE 只是一个富文本编辑器它忠实地保存了你粘贴进来的位图问题在源头上。1.3 芯片制造企业为什么较真“矢量”这两个字普通的宣传页图文里贴一张截图像素低一点没人计较。但芯片制造企业的文档不一样CAD 图纸里往往包含设备坐标、管道走向、洁净室分区、防静电接地点位甚至还有版本号和会签栏。这些内容在评审、审计、打印 A0 蓝图时需要做到任意缩放不变形文字和线型要清晰。更重要的是后续可能还要从文档里提取某个区域的坐标或者拿图纸和现场的 BOM 做对照。保存成位图等于把这些信息全部拍扁成像素点失去了工程语义。所以但凡涉及“CAD 图纸 TinyMCE 矢量输出”正确目标不是让粘贴本身变智能而是定下来一套标准的转换和插入流程。核心就一句话要让矢量进编辑器就必须以 SVG 的形式进。2. 从 CAD 图纸到 SVG四条路线怎么选2.1 前提明确你要的矢量格式浏览器能把矢量内容嵌进 HTML 的实际上只有 SVG。DXF 是给 CAD 软件读的EMF/WMF 浏览器不认PDF 在 TinyMCE 里最多以附件形式存在不能作为内嵌渲染对象。所以无论用哪种方案最后必须得到一段 SVG 图纸数据。可以是完整的svg标签也可以是外部 SVG 文件之后通过后续处理替换成内联代码。这一点先想清楚后面的工具链就不会绕弯。别想着让 TinyMCE 直接支持 DXF 粘贴那在当前的浏览器体系里做不到。2.2 CAD 端直接导出能导则导如果企业用的 CAD 版本支持导出 SVG那肯定是最省事的一条路。不同的 CAD 产品差别很大有的国产 CAD 在“文件 - 另存为”里直接有 SVG 选项有的需要在打印驱动里选择 SVG 打印机有的则必须借助第三方插件。以中望 CAD 来说部分较新的版本能导出 SVG导出前建议先用“图层隔离”把无关图层关掉只保留要发布的图纸内容否则一次导出的 SVG 可能带着几十个空图层和重复视口文件非常大。对于 AutoCAD很多时候需要用SAVEAS先另存为 DXF再交给其他工具转换这样最稳妥兼容性最好。从实际项目经验看我不建议在“找到导出 SVG 的按钮”这件事上花太多时间。工程上常见的情况是从 AutoCAD、中望 CAD、浩辰 CAD 等不同工具收到的图纸混在一起版本五花八门统一走 DXF 交换格式后续用脚本批量处理投入产出比更高。2.3 DXF 转 SVG适合批量处理的自动化方案手头有一批 DXF需要反复转成 SVG并且要能保留图层、颜色、线型用 Python 的 ezdxf 库最靠谱。ezdxf 不仅能读取 DXF还能借助自带的 drawing addon 把模型空间画到 matplotlib 上然后存成 SVG。下面这段代码是我在一个厂务文档项目里实际用过的简化版import ezdxf from ezdxf.addons.drawing import RenderContext, Frontend from ezdxf.addons.drawing.matplotlib import MatplotlibBackend import matplotlib.pyplot as plt doc ezdxf.readfile(layout_20240510.dxf) msp doc.modelspace() fig plt.figure(figsize(16, 10)) ax fig.add_axes([0, 0, 1, 1]) ax.set_aspect(equal) ctx RenderContext(doc) backend MatplotlibBackend(ax) Frontend(ctx, backend).draw_layout(msp) fig.savefig(layout_20240510.svg, formatsvg) plt.close(fig)这段代码跑起来以后会在当前目录生成一个 SVG 文件。用浏览器打开放大到 300% 依然是一条直线不会出现锯齿。批量处理的时候把文件路径改成循环遍历即可像搜索词里提到的“python批量对cad修改”本质上就是先读 DXF再用脚本批量改属性、过滤图层、统一输出。用这个方案有个前提DXF 里的文字如果是 SHX 字体ezdxf 可能无法准确渲染因为 SHX 是 CAD 软件自定义的字形matplotlib 不认。这种情况下要么把 CAD 里的字体改成 TrueType 字体要么在 CAD 端把文字用TXTEXP炸成多段线再导出。2.4 千万别指望“粘贴后自动矢量化”也有同事问我能不能让 TinyMCE 在粘贴位图后自动转成矢量比如用 Potrace、OpenCV 之类的做矢量化。这个思路在美工图形上偶尔能用在工程图纸上就是灾难。CAD 图纸里大量的虚线、点划线、填充图案、尺寸标注、块参照一旦被位图化自动矢量化工具识别出来的是“看起来像”的一组曲线不是原来的线型和图层信息。坐标精度可能相差几个数量级。对一个以微米甚至纳米级精度说话的行业这种矢量化不仅没有价值还会在后续现场施工、设备定位时造成严重问题。所以我的结论很明确矢量必须从源头拿不能靠后期还原。CAD 图纸保留在 CAD 里TinyMCE 里放的是转换出来专门用于发布的 SVG。两边通过>tinymce.init({ selector: #editor, height: 600, plugins: paste code, extended_valid_elements: svg[*],defs[*],g[*],path[*],line[*],polyline[*],polygon[*], circle[*],ellipse[*],rect[*],text[*],tspan[*],use[*],symbol[*],marker[*], custom_elements: svg,defs,g,path,line,polyline,polygon,circle,ellipse,rect,text,tspan,use,symbol,marker, valid_children: body[svg], content_style: svg { max-width: 100%; height: auto; } });extended_valid_elements的关键是[*]表示允许这些标签携带任意属性因为 SVG 内部有大量类似fill、stroke、viewBox的属性如果不放开TinyMCE 会把它们全删掉。custom_elements让 TinyMCE 知道这些不是未知标签会正常参与内容序列化。如果你用的是 TinyMCE 4 或 5配置项名字一样但底层校验机制略有差异老版本里可能还需要加上verify_html: false。这个配置放在全局初始化里比在某个页面单独设置更保险否则前一页能显示 SVG后一页保存时又没了排查起来非常隐蔽。3.2 做一个“插入 CAD 矢量图”按钮配置允许 SVG 标签只是第一步更重要的是让操作者有一条稳定的导入路径。与其依赖工程师从 CAD 直接粘贴不如在 TinyMCE 工具栏上加一个“插入 CAD 矢量图”按钮让用户选择 SVG 文件插件读取内容后插入编辑器。这种做法的好处有三个第一工程师不需要理解 SVG 是什么只要把 CAD 导出的文件选进来就行第二可以在插入前做统一的安全过滤第三方便做数据来源标记比如把文件名或版本号写进>function readSvgFile(file) { return new Promise((resolve, reject) { const reader new FileReader(); reader.onload () resolve(reader.result); reader.onerror reject; reader.readAsText(file); }); } function sanitizeSvg(svgText) { const dom new DOMParser().parseFromString(svgText, image/svgxml); dom.querySelectorAll(script, foreignObject, object, embed).forEach(n n.remove()); dom.querySelectorAll(*).forEach(node { [...node.attributes].forEach(attr { const name attr.name.toLowerCase(); if (name.startsWith(on)) { node.removeAttribute(attr.name); } if ( (name href || name xlink:href) attr.value.trim().toLowerCase().startsWith(javascript:) ) { node.removeAttribute(attr.name); } }); }); return new XMLSerializer().serializeToString(dom); } tinymce.init({ // ...上面的配置 setup(editor) { let svgInput document.createElement(input); svgInput.type file; svgInput.accept .svg,image/svgxml; editor.ui.registry.addButton(insertCadSvg, { text: CAD SVG, onAction() { svgInput.onchange async () { const file svgInput.files[0]; if (!file) return; const raw await readSvgFile(file); const safeSvg sanitizeSvg(raw); editor.insertContent(safeSvg); svgInput.value ; }; svgInput.click(); } }); }, toolbar: insertCadSvg });这里必须强调一下安全过滤。SVG 本质是 XML理论上可以内嵌 JavaScript 事件比如svg onload...。如果直接把外部文件塞进 TinyMCE相当于往内容管理后端开了一个脚本注入的口子。在芯片制造企业的内网系统里即使网络环境相对封闭也不能忽略这个风险所以sanitizeSvg是必不可少的环节。3.3 大文件与安全过滤inline SVG 不是“无脑塞”有些 CAD 图纸很复杂转换出来的 SVG 能到几十 MB。这种文件直接内联进编辑器会导致页面卡顿保存时数据库压力也很大。我的建议是发布到 TinyMCE 的图纸先做“瘦身”把无关图层删掉用viewBox只保留需要展示的区域或者把一张大图拆成设备区、管道区、电气区几个视图分别插入。另外要注意viewBox属性。很多 CAD 转换工具生成的 SVG 只带width和height没有viewBox这种图在固定尺寸下没问题但一旦响应式缩放或者导出 PDF 时按不同纸张尺寸排版就容易变形。插入前最好检查一下如果缺少viewBox用程序补上。方式很简单取width和height的数值生成一个 0 0 width height 的viewBox保证图形在任意缩放下都按比例显示。4. 保存、回显、导出最后一公里别掉链子4.1 后端过滤器和数据库要注意什么很多系统把 TinyMCE 的 HTML 保存到后端之后还要经过一层 XSS 过滤器比如 OWASP Java HTML Sanitizer、Python 的 bleach 等。这类过滤器默认会删掉svg标签如果不在白名单里配置前端做得再完整保存到数据库时照样丢。所以改造不能只在前端做。后端过滤器的标签白名单里要显式加入svg、path、g、line、polyline、polygon、circle、rect、text、tspan、use、defs等属性白名单里要放开viewBox、fill、stroke、stroke-width、transform、d、points、x、y、width、height。如果公司有统一的富文本审核组件这个白名单应当和 TinyMCE 的配置保持一致不然就会出现“编辑界面正常回显页面空白”的诡异问题。存储的时候我习惯在 SVG 根节点上加一个>svg xmlnshttp://www.w3.org/2000/svg>chrome --headless --disable-gpu --print-to-pdfreview.pdf http://your-internal-review-page我在实际项目里会用 PDF 阅读器放大到 400%检查线条边缘是否光滑。如果边缘出现锯齿说明 SVG 在某个环节被转成了位图最常见的原因是导出页面里用了img srcxxx.svg而不是内联svg。img标签加载 SVG 时浏览器虽然能显示但打印输出往往是按位图处理的内联svg才是真正保留矢量信息的方式。如果后端的导出链路是 HTML 转 Word情况要复杂一些。Word 2016 及更早版本对内联 SVG 的支持很差很多 html-to-docx 转换库遇到svg直接忽略。解决方案是把 SVG 先转成 EMF 或者高清位图再插入 Word。但这就意味着 Word 输出天然会丢失一部分矢量特性。如果你的最终交付物必须支持老版 Word需要提前和业务方对齐是接受 PDF 作为矢量交付物还是接受 Word 里使用位图。4.3 文字变豆腐块/字体丢失的问题CAD 图纸里的尺寸标注和文字说明在转 SVG 时经常变成普通text元素。这样看起来没问题但换到一台没有安装对应字体的电脑上文字可能变成方块或者错位。芯片企业往往在不同站点有不同字体环境这个问题在跨部门评审时尤其明显。最稳妥的办法是把文字转成路径。在 CAD 里可以用 Express Tools 里的TXTEXP把文字炸开成线或者在 Inkscape 里打开 SVG 后选中文字执行“路径 - 对象转路径”再另存。这样文字就变成了纯矢量轮廓不受字体环境影响。代价是 SVG 文件变大文字内容不再可检索但对工程发布图来说保证显示准确比检索更重要。5. 一个真实改造案例设备平面图进入 TinyMCE5.1 从 DWG 到 DXF 的清理操作去年我们处理过一个厂务系统改造需求很简单工程师在 TinyMCE 里写设备安装说明要贴上净化车间的设备平面图并且这张图要能在后续的 PDF 评审里随意放大。最初的方案是让工程师在 CAD 里截图粘贴被工艺部门以“看不清楚”为由打回。后来我们定了上面说的路径。第一步让工程师在 CAD 里打开原始 DWG先执行图层隔离只保留“设备布局”这个图层然后用WBLOCK把当前可见内容写到一个临时 DWG再另存为 DXF 2013 格式。这样导出的文件里没有大量和发布无关的辅助线、视口线转换出来的 SVG 体积小很多。清理这一步不要省略。我看过有人直接拿整张 DWG 转换结果原始文件里的图框、标题栏、隐藏图层全部出现在 SVG 里版面很乱后期还得人工裁切。先清理再转换十分钟能省下后面两小时的返工。5.2 用 Python 批量转 SVG由于设备平面图每季度都会更新我们用脚本批量处理代码就是上面那段 ezdxf 的例子。在脚本里加上了图幅自适应读取模型空间的包围盒根据长宽比设置 SVG 的width、height和viewBox这样插入 TinyMCE 后无论编辑区多宽图都不会被拉伸变形。生成 SVG 后我会再用一段脚本做两件事第一去掉空的g分组第二检查有没有text元素如果有统一调用 Inkscape 把它转成路径。这里用命令行执行 Inkscape 也可以但如果是零散几份图直接用 GUI 操作更快。5.3 插入编辑器与最终 PDF 验证接着在 TinyMCE 里加上“插入 CAD 矢量图”按钮工程师上传 SVG插件做安全过滤后插入。保存到数据库后我们单独做了一个预览页面用 headless Chrome 打印 PDF。打开 PDF 后放大到 500%设备轮廓和管道线条依然清晰没有任何锯齿。这套流程上线后工程师不再关心“在 CAD 里复制时是不是要选基点”“粘贴出来颜色对不对”这些问题。他们只需要在 CAD 里导出 SVG然后上传到 TinyMCE 就行。文档里保存的是真正的矢量数据后续做自动比对、版本追溯也都能实现。6. 常见问题与排查速查表现象根本原因解决办法从 CAD 粘贴出来是图片放大模糊浏览器拿不到 EMF/WMF只得到位图不使用直接粘贴改为 CAD 导出 SVG 后插入SVG 插入 TinyMCE 保存后消失TinyMCE schema 过滤掉了 SVG在extended_valid_elements和custom_elements中放行 SVG 标签后端保存成功但回显页不显示 SVG后端 XSS 过滤器剔除了 SVG在后端白名单中允许svg及相关子标签和属性SVG 在编辑器和导出 PDF 中变形缺少viewBox或宽高比例不匹配补全viewBox按实际绘图区域设置转换后文字变成方块或问号CAD 使用 SHX 字体web 环境不认识在 CAD 中改 TrueType 字体或把文字转成路径大图纸插入后编辑器卡死SVG 文件太大节点过多清理图层、按viewBox裁切区域、拆分多个视图导出 Word 后 SVG 不显示html-to-docx 不支持内联 SVGWord 场景下先转 EMF 或高清位图或改用 PDF 交付排查这类问题我自己的经验是先看“保存到数据库之前的 HTML”再看“从数据库读出来的 HTML”。很多问题不是 TinyMCE 渲染造成的而是在入库或出库时数据已经变了。打开浏览器开发者工具在表单提交前把编辑器内容打印出来再用接口工具查一下数据库里的原始值基本就能定位问题在哪一层。最后再分享一个小技巧不要把所有希望寄托在 TinyMCE 插件上CAD 图纸的“矢量输出”本质上是个流程问题不是单纯的前端问题。谁导出 SVG、导出前怎么清理图层、SVG 版本和 DWG 版本如何对应、PDF 用哪条链路生成这些都要在制度里写清楚。工具能解决的是“能不能做”流程能解决的是“会不会稳定地做”。芯片制造企业最怕的恰恰是后一点。
返回列表