【问题标题】:SVG injection with template literals doesn't work in browser带有模板文字的 SVG 注入在浏览器中不起作用
【发布时间】:2019-07-30 21:37:12
【问题描述】:

我的想法是使用模板文字将内联 SVG 注入我的 HTML。 目的只是利用 CSS 样式内联 SVG 图标的好处,但避免使用 SVG 内容使 html 代码臃肿。此外,只需添加相应的类,就可以很容易地重复使用重复的图标。此外,所有图标或徽标等矢量内容都可以存储在单个 JS 文件中。我知道,这是一个奇怪的想法,但我发现它对我的项目很有用。

所以问题是我的脚本在本地文件中的浏览器中无法运行。 但它在 CodePen 和 JSFiddle 中运行良好。 禁用本地文件限制,启用 JS。

也欢迎任何想法如何优化它并使其更好地工作。

var iconLogo = document.querySelectorAll(".ric-logo");
var i; 
for (i = 0; i < iconLogo.length; i++) {
    iconLogo[i].innerHTML = `
<svg width="120px" height="18px" viewBox="0 0 120 18" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
    <g id="ric-logo" stroke="none" stroke-width="1" fill="black" fill-rule="evenodd">
                <path d="M23.326087,0 C23.2252174,0 23.1275,0 23.0266304,0 L23.0266304,0 L2.52173913,0 C1.12902107,-8.82200545e-17 1.70558772e-16,1.16795283 0,2.60869565 L0,15 L5.04347826,15 L5.04347826,5.2173913 C5.04347826,4.8572056 5.32573353,4.56521739 5.67391304,4.56521739 L22.9730435,4.56521739 C23.631932,4.55997742 24.1901947,5.0660023 24.2717391,5.7423913 C24.306535,6.10977596 24.1892199,6.47520901 23.948885,6.74807191 C23.7085502,7.02093481 23.3677046,7.17567223 23.0108696,7.17391304 L7.56521739,7.17391304 L7.56521739,11.7391304 L23.0266304,11.7391304 L23.0266304,11.7391304 C23.1275,11.7391304 23.2252174,11.7391304 23.326087,11.7391304 C26.4597026,11.7391304 29,9.11123658 29,5.86956522 C29,2.62789386 26.4597026,1.98495123e-16 23.326087,0 Z" id="Path"></path>
                <path d="M64.9565217,1.21154527e-06 L61.173913,1.21154527e-06 C60.170401,-0.000815107822 59.2077021,0.410915432 58.4977174,1.14456624 L49.8796739,10.0532605 C49.6430123,10.2978107 49.3221127,10.4350542 48.9876087,10.4347821 L46.673913,10.4347821 C46.3257335,10.4347821 46.0434783,10.142794 46.0434783,9.78260833 L46.0434783,1.21154527e-06 L41,0 L41,12.3913036 C41,13.8320462 42.1290211,14.9999988 43.5217391,14.9999988 L49.826087,14.9999988 C50.829599,15.0008151 51.7922979,14.5890846 52.5022826,13.8554338 L61.1108696,4.95000041 C61.3493224,4.70184137 61.674158,4.56319679 62.0123913,4.56521787 L64.326087,4.56521787 C64.6742665,4.56521787 64.9565217,4.85720602 64.9565217,5.21739167 L64.9565217,14.9999988 L70,15 L70,2.60869644 C70,1.16795385 68.8709789,1.21154527e-06 67.4782609,1.21154527e-06 L64.9565217,1.21154527e-06 Z" id="Path"></path>
                <path d="M114,10 L120,10 L120,16 C120,17.1045695 118.992641,18 117.75,18 L114,18 L114,10 Z" id="Path"></path>
                <path d="M106,0 L106,9.7826087 C106,10.1427944 105.720178,10.4347826 105.375,10.4347826 L87.625,10.4347826 C87.279822,10.4347826 87,10.1427944 87,9.7826087 L87,0 L82,0 L82,12.3913043 C82,13.8320472 83.1192881,15 84.5,15 L108.5,15 C109.880712,15 111,13.8320472 111,12.3913043 L111,0 L106,0 Z" id="Path"></path>
    </g>
</svg>
`;
}
/* Styling all instances of SVG */

.ric-logo * {
  fill: blue;
	width: 120px;
	height: 15px;
};
<body>
<header class="header-menu">
	<div class="ric-logo">
	</div>
	<div class="menu-content">
		<ul>
			<li><a href="#"></a>Item-1</li>
			<li><a href="#"></a>Item-2</li>
			<li><a href="#"></a>Item-3</li>
			<li><a href="#"></a>Item-4</li>
		</ul>
	</div>
