Inkscape 脚本:如何显示/隐藏图层和导出?

平面设计 墨景 层数
2022-01-05 20:59:22

我有一个多层的卡通;在这些层中,我有一个德语层和一个英语层。他们有各自语言的文本。这个想法是隐藏德语层并显示英语层并导出为英语卡通片,或者隐藏英语层并显示德语层以用于德语版卡通片。我想编写该导出的脚本。

这是我的 SVG 文件的一部分:

  <g
     inkscape:groupmode="layer"
     id="layer3"
     inkscape:label="English"
     style="display:inline">
     <text
         xml:space="preserve"  
         <!-- .... --> 
         id="text3255">
         <tspan id="tspan3257">I don't think</tspan>
         <!-- ... -->

 <g
     inkscape:groupmode="layer"
     id="layer4"
     inkscape:label="German"
     style="display:none"> 
     <text
           xml:space="preserve"
           <!-- ... -->
           id="text3284">   
           <tspan id="tspan3286">Ich glaube nicht,</tspan> 
           <!-- ... -->

我看过https://stackoverflow.com/questions/9652573/inkscape-command-line-programming并尝试了这个命令(以及很多变体):

inkscape -z --file=cartoon.svg --select=English --verb=LayerHideAll --select=German --verb=LayerShowAll --export-png=cartoon-de.png --export-area-drawing

但我不断收到英文文本,可能是因为当我保存文件时,英文图层可见而德文图层不可见。

我还尝试通过 ID 选择图层(分别在 layer3 和 layer4 上面的代码中),并选择实际<text>元素;我尝试过 Inkscape 动词的各种组合。但也没有运气。

如何根据需要编写此导出、隐藏或显示语言层的脚本?我可以使用 Inkscape 动词执行此操作,还是应该使用 XML 并尝试将样式属性设置为 display:inline 或 display:none?

4个回答

至于为什么命令行测试不起作用,我相信答案是您首先需要在图层中选择一个项目(而不是图层本身)才能“在”图层中。之后,正确的动词应该是LayerToggleHide(当问这个问题时,不确定这个动词是否可用。)而且,是的,对象只能通过 ID 选择,而不是名称。

此外,因为没有 LayerHide 和 LayerShow 动词(为什么?),要可靠地编写脚本,您首先需要使用LayerHideAllLayerShowAll以一种或另一种方式设置所有层,然后再使用LayerToggleHide以实现最终结果。

我还没有测试过这个命令行路径,所以我无法展示一个明确的工作解决方案。相反,在仔细考虑了命令行路线并意识到需要编写多少脚本才能使其满足我的需求后,我决定全力以赴并编写一个处理此类需求的 Inskape 扩展。我称它为 SLiCk 层组合器,它可以在这里找到:https ://github.com/juanitogan/slick

好的,我搞砸了各种 XML 解析模块,最终得到了以下 Perl 代码。

use XML::LibXML;
use XML::LibXML::XPathContext;

my $file = "file/to/open.svg";

my $xml = XML::LibXML->load_xml(location => $file);
my $xpath = XML::LibXML::XPathContext->new($xml);  
$xpath->registerNs("defNs", 'http://www.w3.org/2000/svg');
foreach my $layer ($xpath->findnodes('/defNs:svg/defNs:g[@inkscape:groupmode="layer"]')) {
    my $label = $layer->{'inkscape:label'};
    foreach my $otherLang (@languages) {
        if ($label =~ m/$other_lang$/) {
            $layer->{'style'} =~ s{\bdisplay:inline\b}{display:none};
        }
    }
    if ($layerLang eq $lang) {
        $layer->{'style'} =~ s{\bdisplay:none\b}{display:inline};
    }
}
$xml->toFile($tempFileName);

这解决了我的问题。希望它对其他人也有用。

我知道这有点晚了,但我发现了这个hide-latyer-svg Github 项目,它使用 python 脚本创建新文件,根据您在图层控制杆上创建的 xml 节点显示和隐藏某些图层。

最好的,克里斯托夫

给定一个具有多个层的文件,其中有趣的层具有 ids:layer0layer1. 可以使用 inkscape 操作单独或一起导出图层,如下所示:

# Export layer0 alone into first.png
inkscape 'file.svg' \
    --actions 'select-all:layers; object-set-attribute:style, display:none;
        select-clear;
        select-by-id:layer0; object-set-attribute:style, display:inline' \
    --export-filename='first.png' --export-type='png'

# Export layer1 alone into second.png
inkscape 'file.svg' \
    --actions 'select-all:layers; object-set-attribute:style, display:none;
        select-clear;
        select-by-id:layer1; object-set-attribute:style, display:inline' \
    --export-filename='second.png' --export-type='png'

# Export layer0 and layer1 into both.png
inkscape 'file.svg' \
    --actions 'select-all:layers; object-set-attribute:style, display:none;
        select-clear;
        select-by-id:layer0,layer1; object-set-attribute:style, display:inline' \
    --export-filename='both.png' --export-type='png'

阅读这个inkscape 论坛帖子是弄清楚如何使用这个文档稀少的功能的关键。