img标签中的SVG完全透明 [英] SVG entire transparent in img tag
问题描述
我有一个奇怪的问题,我想屏蔽图像,为了简单起见,我尝试了 svg 方式,如下所示:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="217.714"height="321.143" viewBox="0 0 58 85"><定义><掩码 id="a"><path d="M22.5 0L45 31.5 22.5 63 0 31.5z" fill="#fff"/></掩码></defs><image xlink:href="https://upload.wikimedia.org/wikipedia/commons/9/97/The_Earth_seen_from_Apollo_17.jpg" mask="url(#a)" preserveAspectRatio="xMidYMid slice" width="45"height="63" transform="translate(6.5 14.5)"/></svg>
我的问题是当我嵌入这个图像时,它似乎是透明的.当我在浏览器中打开它时,它按预期工作.但是,当我使用 <img src="my.svg">
之类的 img 标签添加它时,它采用 svg 中定义的尺寸,但它是透明的.
我尝试上传 svg,但文件类型不受支持,因此我创建了一个
但是你可以通过一些技巧绕过它:
- 使用
new Image()
在内存中加载 IMG URL - 将其转移到 CANVAS
- 从 CANVAS 中提取图像到 DataURL 字符串
- 将完整的 SVG DataURI string(不是 SVG 文件的 url)写入您的 hostIMG src
使用 W3C 标准自定义元素,您可以将其用作:
<masked-img src="https://i.picsum.photos/id/21/200/200.jpg" mask="circle"></masked-img>
JSFiddle 位于:https://jsfiddle.net/CustomElementsExamples/cuwrm7ba/
<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 50 50'><mask id="circle"><circle cx='50%' cy='50%' r='20' fill="#fff"/></mask><mask id="钻石"><polygon points="25 0 50 25 25 50 0 25" fill="#999" stroke="#f00" stroke-width="5"/></掩码><image mask='url(#MASK)' x='0' y='0' width='50' height='50' href='IMG'/></svg></模板><脚本>customElements.define('masked-img', class extends HTMLElement {静态获取观察属性(){返回 ["src", "掩码"];//每当这些属性改变时更新}连接回调(){this.hostIMG = this.appendChild(document.createElement("IMG"));}attributeChangedCallback() {让 svgTemplate = document.querySelector(this.getAttribute("svg")).innerHTML;让 loadIMG = new Image();loadIMG.crossOrigin = '匿名';//!!必需的loadIMG.onload = () =>{let canvas = document.createElement("canvas");canvas.width = loadIMG.width;canvas.height = loadIMG.height;canvas.getContext("2d").drawImage(loadIMG, 0, 0);this.hostIMG.src = `data:image/svg+xml,` +svgTemplate.replace('IMG', canvas.toDataURL("image/png")).replace('MASK', this.getAttribute("mask")).replace(/"/g, "'").replace(/#/g, "%23");//dataURI 中的非法字符};loadIMG.src = this.getAttribute("src");//上面触发 onload}});<风格>图像{宽度:20%;背景:灰色;}</风格><img src="https://i.picsum.photos/id/21/200/200.jpg"><masked-img svg="#one" src="https://i.picsum.photos/id/21/200/200.jpg" mask="circle"></masked-img><img src="https://i.picsum.photos/id/3/100/100.jpg"><masked-img svg="#one" src="https://i.picsum.photos/id/3/100/100.jpg" mask="diamond"></masked-img>代码>
I have a strange issue I want to mask an image, to keep it simple I tried the svg way as here:
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="217.714" height="321.143" viewBox="0 0 58 85">
<defs>
<mask id="a">
<path d="M22.5 0L45 31.5 22.5 63 0 31.5z" fill="#fff"/>
</mask>
</defs>
<image xlink:href="https://upload.wikimedia.org/wikipedia/commons/9/97/The_Earth_seen_from_Apollo_17.jpg" mask="url(#a)" preserveAspectRatio="xMidYMid slice" width="45" height="63" transform="translate(6.5 14.5)"/>
</svg>
My problem is when I embedded this image it seems to be transparent. When I open it in my browser it works as intended. However when I add it with a img tag like <img src="my.svg">
it takes the dimensions as defined in the svg, but it is transparent.
I tried to upload the svg, but the file type is not supported so I created a gist where it doesn't work too. That is so strange.
It should look like this:
Please tell me why this isn't working as expected. If it matter I'm using Firefox 76 on Windows 10.
Yes,
SVG content has CORS restrictions: https://oreillymedia.github.io/Using_SVG/extras/ch10-cors.html
But you can bypass it with some tricks:
- Load the IMG URL in Memory with
new Image()
- transfer it to a CANVAS
- extract the Image from the CANVAS to a DataURL String
- write full SVG DataURI string (NOT the url to an SVG file) into your hostIMG src
With a W3C standard Custom Element you use it as:
<masked-img src="https://i.picsum.photos/id/21/200/200.jpg" mask="circle"></masked-img>
JSFiddle at: https://jsfiddle.net/CustomElementsExamples/cuwrm7ba/
<template id="one">
<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 50 50'>
<mask id="circle"><circle cx='50%' cy='50%' r='20' fill="#fff" /></mask>
<mask id="diamond">
<polygon points="25 0 50 25 25 50 0 25" fill="#999" stroke="#f00" stroke-width="5" />
</mask>
<image mask='url(#MASK)' x='0' y='0' width='50' height='50' href='IMG' />
</svg>
</template>
<script>
customElements.define('masked-img', class extends HTMLElement {
static get observedAttributes() {
return ["src", "mask"]; // update whenever these attributes change
}
connectedCallback() {
this.hostIMG = this.appendChild(document.createElement("IMG"));
}
attributeChangedCallback() {
let svgTemplate = document.querySelector(this.getAttribute("svg")).innerHTML;
let loadIMG = new Image();
loadIMG.crossOrigin = 'anonymous';//!! required
loadIMG.onload = () => {
let canvas = document.createElement("canvas");
canvas.width = loadIMG.width;
canvas.height = loadIMG.height;
canvas.getContext("2d").drawImage(loadIMG, 0, 0);
this.hostIMG.src = `data:image/svg+xml,` +
svgTemplate.replace('IMG', canvas.toDataURL("image/png"))
.replace('MASK', this.getAttribute("mask"))
.replace(/"/g, "'").replace(/#/g, "%23");// illegal characters in dataURI
};
loadIMG.src = this.getAttribute("src");// triggers above onload
}
});
</script>
<style>
img {
width: 20%;
background: grey;
}
</style>
<img src="https://i.picsum.photos/id/21/200/200.jpg">
<masked-img svg="#one" src="https://i.picsum.photos/id/21/200/200.jpg" mask="circle"></masked-img>
<img src="https://i.picsum.photos/id/3/100/100.jpg">
<masked-img svg="#one" src="https://i.picsum.photos/id/3/100/100.jpg" mask="diamond"></masked-img>
这篇关于img标签中的SVG完全透明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!