我想使用在同一 HTML 文件(内联 SVG)中定义的 SVG 形状来剪辑我的元素。
它适用于clip-path:
div {
width: 200px;
height: 200px;
background-color: red;
clip-path: url("#c");
}Run Code Online (Sandbox Code Playgroud)
<div>
<svg>
<defs>
<clippath id="c">
<circle cx="100" cy="100" r="50" />
</clippath>
</defs>
</svg>
</div>Run Code Online (Sandbox Code Playgroud)
但是,当使用掩码时,虽然这在 Firefox 中工作正常,但在 Chrome 中不应用掩码:
div {
width: 200px;
height: 200px;
background-color: red;
mask: url("#m");
}Run Code Online (Sandbox Code Playgroud)
<div>
<svg>
<defs>
<mask id="m">
<circle cx="100" cy="100" r="50" fill="white" />
</mask>
</defs>
</svg>
</div>Run Code Online (Sandbox Code Playgroud)
搜索周围(示例),Chrome 似乎并不期望掩码引用定义,而是引用整个图像。如果图像已内联,是否有办法引用整个图像?或者,我还能做些什么来应用内联元素的蒙版吗?
这是一个丑陋的js解决方案,它将
<mask>,-webkit-mask-image属性。const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
const mask = document.querySelector("mask");
svg.innerHTML = mask.innerHTML;
const markup = new XMLSerializer().serializeToString(svg);
const url = `data:image/svg+xml;charset=utf8,${ encodeURIComponent(markup) }`;
const div = document.getElementById('mask-me');
div.style.webkitMaskImage = `url('${ url }')`;Run Code Online (Sandbox Code Playgroud)
#mask-me {
width: 200px;
height: 200px;
background-color: red;
/**
This will be overidden by -webkit-mask-image even in Firefox.
We could have avoided it with a CSS variable, e.g
-webkit-mask-image: var(--workaround-url);
but Safari acts in all ways as if they did support inline SVG as mask,
when they don't.
So, for them, we have to use the workaround everywhere...
mask-image: url(#m);
**/
}Run Code Online (Sandbox Code Playgroud)
<div id="mask-me">
<svg>
<defs>
<mask id="m">
<circle cx="100" cy="100" r="50" fill="white" />
</mask>
</defs>
</svg>
</div>Run Code Online (Sandbox Code Playgroud)
对于需要该功能的人mask-mode: luminance,您需要通过以下方式在生成的 SVG 图像中手动执行此操作<feColorMatrix type="luminanceToAlpha"/>:
const svgNS = "http://www.w3.org/2000/svg";
const svg = document.createElementNS(svgNS, "svg");
// create a <filter><feColorMatrix type="luninanceToAllpha"/>
const alpha = document.createElementNS(svgNS, "feColorMatrix");
alpha.setAttribute("type", "luminanceToAlpha");
const filter = document.createElementNS(svgNS, "filter");
filter.setAttribute("id", "alpha");
filter.append(alpha);
svg.append(filter);
// apply the filter on all the <mask> content
const g = document.createElementNS(svgNS, "g");
g.setAttribute("filter", "url(#alpha)");
// luminanceToAlpha disregards semi-transparent pixels,
// so we add a black background to have no such thing
const bg = document.createElementNS(svgNS, "rect");
bg.setAttribute("width", "100%");
bg.setAttribute("height", "100%");
g.append(bg);
var mask = document.querySelector('mask').cloneNode(true);
g.append(...mask.children);
svg.append(g);
const markup = new XMLSerializer().serializeToString(svg);
const url = "data:image/svg+xml;charset=utf8," + encodeURIComponent(markup);
const div = document.getElementById("mask-me");
div.style.webkitMaskImage = `url('${ url }')`;Run Code Online (Sandbox Code Playgroud)
.border {
display: inline-block;
border: 1px solid;
}
#mask-me {
width: 300px;
height: 200px;
background-color: red;
/** Safari doesn't really support mask-image using inline SVG either...
mask-image: url(#m);
mask-mode: luminance;
**/
}Run Code Online (Sandbox Code Playgroud)
<div id="mask-me">
<svg width="0">
<defs>
<mask id="m">
<circle cx="100" cy="100" r="50" fill="white" />
<rect x="90" y="90" width="20" height="20" fill="black" />
</mask>
</defs>
</svg>
</div>Run Code Online (Sandbox Code Playgroud)