如何检查 svg 文件中有哪些图标可用?



在我的 vuejs2/html 应用程序中基于外部模板 svg 图标 使用,例如:

<svg class="icon icon-plus">
<use xlink:href="/img/icons.svg#plus" />
</svg>
<svg class="icon icon-basket">
<use xlink:href="/img/icons.svg#basket" />
</svg>

文件图标.svg大小为 20 KiB,我想知道

  1. 如果有办法检查哪些图标在此可用 文件?如何检查?我需要关闭,就像"x"一样,但使

    图标.svg#关闭

我失败了。

  1. 我可以修改这些图标的颜色/背景颜色吗?我需要使用 css 程序修改它并设置自定义颜色。

  2. 是否有一些可用的资源易于使用来创建此类 svg 文件?

谢谢!

大多数现代 svg 图标库(羽化图标、fontAwesome 等)都提供类似"备忘单">的东西,显示所有可用的图标.
此外,它们很可能会提供用于嵌入和样式的 api(如更改图标颜色)。

如果找不到任何文档,可以尝试创建如下所示的可视化概述:

let svgIcons = document.querySelector('#svgIcons');
let symbols =  svgIcons.querySelectorAll('symbol[id]');
let symbolUseHtml = '';
symbols.forEach(function(el, i){
let id = el.id;
let viewBox = el.getAttribute('viewBox');
let viewBoxAtt = viewBox ? 'viewBox="'+viewBox+'"' : '';
symbolUseHtml +=
'<div class="icon-wrp"><svg class="icon icon-'+id+'" id="icon-'+id+'" '+viewBoxAtt+'><use href="#'+id+'"></svg><p>'+id+'</p></div>';
});
symbolUseHtml+='';
document.body.insertAdjacentHTML('beforeend', symbolUseHtml);
.icon-wrp{
display:inline-block;
font-size:20px;
padding:0.5em;
border:1px solid #ccc
}
#icon-home{
fill: red;
}
#icon-close{
fill: green;
}
<svg id="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="close" viewBox="0 0 27 48">
<path d="M26.16,17.92l-10.44,10.44l10.44,10.44l-2.44,2.44l-10.44-10.44l-10.44,10.44l-2.44-2.44l10.44-10.44l-10.44-10.44l2.44-2.44l10.44,10.44l10.44-10.44Z" />
</symbol>
</svg>

最有可能的是,查询<symbol>元素可以解决问题 - 正如@chrwahl建议的那样。

不幸的是,没有标准化的概念,图标库如何引用图标资产:
有些人可能会使用嵌套的 svg 元素或包装在<def>中的元素 .
下面是一个可视化的"图标检查器"的草稿,以说明不同的风格:

图标检查器示例

let svgIcons = document.querySelector(".svgIcons");
let svgMarkup = document.querySelector("#svgMarkup");
let svgUseCode = document.querySelector("#svgUseCode");
let svgUseCodeID = document.querySelector("#svgUseCodeID");
let svgIconAssets = document.querySelector(".svgIconAssets");
let iconType = "";
let iconHtml = "";
// default example svg
let svgSrc = `<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="close" viewBox="0 0 27 48">
<path d="M26.16,17.92l-10.44,10.44l10.44,10.44l-2.44,2.44l-10.44-10.44l-10.44,10.44l-2.44-2.44l10.44-10.44l-10.44-10.44l2.44-2.44l10.44,10.44l10.44-10.44Z" />
</symbol>
</svg>`;
svgMarkup.value = svgSrc;
loadSvg(svgSrc);
let svgSrcSelect = document.querySelectorAll(".trackChange");
svgSrcSelect.forEach(function (el, i) {
el.addEventListener("change", function (e) {
svgSrc = e.target.value;
loadSvg(svgSrc);
});
});
function loadSvg(src) {
// if external src
if (src.indexOf("<svg") == -1) {
fetch(src)
.then((response) => response.text())
.then((data) => {
// add temporary svg to DOM
svgIcons.innerHTML = data;
renderIcons(data);
})
.catch((error) => {
let errorData ='<svg class="icon" viewBox="0 0 100 100"><symbol id="error" viewBox="0 0 100 100" ><text  x="50" y="50" width="100"  text-anchor="middle" style="font-size:25%; fill:red">Not available</text></symbol></svg>';
svgIcons.innerHTML = errorData;
renderIcons(errorData);
})
}

// if src is svg markup
else {
svgIcons.innerHTML = src;
renderIcons(src);
}
}

