【问题标题】:Styling the same SVG <object> different ways以不同的方式为相同的 SVG <object> 设置样式
【发布时间】:2016-04-26 10:15:50
【问题描述】:

我想在一个页面上使用不同颜色的一系列相同的 SVG 文件。我知道在不使代码臃肿的情况下将 SVG 放入页面并且仍然具有外部样式的最佳方法是通过 &lt;object&gt; 标记。

这是我目前所拥有的:

HTML

<object type="image/svg+xml" data="images/circle.svg" class="object-circle red" >
    <!-- fallback image in CSS -->
</object>

<object type="image/svg+xml" data="images/circle.svg" class="object-circle blue" >
    <!-- fallback image in CSS -->
</object>

CSS

.object-circle {
    height:16px;
    width:16px;
}

.red .svg-circle {
    fill:#f00;
}
.blue .svg-circle {
    fill:#00f;
}

SVG

<?xml-stylesheet type="text/css" href="styles.css" ?>
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400" viewBox="0 0 400 400">
  <defs>
    <style>
      .svg-circle {
        fill-rule: evenodd;
      }
    </style>
  </defs>
  <path class="svg-circle" d="M200,398.688A199.552,199. ..."/>
</svg>

这只是不工作。我认为以&lt;object&gt; 标记为目标来操纵CSS 中SVG 的fill 属性存在问题。

.red 选择器从样式表中移除,并将.svg-circle 选择器留在原处按预期工作 - 将圆圈变为红色,但我希望能够在页面上使用不同颜色的多个选择器。

非常感谢任何帮助!

如果我无法破解这个问题,我可能会求助于老式的 .png 精灵表。