</header>
<main>
  <!-- Test repeating SVG class -->
  <div class="ric-logo">
	</div>
</main>
<footer></footer>
</body>

【问题讨论】:

  • 您是否考虑过简单地使用类似这样的 css 背景图像:.ric-logo { background-image: url(/images/ric-logo.svg); }
  • 嗨 Ted,我的想法是让 SVG 以与内联 SVG 相同的方式工作。如果我将它用作外部文件(图像),我将无法访问它的内部部分。您可以在我的 sn-p 中看到,我可以将 CSS 样式应用于该 SVG — 更改颜色填充、更改悬停时的某些内容,例如甚至为某些部分设置动画。实际上它非常有用——非常简单、轻量级的解决方案,没有任何外部库。但我不知道为什么它不起作用。
  • 啊,搞砸了。这是有道理的。
  • 作为替代解决方案,为了避免臃肿,您可以在页面底部的 &lt;/body&gt; 标记之前创建一个 svg 根目录。这样你就不会被代码打扰了。在您的 HTML 中,您可以创建一个 svg 元素并使用带有 &lt;use xlink:href = "#ric-logo" 的图标。如果您查看 css-tricks.com,这就是他们处理此问题的方式。
  • 谢谢!我已经想通了(您可以在下面查看示例并截断),但是您建议的解决方案非常有用,尤其是在没有太多 SVG 的情况下。 js 注入的最初想法已经奏效,我发现它非常有用(我可以从一个 js 文件中加载整个网站的所有图标和插图一次)。

标签: javascript svg innerhtml template-literals


【解决方案1】:

我不确定您是如何构建文件的,因此我可能无法正确重现您的问题。如果我做了任何错误的假设,请告诉我。

首先,Stack Overflow 上的 codepen 和 sn-ps 自动包含 CSS 和 JS,而本地文件不包含。如果您还没有,则需要包含适当的 &lt;script&gt;&lt;style&gt; 标签,其中包含您的 css 和您的 js。

如果您已经这样做了,并且刚刚出于此问题的目的将它们编辑掉,那么另一个可能的问题是您提供的 javascript 已包含在页面顶部。 document.querySelectorAll(".ric-logo") 在页面加载之前不会工作,如果您将提供的 javascript 放在页面顶部,它将在页面完成加载之前运行。解决此问题的最简单方法是将 javascript 放在页面底部。

如果出于某种原因您不想让 javascript 出现在页面底部,则需要类似 jQuery$(document).readythis question 的原版替代品之一。

【讨论】:

  • 嗨,尼古拉斯,谢谢!看起来它正在工作。我只是将我的
  • 我没想到document.querySelectorAll(".ric-logo") 仅在加载所有内容时才有效。显然这是正确的,因为该脚本需要找到所有选择器。我检查了您对 vanilla 解决方案的建议,以将所有依赖项放在首位,因此它也运行良好。我会附上sn-p,也许对其他人有帮助
【解决方案2】:

@Nicholas 是对的,问题是document.querySelectorAll 在加载所有 DOM 内容之前无法工作。 所以一种解决方案是将document.querySelectorAll 放在页面底部。 另一个是使用在页面加载时运行脚本的函数。解释了here

我将它应用到我的脚本中并且效果很好。因此,如果您有兴趣,我会在此处发布剪辑。它可能有助于使用字符串文字进行模板化,或者在我的情况下动态注入内联 SVG。

// Icons SVG injection 
// Function that run code when DOM is loaded
function ready(callback){
	// in case the document is already rendered
	if (document.readyState!='loading') callback();
	// modern browsers
	else if (document.addEventListener) document.addEventListener('DOMContentLoaded', callback);
	// IE <= 8
	else document.attachEvent('onreadystatechange', function(){
    if (document.readyState=='complete') callback();
    });
}

ready(function(){
// All inside tht function executes when DOM is loaded

// Logo SVG 
	var mySvg = document.querySelectorAll(".my-svg");
	var i; 
	for (i = 0; i < mySvg.length; i++) {
	    mySvg[i].innerHTML = `
      <svg width="188px" height="188px" viewBox="0 0 188 188" version="1.1">
        <circle id="Oval" fill="#FC4903" cx="94" cy="94" r="94"></circle>
</svg>
  `
	};

});
/* styling svg */


.my-svg * {
  fill: red;
	width: 200px;
	height: 200px;
};
<!-- creating container where you like to insert SVG -->
<div class="my-svg">
  <div></div>
</div>

【讨论】:

    猜你喜欢
    • 2020-03-24
    • 2023-03-18
    • 1970-01-01
    • 2019-02-07
    • 1970-01-01
    • 2020-09-01
    • 2021-03-30
    • 2013-11-20
    相关资源
    最近更新 更多