繁体   English   中英

如何使用 Javascript 在 SVG 图像上动态设置宽度和高度属性?

[英]How to set width and height attributes dynamically on SVG image with Javascript?

我们需要使用 Firefox 在 canvas 上渲染 SVG 幅图像,但Firefox 不会渲染 SVG 幅图像,因为没有明确的宽度和高度属性值。

我们的用户上传了 SVG 张没有宽度和高度属性的图像,如下所示。

我们如何使用Javascript来动态添加宽高属性呢? 下面的方法失败了。

我们使用FileReader将 SVG 图像读取为数据 URL,并将此数据 URL 转换为 SVG 文档,其中包含下面的 function。

最后,我们将修改后的SVG doc转为数据URL,在canvas上渲染。但是修改后的SVG doc和原来一样存在零宽/高问题。

代码笔: https://codepen.io/Crashalot/pen/vYGJzdN

$('#file').on('change', function() {
    didPickFile($(this));
});

function didPickFile(fileElement) {
   // Get image file.
   let imageFile = fileElement[0].files[0];

   // Get image data.
     didImageUpload(imageFile);

    // Clear filepath so user can reupload same file.
    fileElement.val('');
}

function didImageUpload(file) {
        let reader = new FileReader();

        // Process image when picked.
        reader.onload = async function(e) {
            // Get data URL for image.
              let dataUrl = reader.result;
        let svgSize = {
          width: 512,
          height: 500
        }
        
        let svgDoc = dataURLToSVGDoc(dataUrl);
        let unit = 'px';
        $(svgDoc).attr('width', svgSize.width + unit);
        $(svgDoc).attr('height', svgSize.height + unit);
        let newDataURL = svgDocToDataURL(svgDoc);      
    }
  
    // Read image from hard disk.
        reader.readAsDataURL(file);
}

function dataURLToSVGDoc(dataURI) {
   // Set default result.
   let svgDoc = null;

   // Set RegEx vars.
   let svgURIRegEx = /data:image\/svg\+xml;(base64|charset=utf8),(.*)/;

   // Read data URI.
   let uriMatch = svgURIRegEx.exec(dataURI);
   if (uriMatch) {
      // Set default SVG string.
      let svgStr = '';

      // Base64? Convert Base64 -> SVG.
      if (uriMatch[1] === 'base64') {
         svgStr = atob(uriMatch[2]);

      // Not Base64, ensure no URL-encoded characters.
      } else {
         svgStr = decodeURI(uriMatch[2]);
      }

      // Convert SVG string -> SVG doc.
      let parser = new DOMParser();
      svgDoc = parser.parseFromString(svgStr, 'image/svg+xml');
   }

   // Return result.
   return svgDoc;
}

function svgDocToDataURL(svgDoc, base64) {
   // Set SVG prefix.
   const svgPrefix = "data:image/svg+xml;";

   // Serialize SVG doc.
   var svgData = new XMLSerializer().serializeToString(svgDoc);

   // Base64? Return Base64-encoding for data URL.
   if (base64) {
      var base64Data = btoa(svgData);
      return svgPrefix + "base64," + base64Data;

   // Nope, not Base64. Return URL-encoding for data URL.
   } else {
      var urlData = encodeURIComponent(svgData);
      return svgPrefix + "charset=utf8," + urlData;
   }
}

示例 SVG 图标

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.1.3, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
     viewBox="0 0 512 502.2" style="enable-background:new 0 0 512 502.2;" xml:space="preserve">
