如何在不丢失类和属性的情况下进行SVG的可视化编辑?

9

TL;DR

编辑SVG文件时,若在Illustrator中进行编辑,会导致原始元素类丢失。如何以安全的方式对SVG文件进行可视化编辑? 简要背景:笔者被一个基于单个SVG文件的小型GIS想法所吸引。这是一张互动热力图,标记着我家乡的建筑价值的颜色编码及一些在Google地图API中不可用的视觉效果。因此,我已经成功地:使用OpenStreetMap将墨卡托投影的街道地图转换为带有地理参考坐标的SVG;将建筑多边形与地址、楼层数和建造年份联系起来;实现了令人满意的缩放和滚动性能(感谢D3.js)。 我如何想象使用SVG。两个有时交替出现的任务:
  1. 在Adobe Illustrator中进行可视几何校正:纠正拓扑错误,将多边形转换为复合形状(带有庭院的建筑),等等。
  2. 在Chrome控制台中使用JavaScript和CSS进行数据可视化工作。向多边形添加多个类或数据属性,负责其可视化呈现。使用样式表中的不同选择器和规则,我可以根据建筑风格、高度和建造时间段等因素,创建出一定大小、亮度和色调的多边形周围的发光效果:<polygon class="bld bld-type-public bld-age-soviet bld-style-constructivism" data-storeys="4" data-year="1927" id="b5270" points="2427,788 2435,786 2436,790 2433,791 2428,792"></polygon>

这个过程是漫长而迭代的。矢量图像需要周期性地进行编辑,同时还需基于收集到的数据进行DOM操作。

面对现实。Adobe Illustrator作为一个强大的编辑复杂矢量图像的工具,将SVG文件的DOM转换为其自己的对象模型。但它没有完全做到这一点。在我的方法中,在Illustrator中编辑后有些数据会永久丢失。
数据 在 Adobe Illustrator 中编辑后的结果
点坐标 ✅ 保存为源 SVG 中的格式
元素分组 (<g>) ✅ 保存(可在“图层”面板中查看)
IDs ✅ 保存为对象名称,可在“图层”面板中查看
CSS 类名 ❌ 丢失(类列表被替换为单个类名,如 st0、st1... 或 a、b、c...)
任意(data-)属性 ❌ 丢失

该怎么办?

所有实验都是在 Adobe Illustrator CC 2019 上进行的。最新更新无法安装在我的 macOS Mojave 上。我认为 SVG 引擎中没有更新任何东西(或者我错了吗?)

  • 有没有什么方法可以为这种项目设置矢量编辑器?
  • 是否有(突然出现的)秘密方式来扩展 Chrome DevTools 的功能,以实现在浏览器中进行可视化 SVG 编辑?

当然,每次在 Illustrator 中进行编辑后,总是可以选择后处理。使用 ID,我可以从外部数据数组(JSON)中恢复类名和/或属性列表。但我真的不想让这个过程变得更加复杂,因为它已经有点奇怪了。

Minimum test SVG code:

<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 640 200" xml:space="preserve">
    <style type="text/css">
        .test {fill:red;}
        .test.blue {fill:blue;}
    </style>
    <g>
        <rect id="item1" data-test="1" x="190" y="20" class="test" width="120" height="120"/>
        <rect id="item2" data-test="1" x="322" y="20" class="test blue" width="120" height="120"/>
    </g>
</svg>

这是在Illustrator中保存的结果(合并/重命名类,删除属性):

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     viewBox="0 0 640 200" style="enable-background:new 0 0 640 200;" xml:space="preserve">
<style type="text/css">
    .st0{fill:#FF0000;}
    .st1{fill:#0000FF;}
</style>
<g>
    <rect id="item1" x="190" y="20" class="st0" width="120" height="120"/>
    <rect id="item2" x="322" y="20" class="st1" width="120" height="120"/>
</g>
</svg>

感谢 SO 社区提供的任何帮助和提示!


3
作为一个猜测,Inkscape(https://inkscape.org)能够做到吗?毕竟SVG是Inkscape的本地格式。不幸的是,在macOS上它的表现并不是很好,但在一定程度上可以使用。 - Yuri Khristich
2
即使这个问题不符合正式规则,我认为将此规则应用于这个特定的问题是不明智的。如果不是在这里,那么应该在哪里提出这样的问题呢?而且作者展示了大量的研究努力。我投票支持开放这个问题。 - Yuri Khristich
2
@YuriKhristich非常感谢您对这个问题的支持。Linkscape确实是一个很棒的编辑器,但与Illustrator相比,在我的Mac上运行速度非常慢。我想这就是完全SVG兼容性的代价。特别是当文件大小超过5 MB时。 - Alexey Vladimirov
1
你尝试过这个解决方案吗?它不能解决数据属性的剥离,但希望能保留类名。 - Felipe Saldanha
1
我认为明智的做法是将您的数据链接到位于SVG多边形内部的点。然后,您可以拥有一个本地过程,其中输入是基本SVG和坐标点+数据列表。输出是扩展的SVG。您可以使用此函数:https://dev59.com/fXrZa4cB1Zd3GeqP5KdW#59718419 - vals
显示剩余5条评论
1个回答

2
我强烈推荐使用Boxy SVG作为SVG的可视化编辑器。它不使用单独的对象模型,而是100%基于SVG。我不知道它是否会保留您所有的手动编辑,但我认为它比Illustrator更接近。以下是在Boxy SVG中保存您的最小SVG测试代码的结果:
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 640 200" xml:space="preserve">
    <style type="text/css">
        .test {fill:red;}
        .test.blue {fill:blue;}
    </style>
    <g>
        <rect id="item1" data-test="1" x="190" y="20" class="test" width="120" height="120"/>
        <rect id="item2" data-test="1" x="322" y="20" class="test blue" width="120" height="120"/>
    </g>
</svg>

如您所见,代码完全相同,因此加载到 Box SVG 中并进行“另存为”操作并没有破坏任何内容。据我所知,Boxy SVG 不会触及您的样式块或类属性 - 实际上,它甚至不提供编辑它们的方法,只是让它们保持原样。
在 Box SVG 中对填充或描边颜色所做的任何更改都将作为样式属性添加到对象中,并且当然会覆盖由类分配的任何样式。以下是在 Boxy SVG 中定义了几个命名颜色并将其分配给您的两个对象的结果。如您所见,这些命名颜色在 块中定义,并使用样式属性分配,因此它们会覆盖类分配的颜色,但您的类属性和样式块本身保持不变。
<?xml version="1.0" encoding="utf-8"?>
<svg version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 640 200" xmlns="http://www.w3.org/2000/svg" xmlns:bx="https://boxy-svg.com">
  <defs>
    <linearGradient id="color-0" bx:pinned="true">
      <title>greyish green</title>
      <stop style="stop-color: rgb(115, 169, 111);"/>
    </linearGradient>
    <linearGradient id="color-1" bx:pinned="true">
      <title>pinkish</title>
      <stop style="stop-color: rgb(214, 98, 187);"/>
    </linearGradient>
  </defs>
  <style type="text/css">
        .test {fill:red;}
        .test.blue {fill:blue;}
    </style>
  <g>
    <rect id="item1" data-test="1" x="190" y="20" class="test" width="120" height="120" style="fill: url(#color-0);"/>
    <rect id="item2" data-test="1" x="322" y="20" class="test blue" width="120" height="120" style="fill: url(#color-1);"/>
  </g>
</svg>

请注意,Boxy SVG 现在对您的 SVG 根元素的属性进行了一些微小的更改;这些更改可能或可能不会影响您想要做的事情。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接