Chrome 不适用于线性渐变的属性偏移动画
Posted
技术标签:
【中文标题】Chrome 不适用于线性渐变的属性偏移动画【英文标题】:Chrome doesn’t work on the animation of the attribute offset for a linear gradient 【发布时间】:2019-11-29 13:14:48 【问题描述】:下面是在Firefox
中运行良好的代码,但是任何尝试在Chrome
中为线性渐变的偏移属性设置动画都没有结果。
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 900 900" >
<defs>
<linearGradient id="bgg" x1="0" y1="0" x2="900" y2="900" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="dodgerblue"/>
<stop offset="52%" stop-color="white">
<animate
attributeName="offset"
values="100%;0%;100%"
dur="4s"
repeatCount="indefinite">
</animate>
</stop>
<stop offset="100%" stop-color="gold">
<animate
attributeName="offset"
values="100%;50%;100%"
dur="4s"
repeatCount="indefinite">
</animate>
</stop>
</linearGradient>
</defs>
<rect x="50" y="50" rx="5%" fill="url(#bgg)" />
</svg>
也尝试使用gradientUnits =" objectBoundingBox "
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 900 900" >
<defs>
<linearGradient id="bgg" x1="0%" y1="0%" x2="100%" y2="100%" gradientUnits="objectBoundingBox">
<stop offset="0%" stop-color="dodgerblue"/>
<stop offset="52%" stop-color="white">
<animate
attributeName="offset"
values="100%;0%;100%"
dur="4s"
repeatCount="indefinite">
</animate>
</stop>
<stop offset="100%" stop-color="gold">
<animate
attributeName="offset"
values="100%;50%;100%"
dur="4s"
repeatCount="indefinite">
</animate>
</stop>
</linearGradient>
</defs>
<rect x="50" y="50" rx="5%" fill="url(#bgg)" />
</svg>
此问题的任何解决方案都可以使用:SVG
,css
,javascript
【问题讨论】:
报告给 Chrome 的 bugtracker。 对纯 CSS 动画感兴趣? @Temani Afif 我期待你解决 CSS,但我对动画的确切属性很感兴趣offset
很难做到完全相同,但我们可以这样近似:jsfiddle.net/d6kbvx1n ...我很确定我们可以做得更好,但它需要更精确的值.
@Temani Afif 请在此处发布您的 CSS 解决方案。
【参考方案1】:
对此的一种解决方案是使用浮点数而不是百分比,即values="1;0;1"
而不是values="100%;0%;100%"
svgborder:1px solid
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 900 900" >
<defs>
<linearGradient id="bgg" x1="0" y1="0" x2="50%" y2="50%" gradientUnits="userSpaceOnUse">
<stop offset="0" stop-color="dodgerblue"/>
<stop offset=".52" stop-color="white">
<animate
attributeName="offset"
values="1;0;1"
dur="4s"
repeatCount="indefinite">
</animate>
</stop>
<stop offset="1" stop-color="gold">
<animate
attributeName="offset"
values="1;.5;1"
dur="4s"
repeatCount="indefinite">
</animate>
</stop>
</linearGradient>
</defs>
<rect x="50" y="50" rx="5%" fill="url(#bgg)" />
</svg>
【讨论】:
一个有趣的解决方案谢谢!令人惊讶的是,values =" 1; .5; 1 "
在 gradientUnits =" userSpaceOnUse "
时有效【参考方案2】:
您可以随时使用javascript
:
requestAnimationFrame(animateOffsets);
// if this function called as callback of requestAnimationFrame,
// so there are first argument is the time from beginning from scene start
function animateOffsets(t)
requestAnimationFrame(animateOffsets);
t = t%5000/5000; // will change from 0 to 1 (5 sec)
t = Math.sin(t*Math.PI*2); // will change from -1 to 1
stop1.setAttribute('offset', `$50 + t*50%`);
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 900 900" >
<defs>
<linearGradient id="bgg" x1="0" y1="0" x2="60%" y2="60%" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="dodgerblue"/>
<stop offset="50%" stop-color="white" id="stop1"/>
<stop offset="100%" stop-color="gold"/>
</linearGradient>
</defs>
<rect x="50" y="50" rx="5%" fill="url(#bgg)" />
</svg>
【讨论】:
我喜欢你使用Math.sin()
这一事实。它使动画更流畅。
@enxaneta 我也喜欢在这里使用缓动函数gist.github.com/gre/1650294【参考方案3】:
这是一个仅使用 CSS 的想法,您可以依靠两个渐变和一个平移/不透明度动画来近似它。我还考虑了一点模糊效果,以便在渐变之间有更好的过渡。
.box
border-radius:20px;
width:200px;
height:200px;
position:relative;
z-index:0;
overflow:hidden;
.box:before,
.box:after
content:"";
position:absolute;
bottom:0;
right:0;
width:220%;
height:220%;
animation:translate 2s infinite linear alternate;
.box:after
background:
linear-gradient(to bottom right,dodgerblue 0%,white 40%,gold 60%);
animation-name:translate,show;
opacity:0;
.box:before
background:
linear-gradient(to bottom right,dodgerblue,white 50%,gold 50%);
animation-name:translate,fade;
@keyframes translate
from
transform:translate(48%,48%);
@keyframes show
30%,85%
opacity:1;
@keyframes fade
30%,85%
filter:blur(8px);
<div class="box">
</div>
【讨论】:
【参考方案4】:渐变属性offset
动画作为背景图片
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 900 900" >
<linearGradient id="bgg" x1="479" y1="-345" x2="479" y2="853" gradientUnits="userSpaceOnUse">
<stop offset="0%" stop-color="#fff">
<animate
attributeName="offset"
values="0;1;1;0;0"
dur="5s"
repeatCount="indefinite"
></animate>
</stop>
<stop offset="100%" stop-color="gold">
<animate
attributeName="offset"
values="0;1;1;0;0"
dur="5s"
repeatCount="indefinite"
></animate>
</stop>
</linearGradient>
<rect x="-45" y="0" rx="5%" fill="#ACA900" />
<rect x="65" y="80" rx="5%" fill="url(#bgg)" />
<image x="30" y="100" xlink:href="https://upload.wikimedia.org/wikipedia/commons/f/fd/Ghostscript_Tiger.svg" />
</svg>
径向渐变效果
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 900 900" >
<radialGradient id="myRadial"
fx="50%" fy="50%" r="80%">
<stop offset="0%" stop-color="gold">
<animate
attributeName="offset"
values="0;1.3;0"
dur="5s"
repeatCount="indefinite"
></animate>
</stop>
<stop offset="100%" stop-color="#EDEDED">
<animate
attributeName="offset"
values="0;1.3;1.3;0;0"
dur="5s"
repeatCount="indefinite"
></animate>
</stop>
</radialGradient>
<rect x="0" y="0" rx="5%" fill="#ACC400" />
<rect x="85" y="80" rx="5%" fill="url(#myRadial)" />
</svg>
【讨论】:
以上是关于Chrome 不适用于线性渐变的属性偏移动画的主要内容,如果未能解决你的问题,请参考以下文章