我正在开发一个包含许多在Adobe Illustrator中创建的SVG艺术品的界面。这些SVG的颜色可由用户定制,并且所有艺术品最初使用相同的颜色集。这个想法是,一旦用户改变了每种颜色,它就会反映在所有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中,我手动进入并用class语句替换了fill语句。就像带有fill="#FF0000"
的{{1}}(或属于我正在替换的特定填充阴影的类)一样,它从类中检索填充值,并且始终可以通过LESS发生的颜色变化产生影响。因为我们所有的艺术品都使用相同的颜色,现在他们的填充语句被手动替换为与这些颜色相对应的类,这非常有用。使用class="color3-base-fill"
对每种颜色进行更改会清晰地反映所有艺术品的所有颜色。
问题是我们有大量的SVG图片文件,我必须用相应的阴影类手动替换SVG中的每一个fill语句。这会为很多人为错误打开保证金,这似乎应该是自动化的。
我最理想的是能够在加载SVG时自动进行这些替换。这将使我们在Adobe Illustrator中制作的任何艺术作品在加载时立即可自定义。我尝试了不同的东西,首先将我的SVG转换为字符串,以便我可以将fill声明替换为类声明,但我还没有成功。看起来SVG既不是XML,也不是HTML,很难将其序列化。我的知识在这一点上是有限的,所以解决上述问题的任何帮助都会很棒!
谢谢!
答案 0 :(得分:1)
一种解决方案是使用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
属性,比较其内容(我假设#FF0000
为{{1} }和color3-base-fill
作为#0000FF
),删除color4-base-fill
属性并将其替换为相应的fill
。
class
当然可以改进。您可以将您的颜色/类关系表放在一个单独的文件中,然后加载它,这样您就不必像上面那样硬连接结果。
如果编译样式表并在服务器端提供服务或缓存之前进行转换,效率会更高。这样你也可以使用更强大的XSLT 2.0。但是如果你想在浏览器中加载它,你可以在SVG中包含这个处理指令,当你加载SVG时它将被动态转换:
<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>
这是由上面的样式表转换的SVG:
<?xml-stylesheet type="text/xsl" href="the-stylesheet.xsl"?>
答案 1 :(得分:1)
我设法解决了这个问题,首先将我的所有SVG加载到我的DOM中,然后简单地使用jQuery删除填充属性并用正确的相应类属性替换它们。
function applyClassesOverSVGColors(svg, classGroupName, colors){
for (var i in colors) {
//Customize Fills
$("#" + svg.attr("id") + ' [fill="#'+ colors[i] +'"]').each(function(){$(this).removeAttr('fill').addClass($(this).attr("class")+" "+classGroupName+"-fill")});
//Customize Strokes
$("#" + svg.attr("id") + ' [stroke="#'+ colors[i] +'"]').each(function(){$(this).removeAttr('stroke').addClass($(this).attr("class")+" "+classGroupName+"-stroke")});
};
}
上面,colors
包含需要使用类而不是内联填充或描边声明来表示的所有颜色。
applyClassesOverSVGColors(svg,"color1-base",["50B380","4FB280","4DB180"]);