首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何用Javascript动态设置SVG图像的宽度和高度属性?

如何用Javascript动态设置SVG图像的宽度和高度属性?
EN

Stack Overflow用户
提问于 2020-09-01 07:54:53
回答 1查看 675关注 0票数 0

我们需要用Firefox在画布上呈现SVG图像,但是Firefox doesn't render SVG images没有显式的宽度和高度属性值。

我们的用户上传SVG图片,比如下面没有宽度和高度属性的图片。

如何使用Javascript动态添加宽度和高度属性?下面的方法失败了。

我们使用FileReader将SVG图像作为数据URL读取,并将此数据URL转换为SVG文档,功能如下。

最后,我们将修改后的SVG转换为在画布上呈现的数据URL。但修改后的SVG与原始的SVG具有相同的零宽度/高度问题。

Codepen:https://codepen.io/Crashalot/pen/vYGJzdN

代码语言:javascript
运行
复制
$('#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图标

代码语言:javascript
运行
复制
<?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>
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-09-01 08:51:43

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

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

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

};
代码语言:javascript
运行
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

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

代码语言:javascript
运行
复制
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);
};
代码语言:javascript
运行
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

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

https://stackoverflow.com/questions/63683535

复制
相关文章

相似问题

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