如何获得 svg <image> 元素的自然尺寸?

Fuz*_*yma 7 javascript svg image

在 HTML 中,我们有一个<img>有点映射到Image对象的元素。两者都有两个名为naturalWidthand 的属性naturalHeight。当您想在load回调中将图像的尺寸设置为其自然尺寸时,您可以轻松地使用

var img = new Image
img.addEventListener('load' function(e) {
    // do whatever with naturalWidt/Height
})
Run Code Online (Sandbox Code Playgroud)

但是,当您想设置 svg<image>元素的尺寸时,您不能依赖于此,因为该元素没有natural属性:

var img = document.createElementNS(namespace, 'image')
img.addEventListener('load' function(e) {
    img.setAttributeNS(namespace, 'width', img.naturalWidth) // dont work
})
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:如何在<image>不加载图像的情况下设置 svg elemet的尺寸new Image?规范中是否有计划支持此类natural属性?

her*_*zel 1

Svg<image>元素缺失widthheight属性将默认使用自然像素尺寸。

但是,父 svg 元素不会通过调整其viewBox实际布局withheight.

获取BBox()

使用 svggetBBox()方法检索任何“可渲染元素”的边界框。

与 HTML 元素类似,<img>我们需要等待图像 src 加载。

getBBox()需要将一个元素附加到 DOM - 否则它返回 0x0 边界框。

示例:追加 svg <image>、加载 src 并调整 svg 大小

let svg = document.getElementById("svg");

function loadImg(href) {
  // create namespaced svg element
  let ns = "http://www.w3.org/2000/svg";
  let image = document.createElementNS(ns, "image");
  // set href
  image.setAttribute("href", href);
  svg.appendChild(image);

  image.addEventListener("load", (e) => {
    // get bounding box
    let bb = e.currentTarget.getBBox();
    let [width, height] = [bb.width, bb.height];
    image.setAttribute("width", width);
    image.setAttribute("height", height);
    //adjust viewBox
    svg.setAttribute("viewBox", [0, 0, width, height].join(" "));
    // optional - if you resize your svg via css
    svg.setAttribute("width", width);
    svg.setAttribute("height", height);
  });
}
Run Code Online (Sandbox Code Playgroud)
svg{
  overflow:visible;
  border:1px solid red;
  background:#ccc;
}
Run Code Online (Sandbox Code Playgroud)
<p><button type="button" onclick="loadImg('https://placehold.co/600x400')">load image</button></p>
<svg id="svg" xmlns="http://www.w3.org/2000/svg" width="50" height="50" viewBox="0 0 100 100">
</svg> adjacent text. 
Run Code Online (Sandbox Code Playgroud)

由于浏览器通常缓存图像请求,您也可以使用上述new image()方法来获取图像naturalWidth并将其应用到 svg,<image> 如此处所述