【问题标题】:Canvg not supporting cssCanvg不支持CSS
【发布时间】:2016-03-11 07:33:40
【问题描述】:

我有从服务器动态加载的内联 svg。我希望使用内联 css 对 svg 进行操作或修改。我已经搜索了将修改后的 svg 转换为 png 或 base64 图像。经过长时间的搜索,我决定坚持使用 Canvg。

现在的问题是它渲染了内联样式属性,如背景和边框半径。

这是我的 svg。

<svg height="550" width="550" viewBox="0 0 512 512" id="svg">
<path d="m309 139c0-111-32-139-53-139-21 0-53 28-53 139l-173 122c-2 1-4 4-4 7l0 46c0 6 5 10 11 9l166-37c6 49 16 93 23 139l-63 49c-2 1-4 4-4 6l0 23c0 7 6 11 12 8l85-38 85 38c6 3 12-1 12-8l0-23c0-2-2-5-4-6l-63-49c7-46 17-90 23-139l166 37c6 1 11-3 11-9l0-46c0-3-2-6-4-7z m-53-88c-11 0-21 3-30 7 3-13 15-22 30-22 15 0 27 9 30 22-9-4-19-7-30-7z"></path>
</svg>

看起来像这样:

记住路径是从服务器动态加载的。所以不能修改。

现在我想像这样操作它。

<svg style="background: grey none repeat scroll 0% 0%; fill: white; padding: 70px; border-radius: 98px;" height="550" width="550" viewBox="0 0 512 512" id="svg">
      <path d="m309 139c0-111-32-139-53-139-21 0-53 28-53 139l-173 122c-2 1-4 4-4 7l0 46c0 6 5 10 11 9l166-37c6 49 16 93 23 139l-63 49c-2 1-4 4-4 6l0 23c0 7 6 11 12 8l85-38 85 38c6 3 12-1 12-8l0-23c0-2-2-5-4-6l-63-49c7-46 17-90 23-139l166 37c6 1 11-3 11-9l0-46c0-3-2-6-4-7z m-53-88c-11 0-21 3-30 7 3-13 15-22 30-22 15 0 27 9 30 22-9-4-19-7-30-7z"></path>      </svg>

看起来像这样:

但是在使用canvg脚本渲染之后。它呈现为原始文件。它只包括填充颜色。没有其他的。

有没有其他方法可以做到这一点。使用画布或 svg 元素。

请帮忙!!!提前致谢

【问题讨论】:

  • 使用 DOM 修改即可

标签: javascript css canvas svg canvg


【解决方案1】:

您可以使用 Javascript 和 DOM 来修改当前页面中的任何元素;无论它是服务器生成文件还是其他任何东西。 http://www.i-programmer.info/programming/graphics-and-imaging/3254-svg-javascript-and-the-dom.html