【问题讨论】:

    标签: html css image svg


    【解决方案1】:
    
    document.addEventListener("DOMContentLoaded", function() {
      //attribute name
      const ATTR_NAME = "data-src";
      //base64 encoded brocken image icon
      const ERROR_PLACEHOLDER =
        "<img src='data:image/gif;base64,R0lGODlhEQATAPcAAFKyOVGxOlOxPFSyPFSzPFSyPVSyPlWyPlWyP16kTViyRFmzRVm0RV+1T2GlUGKmUWG2U2K0VGO2V2e6UmW3Wm27X3C/XWyrYHKsaXW7ZHqwbHe7dnTAYnfBcH3EcISGhIWGhIWGhYeFh4aGhoeGh4aIhY6NjpORlJOSlJSSlJSSlZWTlZiYl5qYmpuZm5ubnp6cn5+dn4SqgIqqi56eoaGfoaGhoaKho6Kio6Oio6OhpKKipKShpKSjpKSipaSjpaajpqSlqqilqKmoqaysrL+/v4TEhY/DnpLEpJTEp5vLqaXGsaDJta3FvaXKvafKv7zhs8HjuMHjucfmv8bnv6jLwrDNz7zbyrXP17bO27jP3b3V373R5MfHyMnIycrJy8rKys3MzcTL38LP3MfO3cvR3tTW09DQ1NXV19TU2dDU39jY2dra29nd2N3d397e38rlx9jr2sfQ4cjQ4czT4crT58/X58HT6cLT6sTU6MPR7cPT7MPT7cTT78vV6dba49Tc7MXT8MXT8cbU8cbU8sfU8sbV8sfV8sfU88jW8snX88rY88vY88zZ8svY9MzZ9Mza9M3a9c3b9c7b9c3b9s7b9s/c9tDc8tPe9dPf9tDd+NHe+NPf+NLf+dvg6tvi8dXh+Nbi+Nbi+dfi+djj+drk+eDg4OHg4OHh5+Xl5uLi6Orq6uzs7OTn8eXp8ers9OHq++Tr+uXs+Obs++ft++fu++Tr/OTs/OXs/Ofu/enu+eju++jv++jv/enw/O3y/fT09Pb79PP3//r6+vr6+/v9+/r7/Pn7/vv8/vz8/Pz8/f3//P7//fz9/v79//3+//7+//7//////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAAAAAAALAAAAAARABMAAAj+AGsAEUKwIEEeLdwQk8YwxxlVqCJKVJXGBZE3yhr+6YULly1bt3Dl8gTDS5c1GXHQIcVpVC1epVraobHKFBg2xnDI6cQp1jNpu0BtqvMizKkiQ9DoFDUrGkNptDT5CaLjh48YKXT6Ooasa7NYjy59auXqVZoVOkFlWrt2kiNLoUqVgqVmxQ45lQwZOsT3UCJFixgx4kTmxF1KgxIPIsRY8SBJgL7clZSYECI+d/YUIjRIEKZf0u5GGtSHixUnTJ5gwROokSyGdyHp0ZIkggIGDTZUyaMLWjJgsbMggYBgQIEDCyrEcSYtVQ8cc7YckXCggAEDAiZMCSZNWBkUN8ZKKKEw4LqBABakFJMG54oYFTaWdABAoH4ADlCkLaPiwUgTFCzIcIEDBD6QQRTSDNOGBglgMIMJIowQwgcUlmAGM9KwksKEIZAgQkAAOw==' >";
      let target = document.querySelectorAll(`[${ATTR_NAME}]`);
      //unsorted list
      let _filesList = [];
      target.forEach(function(item) {
        _filesList.push(item.getAttribute(ATTR_NAME).replace(/\\/g, "/"));
      });
      //sorted list
      let filesList = _filesList.filter(function(item, pos) {
        return _filesList.indexOf(item) == pos;
      });
      //ajax request
      filesList.forEach(function(item) {
        let ajax = new XMLHttpRequest();
        ajax.open("GET", item, true);
    
        ajax.onload = function() {
          document.querySelectorAll(`[${ATTR_NAME}="${item}"]`).forEach(item => {
            if (this.status >= 200 && this.status < 400) {
              // Success!
              item.innerHTML = this.response;
            } else {
              // Error!
              item.innerHTML = ERROR_PLACEHOLDER;
            }
          });
        };
    
        ajax.send();
      });
    });
    
    <div class="icon" data-src="icon.svg">
    
    .icon path{
      fill:#000;
    }
    

    【讨论】:

      【解决方案2】:

      我也陷入了同样的困境,但我意识到按照当前的规范这是不可能的,因为 SVG 文档存在于它们自己的 DOM 中,与主文档分开,类似于 iframe(参见 this answer)。但是,这并不意味着我们暂时无法绕过这个限制。

      由于 SVG 文件是纯文本文件,我想为什么不直接使用 JavaScript 渲染它(因为问题没有明确说明不能使用 JS)。以上面的 SVG 圆圈为例,函数如下所示:

      // Render an SVG circle
      // optional oStyles = { selector: style [, ...] }
      function renderCircle(oStyles) {
        var sId = ('svg-'+performance.now()).replace('.', ''),
          sCss = '',
          sSel;
        if (!oStyles) oStyles = {};
        for (var i in oStyles) {
          // Handle group of selectors
          sSel = '';
          i.split(/ *, */).forEach(function(s) {
            sSel += '#' + sId + ' ' + s + ',';
          });
          sSel = sSel.slice(0, -1);
          sCss += sSel + '{' + oStyles[i] + '}';
        }
        return '' +
          '<svg xmlns="http://www.w3.org/2000/svg" id="' + sId + '" width="40" height="40" viewBox="0 0 40 40">' +
            '<style type="text/css">' +
            '<![CDATA[' +
            // Default styles
            '#' + sId + ' .svg-circle { fill: red; }' +
            // Overrides
            sCss +
            ']]>' +
            '</style>' +
            '<circle class="svg-circle" r="20" cx="20" cy="20"/>' +
          '</svg>';
      }
      
      document.getElementById('canvas').innerHTML = renderCircle();
      document.getElementById('canvas').innerHTML += renderCircle({'.svg-circle':'fill:blue'});
      &lt;div id="canvas"&gt;&lt;/div&gt;

      这适用于像徽标这样的一次性图像,但如果您有一堆 SVG 图标,那么您应该考虑使用 SVG 图标字体或 SVG 精灵。这里有一个很好的指南,用于在 Web 上实现 SVG:

      https://svgontheweb.com/

      【讨论】:

        【解决方案3】:

        正如 CBroe 所说,外部对象的样式存在问题。您可以通过 JS 访问它并对其进行更改,但我怀疑那是理想的,并且存在确保其首先加载等问题。

        但是,我不相信这一定是您所说的最好的方法,除非有一些其他要求(例如,没有 javascript 或库并且它必须是外部的,您仍然可以通过 Snap 加载方法加载它,例如那么如果你支持js)。

        您可以简单地使用 defs/use 语句。为了简洁起见,我只是使用了一个圆圈,但你可以有一个更复杂的路径或其中的任何内容。

        jsfiddle

        <svg xmlns="http://www.w3.org/2000/svg" width="400" height="400" viewBox="0 0 400 400">
          <defs>
            <style>
              .svg-circle {
                fill-rule: evenodd;
                fill: 'red';
              }
            </style>
            <circle id="myDefsCircle" class="svg-circle" r="20" cx="100" cy="100"/>
          </defs>
        
           <use x="10" y="0"   xlink:href="#myDefsCircle" style="fill:red"/>
           <use x="10" y="50"  xlink:href="#myDefsCircle" style="fill:blue"/>
           <use x="10" y="100" xlink:href="#myDefsCircle" style="fill:green"/>
        </svg>
        

        【讨论】:

          【解决方案4】:

          参见https://css-tricks.com/using-svg/,“使用 SVG 作为&lt;object&gt;”部分:

          [...] 如果你想让 CSS 工作,你不能在文档上使用外部样式表或 &lt;style&gt;,你需要在 SVG 文件本身中使用 &lt;style&gt; 元素。

          因此,似乎无法通过 CSS 从对象“外部”设置 object 内部的 SVG 元素样式。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2023-03-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2021-03-07
            相关资源
            最近更新 更多