我正在构建一个编辑器,用户可以从CDN中选择SVG,并选择其填充颜色。在前端,我希望能够以用户选择的颜色呈现这些SVG,但这似乎是不可能的。有人知道我应该尝试什么方法吗?
我从服务器得到的数据如下:
-
cdnURL:用来加载SVG的URL
-
fillColor:与前端的SCSS变量对应的文本。我已经为所有颜色创建了实用程序类来实现fill-property:
color__fill--black { fill: black; }
我在这个网站上遇到过建议更改svg文件的fill-property的答案,但这是不可能的,因为我在CDN上只有它的源url。我也看到有人建议使用CSS过滤器,但这并不能解决我的问题,因为颜色变化很大,从黑色到蓝色到黄色到白色。
我建议您加载选定的SVG并将其内联插入到HTML元素中。这里我只使用fetch函数。基本上我在数组中的数据url可以用普通的url替换,代码仍然可以工作(从同一域的web服务器运行)。
当涉及到颜色时,可能有许多不同的方法。这里我更改了一个样式元素的内容。SVG中的任何元素都将获得指定的颜色。
const urls = [ 'data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTAgMTAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPHBhdGggZD0iTSA1IDAgTCAwIDUgTCA1IDEwIEwgMTAgNSBaIiAvPgo8L3N2Zz4=',
'data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTAgMTAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CiAgPGNpcmNsZSBjeD0iNSIgY3k9IjUiIHI9IjUiIC8+Cjwvc3ZnPg=='
];
const container = document.getElementById('container');
const style = document.getElementById('style01');
document.forms.form01.img.addEventListener('change', e => {
if(e.target.value){
fetch(urls[e.target.value]).then(res => res.text()).then(text => {
container.innerHTML = text;
});
}
});
document.forms.form01.color.addEventListener('change', e => {
style.textContent = `#container * {fill: ${e.target.value};}`;
});
#container {
width: 200px;
}
<style id="style01">#container * {fill: #1a5fb4;}</style>
<form name="form01">
<select name="img">
<option>Select an SVG</option>
<option value="0">SVG 1</option>
<option value="1">SVG 2</option>
</select>
<input name="color" type="color" value="#1a5fb4" />
</form>
<div id="container"></div>
简单,创建一个原生javascript<load-svg>
Web组件。
- 加载外部SVG文件
- 将其分配给shadowDOM innerHTML
- 附加所有
<style>
元素
<load-svg src="//svg-cdn.github.io/heart.svg">
<style>
svg { height: 180px } path:nth-child(2n+2) { fill: red }
</style>
</load-svg>
<load-svg src="//svg-cdn.github.io/heart.svg">
<style>
svg { height: 180px } path:nth-child(3n+2) { fill: yellow }
</style>
</load-svg>
<load-svg src="//svg-cdn.github.io/heart.svg">
<style>
svg { height: 180px } path:nth-child(3n+1) { fill: blue }
</style>
</load-svg>
<script>
customElements.define('load-svg', class extends HTMLElement {
async connectedCallback() {
this.attachShadow({mode:"open"})
.innerHTML = await (await fetch(this.getAttribute("src"))).text();
this.shadowRoot.append(...this.childNodes);
}
});
</script>