【讨论】:

    【解决方案2】:

    大多数 svg 到画布库不支持外部资源(xlink 属性、图像和 CSS)。

    我发现的唯一方法是将这些外部资源附加到 svg 节点中,然后使用 canvas.toDataURL() 方法将您的 svg 绘制到画布上。

    我正在写一个 small script 来处理这个问题,这里是我制作的 CSS 解析器的转储,它将遍历所有文档的样式表,并且只附加那些对内部元素有影响的样式表。

    var parseStyles = function() {
        var styleSheets = [],
            i;
        // get the stylesheets of the document (ownerDocument in case svg is in <iframe> or <object>)
        var docStyles = svg.ownerDocument.styleSheets;
        // transform the live StyleSheetList to an array to avoid endless loop
        for (i = 0; i < docStyles.length; i++) {
            styleSheets.push(docStyles[i]);
        }
        if (styleSheets.length) {
            // getDef() will return an svg <defs> element if already into the node, or will create it otherwise
            getDef();
            svg.matches = svg.matches || svg.webkitMatchesSelector || svg.mozMatchesSelector || svg.msMatchesSelector || svg.oMatchesSelector;
        }
    
        // iterate through all document's stylesheets
        for (i = 0; i < styleSheets.length; i++) {
            // create a new style element
            var style = document.createElement('style');
            // some stylesheets can't be accessed and will throw a security error
            try {
                var rules = styleSheets[i].cssRules,
                    l = rules.length;
                // iterate through each cssRules of this stylesheet
                for (var j = 0; j < l; j++) {
                    // get the selector of this cssRules
                    var selector = rules[j].selectorText;
                    // is it our svg node or one of its children ?
                    if ((svg.matches && svg.matches(selector)) || svg.querySelector(selector)) {
                        // append it to our <style> node
                        style.innerHTML += rules[j].cssText + '\n';
                    }
                }
                // if we got some rules
                if (style.innerHTML) {
                    // append the style node to the clone's defs
                    defs.appendChild(style);
                }
            } catch (e) {
                console.warn('unable to get some cssRules : ', e);
            }
        }
        // small hack to avoid border and margins being applied inside the <img>
        var s = clone.style;
        s.border = s.padding = s.margin = 0;
        s.transform = 'initial';
    };
    

    var svg = document.querySelector('svg');
    var doSomethingWith = function(canvas) {
      document.body.appendChild(canvas)
    };
    
    
    
    var parseStyles = function() {
      var styleSheets = [],
        i;
      // get the stylesheets of the document (ownerDocument in case svg is in <iframe> or <object>)
      var docStyles = svg.ownerDocument.styleSheets;
      // transform the live StyleSheetList to an array to avoid endless loop
      for (i = 0; i < docStyles.length; i++) {
        styleSheets.push(docStyles[i]);
      }
      if (styleSheets.length) {
        // getDef() will return an svg <defs> element if already into the node, or will create it otherwise
        getDef();
        svg.matches = svg.matches || svg.webkitMatchesSelector || svg.mozMatchesSelector || svg.msMatchesSelector || svg.oMatchesSelector;
      }
    
      // iterate through all document's stylesheets
      for (i = 0; i < styleSheets.length; i++) {
        // create a new style element
        var style = document.createElement('style');
        // some stylesheets can't be accessed and will throw a security error
        try {
          var rules = styleSheets[i].cssRules,
            l = rules.length;
          // iterate through each cssRules of this stylesheet
          for (var j = 0; j < l; j++) {
            // get the selector of this cssRules
            var selector = rules[j].selectorText;
            // is it our svg node or one of its children ?
            if ((svg.matches && svg.matches(selector)) || svg.querySelector(selector)) {
              // append it to our <style> node
              style.innerHTML += rules[j].cssText + '\n';
            }
          }
          // if we got some rules
          if (style.innerHTML) {
            // append the style node to the clone's defs
            defs.appendChild(style);
          }
        } catch (e) {
          console.warn('unable to get some cssRules : ', e);
        }
      }
      // small hack to avoid border and margins being applied inside the <img>
      var s = svg.style;
      s.border = s.padding = s.margin = 0;
      s.transform = 'initial';
      exportDoc();
    };
    
    var defs;
    var getDef = function() {
      // Do we have a `<defs>` element already ?
      defs = svg.querySelector('defs') || document.createElementNS('http://www.w3.org/2000/svg', 'defs');
      if (!defs.parentNode) {
        svg.insertBefore(defs, svg.firstElementChild);
      }
    };
    
    var exportDoc = function() {
      // check if our svgNode has width and height properties set to absolute values
      // otherwise, canvas won't be able to draw it
      var bbox = svg.getBoundingClientRect();
    
      if (svg.width.baseVal.unitType !== 1) svg.setAttribute('width', bbox.width);
      if (svg.height.baseVal.unitType !== 1) svg.setAttribute('height', bbox.height);
    
      // serialize our node
      var svgData = (new XMLSerializer()).serializeToString(svg);
      // remember to encode special chars
      var svgURL = 'data:image/svg+xml; charset=utf8, ' + encodeURIComponent(svgData);
    
      var svgImg = new Image();
    
      svgImg.onload = function() {
        var canvas = document.createElement('canvas');
        // IE11 doesn't set a width on svg images...
        canvas.width = this.width || bbox.width;
        canvas.height = this.height || bbox.height;
    
        canvas.getContext('2d').drawImage(svgImg, 0, 0, canvas.width, canvas.height);
        doSomethingWith(canvas)
      };
    
      svgImg.src = svgURL;
    };
    
    parseStyles();
    rect {
      fill: red;
      padding: 25em;
      border: 25px solid yellow;
    }
    canvas {
      border: 1px solid green;
    }
    svg{
      background-color: skyblue;
    }
    <svg width="200" height="200" xmlns="http://www.w3.org/2000/svg" version="1.1">
      <rect x="0" y="0" width="100" height="100" />
    </svg>

    【讨论】:

    • 我没有正确阅读这个问题,虽然这是外部 CSS 的问题。对于内联 CSS,@JosepValls 建议通过 DOM 操作对其进行修改就足够了。无论如何,我都会把它放在这里,以防它对其他人有帮助。
    • 我可以使用内联 CSS,例如填充、高度、宽度。但不能使用背景、内边距、边距、边框等
    • @DawoodiBohra 好吧,填充边距和边框不会对您的内部 svg 元素产生任何影响。看看更新。唯一可能受到影响的元素是 svg 节点本身。我的脚本也处理它,但将这些特定样式应用于它将返回的画布,因此它在光栅化图像中不可见(并且不应该是顺便说一句,因为这些是相对于外部文档的)。但是,应用了背景。
    • 终于在找到拉斐尔脚本之后。我做了我的工作。看一看:materialground.com/icon-maker
    猜你喜欢
    • 2015-04-20
    • 1970-01-01
    • 2014-01-23
    • 1970-01-01
    • 2013-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-28
    相关资源
    最近更新 更多