如何将动画渐变添加到 svg 路径?

Posted

技术标签:

【中文标题】如何将动画渐变添加到 svg 路径?【英文标题】:How to add animated gradient to an svg path? 【发布时间】:2019-03-19 14:08:36 【问题描述】:

我有一个这样的心脏 svg 路径:

<svg viewBox="0 0 100 100">
<path className="" d="M20,31 C15.4189994,27.2225585 12.5023327,24.2225585 11.25,22 C10.2743515,20.6156479 10,19.6181623 10,18.1428571 C10,15.5113854 12.4883456,13 15,13 C17.3176009,13 18.9621484,13.8491346 20,15.5714286 C21.0382977,13.8491346 22.6828452,13 25,13 C27.5116544,13 30,15.5113854 30,18.1428571 C30,19.6181623 29.7256485,20.6156479 28.75,22 C27.497816,24.2225585 24.5811493,27.2225585 20,31 Z" />
</svg>

我还想在上面加个渐变效果,把渐变从左向右移动,仿佛心在闪烁。

但是,path 不接受 background 属性,如果我使用 fill,它不接受渐变作为值。它也没有background-position 属性(因此我可以使用@keyframesbackground-position 从左向右移动)。

有没有办法做到这一点?

【问题讨论】:

只是一个想法:jsfiddle.net/qraskdyg/1 这可能对developer.mozilla.org/en-US/docs/Web/SVG/Element/clipPath有帮助 【参考方案1】:

您可以使用SMIL animation of SVG。这个想法是为颜色停止或渐变的偏移设置动画以创建所需的效果:

svg 
 border:1px solid;
 width:200px;
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 
   viewBox="10 10 24 24">
    <defs>
        <linearGradient id="linear-gradient" x1="-100%" y1="0" x2="200%" y2="0" >
            <stop offset="0" stop-color="red">
               <animate attributeName="offset" values="0;0.2;0.5" dur="2s" repeatCount="indefinite"  /> 
            </stop>
            <stop offset="0.5" stop-color="yellow">
                <animate attributeName="offset" values="0.5;0.7;0.8;1" dur="2s" repeatCount="indefinite"  /> 
            </stop>
        </linearGradient>
    </defs>
<path fill="url(#linear-gradient)" d="M20,31 C15.4189994,27.2225585 12.5023327,24.2225585 11.25,22 C10.2743515,20.6156479 10,19.6181623 10,18.1428571 C10,15.5113854 12.4883456,13 15,13 C17.3176009,13 18.9621484,13.8491346 20,15.5714286 C21.0382977,13.8491346 22.6828452,13 25,13 C27.5116544,13 30,15.5113854 30,18.1428571 C30,19.6181623 29.7256485,20.6156479 28.75,22 C27.497816,24.2225585 24.5811493,27.2225585 20,31 Z" />
</svg>

动画颜色:

svg 
 border:1px solid;
 width:200px;
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" 
   viewBox="10 10 24 24">
    <defs>
        <linearGradient id="linear-gradient" x1="0" y1="0" x2="100%" y2="0" >
            <stop offset="0" stop-color="red">
               <animate attributeName="stop-color" values="yellow;red" dur="2s" repeatCount="indefinite"  /> 
            </stop>
            <stop offset="1" stop-color="yellow">
                <animate attributeName="stop-color" values="red;yellow" dur="2s" repeatCount="indefinite"  /> 
            </stop>
        </linearGradient>
    </defs>
<path fill="url(#linear-gradient)" d="M20,31 C15.4189994,27.2225585 12.5023327,24.2225585 11.25,22 C10.2743515,20.6156479 10,19.6181623 10,18.1428571 C10,15.5113854 12.4883456,13 15,13 C17.3176009,13 18.9621484,13.8491346 20,15.5714286 C21.0382977,13.8491346 22.6828452,13 25,13 C27.5116544,13 30,15.5113854 30,18.1428571 C30,19.6181623 29.7256485,20.6156479 28.75,22 C27.497816,24.2225585 24.5811493,27.2225585 20,31 Z" />
</svg>

另一个想法是考虑掩码内的路径,然后运行 ​​CSS 动画来轻松地为背景属性设置动画:

svg 
  border: 1px solid;
  width: 200px;


.box 
  width:200px;
  height:200px;
  background:linear-gradient(to right,red,green,blue) left/200% 100%;
  -webkit-mask:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg"  viewBox="10 10 24 24"><path  d="M20,31 C15.4189994,27.2225585 12.5023327,24.2225585 11.25,22 C10.2743515,20.6156479 10,19.6181623 10,18.1428571 C10,15.5113854 12.4883456,13 15,13 C17.3176009,13 18.9621484,13.8491346 20,15.5714286 C21.0382977,13.8491346 22.6828452,13 25,13 C27.5116544,13 30,15.5113854 30,18.1428571 C30,19.6181623 29.7256485,20.6156479 28.75,22 C27.497816,24.2225585 24.5811493,27.2225585 20,31 Z" /></svg>') center/contain;
          mask:url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg"  viewBox="10 10 24 24"><path  d="M20,31 C15.4189994,27.2225585 12.5023327,24.2225585 11.25,22 C10.2743515,20.6156479 10,19.6181623 10,18.1428571 C10,15.5113854 12.4883456,13 15,13 C17.3176009,13 18.9621484,13.8491346 20,15.5714286 C21.0382977,13.8491346 22.6828452,13 25,13 C27.5116544,13 30,15.5113854 30,18.1428571 C30,19.6181623 29.7256485,20.6156479 28.75,22 C27.497816,24.2225585 24.5811493,27.2225585 20,31 Z" /></svg>') center/contain;
          
   animation:change 2s infinite linear alternate;

@keyframes change 
  to 
    background-position:right;
  
<div class="box">
</div>

获取有关背景计算的更多详细信息的相关问题:Using percentage values with background-position on a linear-gradient

【讨论】:

实用提示 - 使用 fakeSMIL js 库使其与 IE/Edge 兼容 虽然不循环。结束与重新开始之间总是有一个跳跃。 @aviya.developer 它不是循环播放的。跳跃是设计使然。我只展示了使用 SVG 的不同技术。 @TemaniAfif 你通常用什么来制作短动画?像预加载器等?我已经涉足 svg,但到目前为止还没有证明它很舒服。 @aviya.developer 这取决于您要实现的动画。没有通用的解决方案

以上是关于如何将动画渐变添加到 svg 路径?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 flyto 传单功能添加到自定义 Svg 地图

如何使用 SVG 滤镜创建透明渐变蒙版

如何将 svg 路径变形动画合并到 React 应用程序中

我可以沿 SVG 路径应用渐变吗?

SVG 动画精髓

SVG 动画精髓