首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >svg样式相互干扰

svg样式相互干扰
EN

Stack Overflow用户
提问于 2017-09-15 08:21:48
回答 2查看 3K关注 0票数 8

我有一堆徽标,生成与插画,我想嵌入到我的网站直接。svgs都有一个<style>元素,其中样式是在svg元素中定义的,如下所示:

代码语言:javascript
运行
复制
<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,这似乎不起作用。

如何确保内联SVG样式不相互干扰,而不触及实际的SVG代码?

这里有一支笔来说明这个问题:https://codepen.io/pwkip/pen/RLPgpW

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-09-15 09:12:17

我想出了一个JavaScript解决方案。尽管如果您使用大量的SVG,这可能会有些过分和缓慢。但到目前为止效果还不错。

我所做的是,遍历所有SVG并收集/解析它们的CSS样式。我收集所有的类名和属性,并手动将它们应用到SVG元素上。

代码语言:javascript
运行
复制
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 );
  }
}
代码语言:javascript
运行
复制
<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>

尽管这样做很好,但我不会建议它(正如在您的问题上的评论中提到的)。最好在插图中将CSS Properties设置为Presentation Attributes

票数 0
EN

Stack Overflow用户

发布于 2017-09-16 10:46:23

我建议首先导出具有适当CSS属性的svg。在从Illustrator导出的过程中,请选择:style attributes,在svg中如下所示:

<path style="fill: red"></path>

它可以增加您的文件大小,但它肯定可以完成这项工作。我找到了一个很好的解释这里

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46234957

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档