function renderIcons(data) {
let svgOuter = svgIcons.querySelector("svg");
let nested = svgOuter.querySelectorAll("svg");
let symbols = svgOuter.querySelectorAll("symbol");
let icons = symbols.length ? symbols : nested;
let nonPathEls = svgIcons.querySelectorAll("polyline, line");
iconType = icons == symbols ? "symbols" : "nested svgs";
iconHtml = "";
icons.forEach(function (el, i) {
let id = el.id ? el.id : "";
let idAtt = id ? ' id="icon-'+id+'" ' : '';
/**
* if an icon doesn't have an id –
* try to fetch the last class name
**/
let classAtt = !id ? el.classList : "";
let classLast = classAtt ? [].slice.call(classAtt).pop() : "";
let viewBox = el.getAttribute("viewBox");
let viewBoxAtt = viewBox ? 'viewBox="' + viewBox + '"' : "";
let iconDef = id ? document.querySelector("#" + id) : "";
let iconAsset = iconDef ? iconDef : el;
let iconUseHtml = "";
/**
* if icon defs contain other elements
* than paths – like polyline or line –
* maybe they're intended to have outlines/strokes
* but no fill (like in feather-icons)
**/
if (iconAsset) {
let children = iconAsset.childNodes;
if (children.length && nonPathEls.length) {
children.forEach(function (sub, i) {
sub.classList.add("icon-inner-stroke");
});
}
let iconInner = iconAsset ? iconAsset.innerHTML : "";
let iconSelector = !id ? "class: " + '<strong>'+classLast+'</strong>' : "id: " + '<strong>'+id+'</strong>';
if (id) {
iconUseHtml =
'<svg class="icon-use icon-use-' +
id +
idAtt+
viewBoxAtt +
">n" +
'<use href="' +
id +
'" />n' +
"</svg>n";
}
let dataUse = iconUseHtml
? 'data-use="' + encodeURIComponent(iconUseHtml) + '" '
: 'data-use=""';
iconHtml +=
'<div class="icon-wrp" ' +
dataUse +
" >" +
'<svg class="icon icon-' +
id + '" '+
idAtt+
viewBoxAtt +
">" +
iconInner +
"</svg>" +
'<p class="icon-label">' +
iconSelector +
"<br>type: " +
iconType +
"</p>" +
"</div>";
//console.log(svgIconAssets)
}
});
svgIconAssets.innerHTML = iconHtml;
let svgIconWrp = svgIconAssets.querySelectorAll(".icon-wrp");
svgIconWrp.forEach(function (el, i) {
el.addEventListener("click", function (e) {
let currentIcon = e.target.closest(".icon-wrp");
let iconCode = '<!-- not selectable by id -->n'+currentIcon.innerHTML; 
let useCode = currentIcon.getAttribute("data-use");
useCode = useCode ? decodeURIComponent(useCode) : iconCode;
svgUseCode.value = useCode;
svgUseCodeID.innerHTML =
"<strong>" + currentIcon.querySelector("svg").id + "</strong>";
});
});
}
body {
margin: 0;
font-family: "Segoe UI";
}
* {
box-sizing: border-box;
font-family: inherit;
}
:root {
--svgHover: red;
}
::-webkit-scrollbar {
width: 0.45em;
border-radius: 0.5em;
background: #ddd;
}
::-webkit-scrollbar-track {
border-radius: 0.5em;
}
::-webkit-scrollbar-thumb {
background: #aaa;
border-radius: 0.5em;
}
.layout {
display: flex;
height: 100vh;
overflow: hidden;
}
.svgIconAssets {
display: flex;
flex-wrap: wrap;
}
.icon-wrp {
width: 10vw;
font-size: 4vw;
margin-bottom: 0.5em;
text-align: center;
}
.icon-wrp * {
text-align: center;
}
.icon-label {
font-size: 12px;
text-align: center;
margin: 0;
}
.icon {
display: inline-block;
height: 1em;
font-size: 1em;
color: #999;
fill: #999;
cursor:pointer;
&:hover {
color: var(--svgHover);
fill: var(--svgHover);
}
}
.icon-inner-stroke {
stroke: currentColor;
stroke-width: 2;
stroke-linecap: round;
stroke-linejoin: round;
fill: none;
}
input {
width: 100%;
}
label{
font-size:0.8rem;
line-height: 1.2em;
margin-bottom:0.25rem;
}
.svgDisplay {
width: 75%;
height: 100%;
position: relative;
overflow: auto;
}
.frm-wrp {
padding: 1em;
margin-left: auto;
width: 20%;
background-color: #ccc;
display: flex;
flex-direction: column;
flex: 1;
* {
width: 100%;
}
textarea {
min-height: 5em;
height: 90%;
white-space: pre-wrap;
font-family: monospace;
}

input, textarea{
margin-bottom: 0.5rem;
}
}
<div class="layout">
<div class="svgDisplay">
<div class="svgIcons" style="display:none"></div>
<div class="svgIconAssets"></div>
</div>
<div class="frm-wrp">
<label>Svg URL</label>
<input type="text" id="svgSrcSelect" class="svgSrcSelect trackChange" list="dataSrc" placeholder="select example or paste svg url" />
<datalist id="dataSrc">
<option value="https://unpkg.com/feather-icons@4.28.0/dist/feather-sprite.svg">Feather icons</option>
<option value="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0-beta3/sprites/regular.svg">FontAwesome (6.0)</option>
<option value="https://cdn.jsdelivr.net/npm/font-awesome-svg-icons@0.1.0/svg-sprite.svg">FontAwesome (0.1)</option>
</datalist>
<label>Svg markup</label>
<textarea id="svgMarkup" class="svgMarkup trackChange" placeholder="enter svg code"></textarea>
<label>Svg use code: <span id="svgUseCodeID"></span></label>
<textarea id="svgUseCode" class="svgUseCode" placeholder="enter svg code"></textarea>
</div>
</div>

此示例包含 3 个图标库 svg(您可以在 URL 字段中选择它们作为数据列表选项).
显著差异:

1. 羽毛图标

  • 图标定义为符号
  • 包含不同的元素类型,如圆形、折线等(除了<path>
  • )
  • 所有图标均按描边属性(描边、描边宽度、描边线帽)设置样式

阿拉伯数字。字体真棒 (6.0)

  • 图标定义为符号
  • 所有资产均为实心/闭合<path>形状
  • 所有图标均按填充属性设置样式

3.字体真棒 (0.1)

  • 图标分组在嵌套的 SVG 元素中
  • 使用类名而不是 ID (可能应该只是一个测试文件)

最新更新