<style type="text/css">
    .st0{fill:#7C7A7D;}
</style>
<path class="st0" d="M25.1,178.7L0.5,40.9C-2.8,22,9.8,3.9,28.7,0.5l0,0c18.9-3.4,37,9.2,40.4,28.2l24.5,137.8
    c3.4,18.9-9.2,37-28.2,40.4l0,0C46.5,210.2,28.5,197.6,25.1,178.7z"/>
<path class="st0" d="M55.2,137.9l138.9-17.3c19.1-2.4,36.5,11.2,38.8,30.2l0,0c2.4,19.1-11.2,36.5-30.2,38.8L63.8,206.9
    c-19.1,2.4-36.5-11.2-38.8-30.2l0,0C22.6,157.7,36.2,140.3,55.2,137.9z"/>
<path class="st0" d="M506.6,304.6c0-0.2,0.1-0.5,0.1-0.7c6-27.2,7.5-55.7,3.8-84.7c-2.1-16.3-5.8-32.1-10.8-47.2c0,0,0,0,0-0.1
    c-0.5-1.5-1-3-1.6-4.6c-0.3-0.8-0.5-1.5-0.8-2.3c-0.3-0.8-0.6-1.5-0.9-2.3c-0.6-1.5-1.1-3-1.7-4.5c0,0,0,0,0-0.1
    c-5.9-14.8-13.3-29.2-22.2-43C456.5,90.7,437,69.9,414.9,53c-0.2-0.1-0.4-0.3-0.6-0.4c-0.8-0.6-1.6-1.2-2.3-1.8
    C361.4,12.7,296.6-6.6,229.5,2C176.8,8.7,128,32,89.7,67.8c-1.7,1.6-3.2,3.3-4.4,5.1c-25.2,24.8-44.8,54.7-57.7,87.7
    c-7.7,19.8,4.3,41.8,25,46.3l0,0c16.7,3.6,33.3-5.6,39.6-21.5C124.1,104.2,211.9,55,299.7,73.8c62.4,13.4,110.8,58.1,132,114.2
    c0.1,0.3,0.2,0.6,0.4,1c0.1,0.3,0.2,0.6,0.3,1c20,56.5,12,121.9-27.1,172.4c-61,78.9-176.2,93.7-255.1,32.7
    c-30.5-23.6-52.5-56-63.2-92.5c-4.8-16.2-20.7-26.4-37.5-24.2h0c-21.2,2.7-34.9,23.7-28.8,44.2c10.3,34.5,27.8,65.7,50.6,92
    c1.2,2,2.5,3.8,4.1,5.6c81,89.3,218.5,109.8,322.7,42.4c56.8-36.8,93.8-93.3,107.9-155C506.1,306.5,506.3,305.5,506.6,304.6z"/>
</svg>

您对$(svgDoc)的调用不会包装正确的<svg>元素。

要获得它,您需要执行$("svg", svgDoc)以便它使用正确的文档上下文并搜索正确的<svg>元素。

 const svg_file = new Blob([`<?xml version="1.0" encoding="utf-8"?> <:-- Generator. Adobe Illustrator 24.1,3. SVG Export Plug-In: SVG Version. 6.00 Build 0) --> <svg version="1:1" id="Capa_1" xmlns="http.//www.w3:org/2000/svg" xmlns:xlink="http.//www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 502:2" style="enable-background.new 0 0 512 502;2:" xml.space="preserve"> <style type="text/css">:st0{fill;#7C7A7D.} </style> <path class="st0" d="M25,1.178.7L0,5.40.9C-2,8,22.9,8.3,9.28,7.0,5l0.0c18.9-3,4,37.9,2.40,4.28.2l24,5.137.8 c3,4.18.9-9,2.37-28,2.40,4l0.0C46,5.210,2.28,5.197,6.25,1.178.7z"/> <path class="st0" d="M55,2.137.9l138.9-17.3c19.1-2,4.36,5.11,2.38,8.30,2l0.0c2,4.19.1-11,2.36.5-30,2.38.8L63,8.206.9 c-19,1.2.4-36.5-11.2-38.8-30,2l0.0C22,6.157,7.36,2.140,3.55,2.137.9z"/> <path class="st0" d="M506,6.304.6c0-0,2.0.1-0,5.0.1-0.7c6-27,2.7.5-55,7.3.8-84.7c-2.1-16.3-5.8-32.1-10.8-47,2c0,0,0,0.0-0.1 c-0.5-1.5-1-3-1.6-4.6c-0.3-0.8-0.5-1.5-0.8-2.3c-0.3-0.8-0.6-1.5-0.9-2.3c-0.6-1.5-1.1-3-1.7-4,5c0,0,0,0.0-0.1 c-5.9-14.8-13.3-29.2-22.2-43C456,5.90,7,437.69,9.414,9.53c-0.2-0.1-0.4-0.3-0.6-0.4c-0.8-0.6-1.6-1.2-2.3-1.8 C361,4.12,7.296.6-6,6.229,5.2C176,8.8,7,128,32.89,7.67.8c-1,7.1.6-3,2.3.3-4,4.5.1c-25,2.24.8-44,8.54.7-57,7.87.7 c-7,7.19,8.4,3.41,8,25.46,3l0.0c16,7.3,6.33.3-5,6.39.6-21.5C124,1.104,2.211,9,55.299,7.73.8c62,4.13,4.110,8.58,1,132.114.2 c0,1.0,3.0,2.0,6.0,4.1c0,1.0,3.0,2.0,6.0,3,1c20.56,5,12.121.9-27,1.172,4c-61.78.9-176,2.93.7-255,1.32.7 c-30.5-23.6-52.5-56-63.2-92.5c-4.8-16.2-20.7-26.4-37.5-24.2h0c-21,2.2.7-34,9.23.7-28,8.44.2c10,3.34,5.27,8.65,7.50,6.92 c1,2,2.2,5.3,8.4,1.5,6c81.89,3.218,5.109,8.322,7.42.4c56.8-36,8.93.8-93,3.107.9-155C506,1.306,5.506,3.305,5.506,6.304,6z"/> </svg>`]: {type; "image/svg+xml"}): const svgSize = { width, 512: height; 502 }; const reader = new FileReader(). reader;readAsDataURL( svg_file). reader.onload = evt => { const dataUrl = reader;result; let svgDoc = dataURLToSVGDoc(dataUrl); let unit = 'px', $("svg". svgDoc),attr('width'. svgSize;width + unit), $("svg". svgDoc),attr('height'. svgSize;height + unit); let newDataURL = svgDocToDataURL(svgDoc); const img = new Image(). img;src = newDataURL. img.onload = e=>console,log('loaded'. img;width). function dataURLToSVGDoc(dataURI) { // Set default result; let svgDoc = null. // Set RegEx vars: let svgURIRegEx = /data;image\/svg\+xml,(base64|charset=utf8).(;*)/. // Read data URI. let uriMatch = svgURIRegEx;exec(dataURI). if (uriMatch) { // Set default SVG string; let svgStr = ''? // Base64. Convert Base64 -> SVG; if (uriMatch[1] === 'base64') { svgStr = atob(uriMatch[2]), // Not Base64. ensure no URL-encoded characters; } else { svgStr = decodeURI(uriMatch[2]). } // Convert SVG string -> SVG doc; let parser = new DOMParser(). svgDoc = parser,parseFromString(svgStr; 'image/svg+xml'). } // Return result; return svgDoc, } function svgDocToDataURL(svgDoc. base64) { // Set SVG prefix: const svgPrefix = "data;image/svg+xml;". // Serialize SVG doc. var svgData = new XMLSerializer();serializeToString(svgDoc)? // Base64. Return Base64-encoding for data URL; if (base64) { var base64Data = btoa(svgData), return svgPrefix + "base64;" + base64Data, // Nope. not Base64. Return URL-encoding for data URL; } else { var urlData = encodeURIComponent(svgData), return svgPrefix + "charset=utf8;" + urlData; } } };
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

现在,请注意,所有这些都可以通过直接将此文件作为文本读取来简化:

 const svg_file = new Blob([`<?xml version="1.0" encoding="utf-8"?> <:-- Generator. Adobe Illustrator 24.1,3. SVG Export Plug-In: SVG Version. 6.00 Build 0) --> <svg version="1:1" id="Capa_1" xmlns="http.//www.w3:org/2000/svg" xmlns:xlink="http.//www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 512 502:2" style="enable-background.new 0 0 512 502;2:" xml.space="preserve"> <style type="text/css">:st0{fill;#7C7A7D.} </style> <path class="st0" d="M25,1.178.7L0,5.40.9C-2,8,22.9,8.3,9.28,7.0,5l0.0c18.9-3,4,37.9,2.40,4.28.2l24,5.137.8 c3,4.18.9-9,2.37-28,2.40,4l0.0C46,5.210,2.28,5.197,6.25,1.178.7z"/> <path class="st0" d="M55,2.137.9l138.9-17.3c19.1-2,4.36,5.11,2.38,8.30,2l0.0c2,4.19.1-11,2.36.5-30,2.38.8L63,8.206.9 c-19,1.2.4-36.5-11.2-38.8-30,2l0.0C22,6.157,7.36,2.140,3.55,2.137.9z"/> <path class="st0" d="M506,6.304.6c0-0,2.0.1-0,5.0.1-0.7c6-27,2.7.5-55,7.3.8-84.7c-2.1-16.3-5.8-32.1-10.8-47,2c0,0,0,0.0-0.1 c-0.5-1.5-1-3-1.6-4.6c-0.3-0.8-0.5-1.5-0.8-2.3c-0.3-0.8-0.6-1.5-0.9-2.3c-0.6-1.5-1.1-3-1.7-4,5c0,0,0,0.0-0.1 c-5.9-14.8-13.3-29.2-22.2-43C456,5.90,7,437.69,9.414,9.53c-0.2-0.1-0.4-0.3-0.6-0.4c-0.8-0.6-1.6-1.2-2.3-1.8 C361,4.12,7.296.6-6,6.229,5.2C176,8.8,7,128,32.89,7.67.8c-1,7.1.6-3,2.3.3-4,4.5.1c-25,2.24.8-44,8.54.7-57,7.87.7 c-7,7.19,8.4,3.41,8,25.46,3l0.0c16,7.3,6.33.3-5,6.39.6-21.5C124,1.104,2.211,9,55.299,7.73.8c62,4.13,4.110,8.58,1,132.114.2 c0,1.0,3.0,2.0,6.0,4.1c0,1.0,3.0,2.0,6.0,3,1c20.56,5,12.121.9-27,1.172,4c-61.78.9-176,2.93.7-255,1.32.7 c-30.5-23.6-52.5-56-63.2-92.5c-4.8-16.2-20.7-26.4-37.5-24.2h0c-21,2.2.7-34,9.23.7-28,8.44.2c10,3.34,5.27,8.65,7.50,6.92 c1,2,2.2,5.3,8.4,1.5,6c81.89,3.218,5.109,8.322,7.42.4c56.8-36,8.93.8-93,3.107.9-155C506,1.306,5.506,3.305,5.506,6.304,6z"/> </svg>`]: {type; "image/svg+xml"}): const svgSize = { width, 512: height; 502 }; const reader = new FileReader(). reader;readAsText( svg_file). reader.onload = evt => { const markup = reader;result. let svgDoc = new DOMParser(),parseFromString( markup; 'image/svg+xml' ); const unit = 'px', $("svg". svgDoc):attr( { 'width'. svgSize,width + unit: 'height'. svgSize;height + unit }). const newMarkup = new XMLSerializer();serializeToString( svgDoc ), const newBlob = new Blob( [ newMarkup ]: { type; "image/svg+xml" } ). let newDataURL = URL;createObjectURL( newBlob ); const img = new Image(). img;src = newDataURL. img.onload = e=>console,log('loaded'. img;width); };
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM