SVG+JavaScript,如何查找<use>引用是否存在

问题描述 投票:0回答:2

我有一个像这样的 SVG 文件

<svg class="icon" viewBox="0 0 16 16">
  <use href="assets/icons.svg#my-fancy-icon"></use>
</svg>

使用 JavaScript,如何确定

href
元素的
use
属性是否指向实际存在的元素?

javascript svg
2个回答
2
投票

获取
<use>
元素的边界:宽度和高度:0 =不存在

成功附加 svg 元素后,它将返回宽度和高度值 > 0(调用

getBBox()
)。

如果不是 –

getBBox()
将返回宽度和高度值 0。
使用参考无效/不存在。 这也适用于错误附加的元素,例如使用
document.createElement()
(缺少正确的命名空间)而不是
document.createElementNS()
时。

示例 1:检查宽度和高度

let useEls = document.querySelectorAll('use');

useEls.forEach(function(use) {
  let bb = use.getBBox();
  let [width, height] = [bb.width, bb.height];
  if (width == 0 && height == 0) {
    use.closest('svg').classList.add('notavailable')
  }
})
svg {
  height: 10em;
  border: 1px solid #ccc;
  display: inline-block;
}

.notavailable {
  border: 1px solid red;
}
<svg id="svgIcons" class="svgIcons" viewBox="0 0 100 100" style="position:absolute; height:0; width:0;" xmlns="http://www.w3.org/2000/svg">
  <symbol id="home" viewBox="0 0 34 48">
    <path d="M33.16,28.12h-5.2v13h-3.44v-16.72l-7.72-8.72l-7.72,8.72v16.72h-3.44v-13h-5.24l16.4-17.4Z" />
  </symbol>
</svg>

<svg viewBox="0 0 34 48">
  <use href="#home" />
</svg>
<svg viewBox="0 0 34 48">
  <use href="#notExistent" />
</svg>

示例 2:克隆临时 svg 中的所有 use 元素

这样我们还可以检查被 <use>

 隐藏的 
不可见 display: none
 元素
,这些元素会被之前的检查方法忽略。

checkUseEls();

function checkUseEls() {
  // collect missing references
  let missingRefs = [];
  //add temporary hidden svg
  let svgTmp = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
  svgTmp.setAttribute('style', 'position:absolute; width:0; height:0;visibility:hidden');
  document.body.appendChild(svgTmp);

  //add cloned use els
  let useEls = document.querySelectorAll('use');
  useEls.forEach(function(use) {
    let cloned = use.cloneNode();
    cloned.setAttribute('style', 'display:block!important')
    svgTmp.appendChild(cloned)
    let bb = cloned.getBBox();
    let [width, height] = [bb.width, bb.height];
    if (width == 0 && height == 0) {
      missingRefs.push(cloned.getAttribute('href'))
    }
  })
  svgTmp.remove();
  console.log(missingRefs)

}
svg {
  height: 10em;
  border: 1px solid #ccc;
  display: inline-block;
}

.notavailable {
  border: 1px solid red;
}
<svg id="svgIcons" class="svgIcons" viewBox="0 0 100 100" style="display:none" xmlns="http://www.w3.org/2000/svg">
  <symbol id="home" viewBox="0 0 34 48">
    <path d="M33.16,28.12h-5.2v13h-3.44v-16.72l-7.72-8.72l-7.72,8.72v16.72h-3.44v-13h-5.24l16.4-17.4Z" />
  </symbol>
  <symbol id="homeHidden" viewBox="0 0 34 48">
    <path d="M33.16,28.12h-5.2v13h-3.44v-16.72l-7.72-8.72l-7.72,8.72v16.72h-3.44v-13h-5.24l16.4-17.4Z" />
  </symbol>
</svg>

<svg viewBox="0 0 34 48">
  <use href="#home" />
</svg>
<svg viewBox="0 0 34 48" style="display:none">
  <use href="#notExistent" />
</svg>
<svg viewBox="0 0 34 48">
  <use href="#homeHidden" style="display:none"/>
</svg>

符号 #homeHidden 存在但隐藏。通过将

display:block
应用于它的克隆实例,我们可以检查它的高度。

示例3:查询使用定义

您还可以搜索所有定义,例如

<symbol>
元素

findMissingUseDefs();

function findMissingUseDefs() {
  // collect missing references
  let missingRefs = [];

  //add cloned use els
  let useEls = document.querySelectorAll("use");
  useEls.forEach((use) => {
    let href = use.getAttribute("xlink:href") ?
      use.getAttribute("xlink:href") :
      use.getAttribute("href");
    let id = href.replace("#", "");
    let defs = document.querySelectorAll(`${href}`);
    if (!defs.length) {
      missingRefs.push(href);
    }
  });
  console.log(missingRefs);
}
svg {
  height: 10em;
  border: 1px solid #ccc;
  display: inline-block;
}

.notavailable {
  border: 1px solid red;
}
<svg id="svgIcons" class="svgIcons" viewBox="0 0 100 100" style="display:none" xmlns="http://www.w3.org/2000/svg">
      <symbol id="home" viewBox="0 0 34 48">
        <path d="M33.16,28.12h-5.2v13h-3.44v-16.72l-7.72-8.72l-7.72,8.72v16.72h-3.44v-13h-5.24l16.4-17.4Z" />
      </symbol>
      <symbol id="homeHidden" viewBox="0 0 34 48">
        <path d="M33.16,28.12h-5.2v13h-3.44v-16.72l-7.72-8.72l-7.72,8.72v16.72h-3.44v-13h-5.24l16.4-17.4Z" />
      </symbol>
    </svg>

<svg viewBox="0 0 34 48">
      <use href="#home" />
    </svg>
<svg viewBox="0 0 34 48" style="display:none">
      <use href="#notExistent" />
    </svg>
<svg viewBox="0 0 34 48">
      <use href="#homeHidden" style="display:none"/>
    </svg>

如果您使用外部 svgs,您将需要获取所有这些文件并查询解析的文件。总而言之,检查 bbox 可能是最简单的方法。


-2
投票

试试这个方法:

const icon = document.querySelector(".use");

if (icon.firstElementChild === "USE") //...do something
© www.soinside.com 2019 - 2024. All rights reserved.