我有一堆徽标,由插画家生成,我想直接嵌入我的网站。 svgs都有一个<style>
元素,其中样式在svg元素中定义,如下所示:
<svg>
<style>
.st1 { fill:#ff00ff; }
.st2 { fill:#ff3421; }
/* ... and so on */
</style>
<!-- svg paths and shapes -->
</svg>
问题在于这些风格相互干扰。因此,如果最后的图像定义.st21 {fill:#555555}
,则此样式将应用于class="st21"
的所有路径,包括来自所有先前加载的svg图像的路径。
在另一个帖子中,有人建议用<object>
标签包装我的svg-xml,这似乎不起作用。
如何在不触及实际SVG代码的情况下确保内联SVG样式不会相互干扰?
这是用来说明问题的笔:https://codepen.io/pwkip/pen/RLPgpW
答案 0 :(得分:1)
我建议首先使用适当的CSS属性导出svg。
从Illustrator导出期间,选择:style attributes
在svg:
<path style="fill: red"></path>
它可能会增加您的文件大小,但它绝对可以胜任。我找到了一个很好的解释here
答案 1 :(得分:0)
我想出了一个JavaScript解决方案。虽然如果使用大量SVG,这可能有点过分和缓慢。但到目前为止,这种方法很好。
我所做的是,我遍历所有SVG并收集/解析他们的CSS样式。我收集所有类名和属性,并将它们手动应用到SVG元素上。
const svgCollection = document.querySelectorAll( 'svg' );
function parseStyles( styleTag ) {
if ( !styleTag ) {
return {};
}
const classCollection = {};
const plain = styleTag.innerHTML;
const regex = /\.([^\s{]+)[\s]*\{([\s\S]+?)\}/;
const propertyRegex = /([\w\-]+)[\s]*:[\s]*([^;]+)/;
const result = plain.match( new RegExp( regex, 'g' ) );
if ( result ) {
result.forEach( c => {
const classResult = c.match( regex );
const propertiesResult = classResult[ 2 ].match( new RegExp( propertyRegex, 'g' ) );
const properties = propertiesResult.reduce( ( collection, item ) => {
const p = item.match( propertyRegex );
collection[ p[ 1 ] ] = p[ 2 ];
return collection;
}, {} );
classCollection[ classResult[ 1 ] ] = properties;
} );
return classCollection;
}
return {};
}
function applyProperties( element, properties ) {
if ( !properties ) {
return;
}
Object.keys( properties ).forEach( key => {
element.style[ key ] = properties[ key ];
} );
}
function applyStyles( element, styles ) {
const classNames = ( element.getAttribute( 'class' ) || '' ).split( ' ' );
classNames.forEach( c => {
applyProperties( element, styles[ c ] );
} );
element.setAttribute( 'class', '' );
}
for ( let i = 0; i < svgCollection.length; i += 1 ) {
const svg = svgCollection[ i ];
const styles = parseStyles( svg.querySelector( 'style' ) );
const elements = svg.querySelectorAll( '[class]' );
for ( let j = 0; j < elements.length; j += 1 ) {
applyStyles( elements[ j ], styles );
}
}
<p>this shape should be blue:</p>
<svg height="210" width="210">
<style>
.st1 {
fill:blue;
}
</style>
<polygon points="100,10 40,198 190,78 10,78 160,198" class="st1"/>
</svg>
<p>this shape should be red:</p>
<svg height="210" width="210">
<style>
.st1 {
fill:red;
}
</style>
<ellipse cx="105" cy="80" rx="100" ry="50" class="st1" />
</svg>
尽管这很有用,但我不建议(如你问题的评论所述)。最好在Illustrater中将CSS Properties
设置为Presentation Attributes