javascript - SVG 用类声明替换填充声明,用于高级颜色自定义

标签 javascript jquery html css svg

我正在处理一个包含许多 SVG 图稿的界面,这些图稿是在 Adob​​e Illustrator 中创建的。这些 SVG 的颜色可由用户自定义,所有艺术品最初都使用同一组颜色。这个想法是,一旦用户更改了每种颜色,它就会反射(reflect)在所有 SVG 图稿中。

现在,我可以正常使用此功能。我首先使用 LESS 在我的 CSS 中生成所有颜色阴影并将它们分配给类。

像这样

@color3-base: #FF0000;
@color3-shade1: mix(@color3-base, @color2-base, 90%);
@color3-shade2: mix(@color3-base, @color2-base, 80%);
@color3-shade3: mix(@color3-base, @color2-base, 70%);
@color3-shade4: mix(@color3-base, @color2-base, 60%);
@color3-shade5: mix(@color3-base, @color2-base, 50%);
@color3-shade6: mix(@color3-base, @color2-base, 40%);
@color3-shade7: mix(@color3-base, @color2-base, 30%);
@color3-shade8: mix(@color3-base, @color2-base, 20%);

还有这个

.color3-base-fill {fill: @color3-base;}
.color3-shade1-fill {fill: @color3-shade1;}
.color3-shade2-fill {fill: @color3-shade2;}
.color3-shade3-fill {fill: @color3-shade3;}
.color3-shade4-fill {fill: @color3-shade4;}
.color3-shade5-fill {fill: @color3-shade5;}
.color3-shade6-fill {fill: @color3-shade6;}
.color3-shade7-fill {fill: @color3-shade7;}
.color3-shade8-fill {fill: @color3-shade8;}

我使用 less.js 方法 less.modifyVars 来更新我的基色值,比如颜色 @color3-base。对每种颜色的任何更改都会导致在整个 SVG 作品中使用的这些颜色的所有不同阴影。所有颜色都完美生成,没有问题。

我使用 solution provided here以内联方式加载我所有的 SVG,这样它们就是我的 DOM 的一部分,并且可以从我的 LESS CSS 中发生的所有颜色阴影变化中产生影响。

现在,在这些加载的 SVG 中,我手动进入并将填充语句替换为类语句。像 fill="#FF0000"class="color3-base-fill" (或属于我正在替换的特定填充阴影的类)以便它检索来自类的填充值,并且总是会受到通过 LESS 发生的颜色变化的影响。因为我们所有的作品都使用相同的颜色集,并且现在将它们的填充语句手动替换为与这些颜色对应的类,所以效果很好。使用 less.modifyVars 对每种颜色的更改会清楚地反射(reflect)在所有艺术品的所有颜色上。

问题是我们有大量的 SVG 图稿文件,我必须用相应的着色类手动替换 SVG 中的每个填充语句。这为很多人为错误留下了余地,而这似乎应该是自动化的。

我最理想的是能够在加载 SVG 时自动进行这些替换。这将使我们在 Adob​​e Illustrator 中制作的任何艺术品在加载时立即可定制。我尝试了不同的方法来首先将我的 SVG 转换为字符串,以便我可以将填充声明替换为类声明,但我没有成功。似乎 SVG 既不是 XML 也不是 HTML,很难序列化它。目前我的知识有限,所以对解决上述问题的任何帮助都会很棒!

谢谢!

最佳答案

一种解决方案是使用 XSLT 样式表。您可以运行它以在提供服务之前预处理您的文件,将您的系统配置为在服务器端自动运行它,甚至可以在客户端运行它(取决于浏览器支持)。

SVG 是 100% XML,因此您可以使用 XSLT 对其进行处理。

假设您有一个像这样的 SVG:

<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
    <circle cx="300" cy="300" r="200" fill="#FF0000">
        <desc>Text</desc>
    </circle>
    <rect rx="10" ry="10" height="150" width="200" x="10" y="10" fill="#0000FF" />
</svg>

如果您使用下面的 XSLT 1.0 样式表将它加载到 XSL 处理器中,它将查找所有元素中的所有 fill 属性,比较其内容(我假设 #FF0000color3-base-fill#0000FFcolor4-base-fill),移除 fill属性并将其替换为相应的 class

<xsl:template match="node()|@*">
    <xsl:copy>
        <xsl:apply-templates select="node() | @*" />
    </xsl:copy>
</xsl:template>

<xsl:template match="*[@fill]">
    <xsl:choose>
        <xsl:when test=".[@fill='#FF0000']">
            <xsl:copy>
                <xsl:attribute name="class">
                    <xsl:text>color3-base-fill</xsl:text>
                </xsl:attribute>
                <xsl:apply-templates select="node()|@*[not(name() = 'fill')]"/>
            </xsl:copy>
        </xsl:when>
        <xsl:when test=".[@fill='#0000FF']">
            <xsl:copy>
                <xsl:attribute name="class">
                    <xsl:text>color4-base-fill</xsl:text>
                </xsl:attribute>
                <xsl:apply-templates select="node()|@*[not(name() = 'fill')]"/>
            </xsl:copy>
        </xsl:when>
        <xsl:otherwise>
            <xsl:copy>
                <xsl:apply-templates select="node()|@*" />
            </xsl:copy>
        </xsl:otherwise>
    </xsl:choose>

</xsl:template>

当然可以改进。您可以将颜色/类关系表放在一个单独的文件中,然后加载它,这样您就不必像我上面那样硬连接结果。

如果在服务器端服务或缓存之前编译样式表并进行转换,效率会高得多。这样您还可以使用功能更强大的 XSLT 2.0。但是如果你想在浏览器中加载它,你可以在 SVG 中包含这个处理指令,当你加载 SVG 时它会动态转换:

<?xml-stylesheet type="text/xsl" href="the-stylesheet.xsl"?>

这是由上面的样式表转换后的 SVG:

<svg xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink"
     width="100%" height="100%" version="1.1">
    <circle class="color3-base-fill" cx="300" cy="300" r="200">
        <desc>Text</desc>
    </circle>
    <rect class="color4-base-fill" rx="10" ry="10" height="150" width="200" x="10" y="10"/>
</svg>

关于javascript - SVG 用类声明替换填充声明,用于高级颜色自定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22213073/

相关文章:

javascript - 回调(假)和回调(真)有什么作用?

Javascript 避免嵌套 For 循环

javascript - Chrome/FF 中的对象处理?

javascript - jquery - 如何从列表中获取第 n 个子数值

php - 使用 PHP 的 DOMDocument 时避免百分比编码 href 属性

html - 如何自定义 tumblr 404 URL 未找到页面

javascript - jquery - 使用 href 按钮删除特定输入

javascript - 从静态方法 ES6 调用私有(private)方法

javascript - jQuery 序列化顺序似乎是随机的

jquery - 使用 jQuery 浏览文件系统并在跨度中显示图像