CSS SVG 蒙版上的过渡?
CSS transition on the mask of an SVG?
我在一个内联 SVG 中有一个图像,当它悬停在上面时会在两个蒙版之间切换。
但是,CSS 转换不适用于 transition-property: mask;
是否有其他方法可用于 CSS 转换?
我也试过设置样式 <mask>
但似乎无法设置定义元素的样式 (?)。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div style="width: 604px; height: 302px; margin: 20px auto;"> <!-- IE needs width AND height specified to scale the SVG inside correctly. -->
<svg id="artwork" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1208 604">
<style type="text/css">
/* <![CDATA[ */
.mask_hover a:link,
.mask_hover a:visited {
mask: url(#mask_right);
}
.mask_hover a:hover,
.mask_hover a:active {
transition-property: mask;
transition-duration: 0.4s;
transition-timing-function: ease-in-out;
mask: url(#mask_left);
}
/* ]]> */
</style>
<defs>
<mask id="mask_left">
<circle id="circle_l" cx="416" cy="216" r="202" fill="#fff"/>
</mask>
<mask id="mask_right">
<circle id="circle_r" cx="809" cy="337" r="202" fill="#fff"/>
</mask>
</defs>
<g class="mask_hover">
<a xlink:href="#">
<image id="img" width="1208" height="604" xlink:href="https://i.stack.imgur.com/LCpGU.jpg"/>
</a>
</g>
</svg>
</div>
</body>
</html>
图片来源:Pixabay
真的不是mask
属性不能动画,而是url()
.
要创建过渡,您需要有一个状态 1 到状态 2,并且可以在两个状态之间创建插值。
当您使用 url(#1)
并希望转到 url(#2)
时,无法在这两个状态之间创建任何插值,因为 url(#1.5)
不会是中间状态。
不过可以动画化的是蒙版的内容。
在 SVG2 中,您可以直接设置从 CSS 更改的属性(即 cx
和 cy
),但这仍然仅受 Blink&Safari 浏览器支持:
<svg id="artwork" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1208 604">
<style type="text/css">
/* <![CDATA[ */
.mask_hover a:link,
.mask_hover a:visited {
mask: url(#mask);
}
#mask > circle {
transition-property: cx, cy;
transition-duration: 0.4s;
transition-timing-function: ease-in-out;
}
.mask_hover a:hover + defs #mask > circle,
.mask_hover a:active + defs #mask > circle {
cx: 416;
cy: 216;
}
/* ]]> */
</style>
<g class="mask_hover">
<a xlink:href="#">
<image id="img" width="1208" height="604" xlink:href="https://i.stack.imgur.com/LCpGU.jpg"/>
</a>
<!-- we need to move it here so we can target it with our CSS rules -->
<defs>
<mask id="mask">
<circle id="circle_l" cx="809" cy="337" r="202" fill="#fff"/>
</mask>
</defs>
</g>
</svg>
对于不支持这部分 SVG2 的其他浏览器,您应该可以使用转换 属性 来完成它,但不知何故,Firefox 不接受它...
<svg id="artwork" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1208 604">
<style type="text/css">
/* <![CDATA[ */
.mask_hover a:link,
.mask_hover a:visited {
mask: url(#mask);
}
#mask > circle {
transition-property: transform;
transition-duration: 0.4s;
transition-timing-function: ease-in-out;
}
.mask_hover a:hover + defs #mask > circle,
.mask_hover a:active + defs #mask > circle {
transform: translate(-393px, -121px);
}
/* ]]> */
</style>
<g class="mask_hover">
<a xlink:href="#">
<image id="img" width="1208" height="604" xlink:href="https://i.stack.imgur.com/LCpGU.jpg"/>
</a>
<!-- we need to move it here so we can target it with our CSS rules -->
<defs>
<mask id="mask">
<circle id="circle_l" cx="809" cy="337" r="202" fill="#fff"/>
</mask>
</defs>
</g>
</svg>
所以您可能还想尝试使用 SMIL,但是您将无法使用 :active
规则,而且 Safari 在实现悬停状态时存在错误...
<svg id="artwork" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1208 604">
<style type="text/css">
/* <![CDATA[ */
.mask_hover a:link,
.mask_hover a:visited {
mask: url(#mask);
}
/* ]]> */
</style>
<defs>
<mask id="mask">
<circle id="circle_r" cx="809" cy="337" r="202" fill="#fff">
<animateTransform attributeName="transform"
attributeType="XML"
type="translate"
to="-393 -121"
dur="0.4s"
fill="freeze"
begin="anchor.mouseover"/>
<animateTransform attributeName="transform"
attributeType="XML"
type="translate"
to="0 0"
dur="0.4s"
fill="freeze"
begin="anchor.mouseout"/>
</circle>
</mask>
</defs>
<g class="mask_hover">
<a xlink:href="#" id="anchor">
<image id="img" width="1208" height="604" xlink:href="https://i.stack.imgur.com/LCpGU.jpg"/>
</a>
</g>
</svg>
所以最终的方法可能是仅使用来自 CSS:
的 clip-path
来实现整个事情
<svg id="artwork" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1208 604">
<style type="text/css">
/* <![CDATA[ */
.mask_hover a image {
transition: clip-path .4s;
}
.mask_hover a {
pointer-events: all;
}
.mask_hover a:link image,
.mask_hover a:visited image{
clip-path: circle(202px at 809px 337px);
}
.mask_hover a:hover image,
.mask_hover a:active image{
clip-path: circle(202px at 416px 216px);
}
/* ]]> */
</style>
<g class="mask_hover">
<a xlink:href="#">
<image id="img" width="1208" height="604" xlink:href="https://i.stack.imgur.com/LCpGU.jpg"/>
<!-- so we can hover everywhre -->
<rect fill="none" width="1208" height="604"/>
</a>
</g>
</svg>
我在一个内联 SVG 中有一个图像,当它悬停在上面时会在两个蒙版之间切换。
但是,CSS 转换不适用于 transition-property: mask;
是否有其他方法可用于 CSS 转换?
我也试过设置样式 <mask>
但似乎无法设置定义元素的样式 (?)。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div style="width: 604px; height: 302px; margin: 20px auto;"> <!-- IE needs width AND height specified to scale the SVG inside correctly. -->
<svg id="artwork" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1208 604">
<style type="text/css">
/* <![CDATA[ */
.mask_hover a:link,
.mask_hover a:visited {
mask: url(#mask_right);
}
.mask_hover a:hover,
.mask_hover a:active {
transition-property: mask;
transition-duration: 0.4s;
transition-timing-function: ease-in-out;
mask: url(#mask_left);
}
/* ]]> */
</style>
<defs>
<mask id="mask_left">
<circle id="circle_l" cx="416" cy="216" r="202" fill="#fff"/>
</mask>
<mask id="mask_right">
<circle id="circle_r" cx="809" cy="337" r="202" fill="#fff"/>
</mask>
</defs>
<g class="mask_hover">
<a xlink:href="#">
<image id="img" width="1208" height="604" xlink:href="https://i.stack.imgur.com/LCpGU.jpg"/>
</a>
</g>
</svg>
</div>
</body>
</html>
图片来源:Pixabay
真的不是mask
属性不能动画,而是url()
要创建过渡,您需要有一个状态 1 到状态 2,并且可以在两个状态之间创建插值。
当您使用 url(#1)
并希望转到 url(#2)
时,无法在这两个状态之间创建任何插值,因为 url(#1.5)
不会是中间状态。
不过可以动画化的是蒙版的内容。
在 SVG2 中,您可以直接设置从 CSS 更改的属性(即 cx
和 cy
),但这仍然仅受 Blink&Safari 浏览器支持:
<svg id="artwork" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1208 604">
<style type="text/css">
/* <![CDATA[ */
.mask_hover a:link,
.mask_hover a:visited {
mask: url(#mask);
}
#mask > circle {
transition-property: cx, cy;
transition-duration: 0.4s;
transition-timing-function: ease-in-out;
}
.mask_hover a:hover + defs #mask > circle,
.mask_hover a:active + defs #mask > circle {
cx: 416;
cy: 216;
}
/* ]]> */
</style>
<g class="mask_hover">
<a xlink:href="#">
<image id="img" width="1208" height="604" xlink:href="https://i.stack.imgur.com/LCpGU.jpg"/>
</a>
<!-- we need to move it here so we can target it with our CSS rules -->
<defs>
<mask id="mask">
<circle id="circle_l" cx="809" cy="337" r="202" fill="#fff"/>
</mask>
</defs>
</g>
</svg>
对于不支持这部分 SVG2 的其他浏览器,您应该可以使用转换 属性 来完成它,但不知何故,Firefox 不接受它...
<svg id="artwork" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1208 604">
<style type="text/css">
/* <![CDATA[ */
.mask_hover a:link,
.mask_hover a:visited {
mask: url(#mask);
}
#mask > circle {
transition-property: transform;
transition-duration: 0.4s;
transition-timing-function: ease-in-out;
}
.mask_hover a:hover + defs #mask > circle,
.mask_hover a:active + defs #mask > circle {
transform: translate(-393px, -121px);
}
/* ]]> */
</style>
<g class="mask_hover">
<a xlink:href="#">
<image id="img" width="1208" height="604" xlink:href="https://i.stack.imgur.com/LCpGU.jpg"/>
</a>
<!-- we need to move it here so we can target it with our CSS rules -->
<defs>
<mask id="mask">
<circle id="circle_l" cx="809" cy="337" r="202" fill="#fff"/>
</mask>
</defs>
</g>
</svg>
所以您可能还想尝试使用 SMIL,但是您将无法使用 :active
规则,而且 Safari 在实现悬停状态时存在错误...
<svg id="artwork" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1208 604">
<style type="text/css">
/* <![CDATA[ */
.mask_hover a:link,
.mask_hover a:visited {
mask: url(#mask);
}
/* ]]> */
</style>
<defs>
<mask id="mask">
<circle id="circle_r" cx="809" cy="337" r="202" fill="#fff">
<animateTransform attributeName="transform"
attributeType="XML"
type="translate"
to="-393 -121"
dur="0.4s"
fill="freeze"
begin="anchor.mouseover"/>
<animateTransform attributeName="transform"
attributeType="XML"
type="translate"
to="0 0"
dur="0.4s"
fill="freeze"
begin="anchor.mouseout"/>
</circle>
</mask>
</defs>
<g class="mask_hover">
<a xlink:href="#" id="anchor">
<image id="img" width="1208" height="604" xlink:href="https://i.stack.imgur.com/LCpGU.jpg"/>
</a>
</g>
</svg>
所以最终的方法可能是仅使用来自 CSS:
的clip-path
来实现整个事情
<svg id="artwork" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 1208 604">
<style type="text/css">
/* <![CDATA[ */
.mask_hover a image {
transition: clip-path .4s;
}
.mask_hover a {
pointer-events: all;
}
.mask_hover a:link image,
.mask_hover a:visited image{
clip-path: circle(202px at 809px 337px);
}
.mask_hover a:hover image,
.mask_hover a:active image{
clip-path: circle(202px at 416px 216px);
}
/* ]]> */
</style>
<g class="mask_hover">
<a xlink:href="#">
<image id="img" width="1208" height="604" xlink:href="https://i.stack.imgur.com/LCpGU.jpg"/>
<!-- so we can hover everywhre -->
<rect fill="none" width="1208" height="604"/>
</a>
</g>
</svg>