css - 如何使用CSS为径向渐变设置动画?

标签 css svg css-animations radial-gradients

我正在尝试为div框创建放射状渐变光泽效果,但我不确定这样做的最佳方法是什么。我没有发现实现我想要实现的目标的资源;只是光泽会影响看起来像叠加的效果。

我发现的大多数示例看起来都是这样的http://jsfiddle.net/nqQc7/512/

下面,我显示了我要创建的内容。



#shine-div {
  height: 30vh;
  width: 60vw;
  margin-right: auto;
  margin-left: auto;
  border-radius: 10px;
  /*background: radial-gradient(ellipse farthest-corner at right top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 25%, #800080 62.5%, #b300b3 100%);*/
  display: flex;
  justify-content: center;
  align-items: center;
  color: white;
  font-weight: bold;
  animation: colorChange 5s infinite;
}

@keyframes colorChange {
  0% {
    background: radial-gradient(ellipse farthest-corner at left top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 25%, #800080 62.5%, #b300b3 100%)
  }
  50% {
    background: radial-gradient(ellipse farthest-corner at top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 25%, #800080 62.5%, #b300b3 100%)
  }
  100% {
    background: radial-gradient(ellipse farthest-corner at right top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 25%, #800080 62.5%, #b300b3 100%)
  }
}

<div id="shine-div">
  Shine
</div>





是否有可能做到这一点?我还想使白色的光晕在顶部平滑地从左向右移动吗?我的尝试是否在正确的轨道上?

最佳答案

您可以不同地进行渐变并为位置设置动画。诀窍是将渐变的大小加倍,并使色标的值停止为实际值的一半,以便保持相同的视觉渐变,然后可以从左到右对其进行动画处理。

由于计算了最远的角,因此它看起来与您在动画中定义的渐变不完全相同。



#shine-div {
  height: 30vh;
  width: 60vw;
  margin-right: auto;
  margin-left: auto;
  border-radius: 10px;
  background: radial-gradient(farthest-corner at top, #FFFFFF 0%, #ffb3ff 4%, #ff33ff 12.25%, #800080 31.25%, #b300b3 50%) top right/200% 200%;
  display: flex;
  justify-content: center;
  align-items: center;
  color: white;
  font-weight: bold;
  animation: colorChange 5s infinite alternate;
}

@keyframes colorChange {
  to {
    background-position:top left;
  }
 }

<div id="shine-div">
  Shine
</div>







为了更接近您的渐变,您还必须为background-size设置动画(有关计算的详细信息,请参见下文)



#shine-div {
  height: 30vh;
  width: 60vw;
  margin-right: auto;
  margin-left: auto;
  border-radius: 10px;
  background: radial-gradient(farthest-corner at top, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 24.5%, #800080 62.5%, #b300b3 100%);
  display: flex;
  justify-content: center;
  align-items: center;
  color: white;
  font-weight: bold;
  animation: colorChange 5s infinite alternate linear;
}

@keyframes colorChange {
  from { /* radial-gradient(farthest-corner at top right, ..) */
    background-position:left top;
    background-size:200% 100%;
  
  }
  49.9% {
    background-position:left top;  
  }
  50% { /* radial-gradient(farthest-corner at top center, ..) */
    background-size:100% 100%;
  }
  50.1% {
    background-position:right top; 
  }
  to { /* radial-gradient(farthest-corner at top left, ..) */
    background-position:right top;
    background-size:200% 100%;
  }
 }

<div id="shine-div">
  Shine
</div>





您还可以考虑使用伪元素进行相同的动画,并进行变换以提高性能:



#shine-div {
  height: 30vh;
  width: 60vw;
  margin-right: auto;
  margin-left: auto;
  border-radius: 10px;
  display: flex;
  justify-content: center;
  align-items: center;
  color: white;
  font-weight: bold;
  overflow:hidden;
  position:relative;
  z-index:0;
}
#shine-div:before {
  content:"";
  position:absolute;
  z-index:-1;
  top:0;
  left:0;
  width:400%;
  height:200%;
  background: radial-gradient(farthest-corner at top, #FFFFFF 0%, #ffb3ff 4%, #ff33ff 12.25%, #800080 31.25%, #b300b3 50%);
  animation: colorChange 5s infinite alternate linear;
}

@keyframes colorChange {
  from {
    transform:translateX(-50%);
  }
  50% {
    transform:scaleX(0.75) translateX(-50%)
  }
  to {
    transform:translateX(-25%);
  }
 }

<div id="shine-div">
  Shine
</div>









更深入

为了使答案更通用,我将详细说明如何从两个不同的位置为任何渐变设置动画。主要技巧是以不同的方式编写渐变,以使其定义为常数(radial-gradient(<constant_definition>)并为background-position(在某些情况下为background-size)设置动画。

让我们考虑我们的渐变为background:radial-gradient(Rh Rv at X Y, color1 p1, color2 p2),其中RhRy分别是椭圆的水平半径和垂直半径(如果两者相等或仅使用一个值,则为圆)。

首先,我们将渐变大小加倍。这个技巧将使我们能够轻松地使用百分比值(在这里解释Using percentage values with background-position on a linear gradient)来调整渐变的位置

如果半径是用像素值定义的,则将其保留,但如果半径是用百分比值定义的,则将其除以2,因为它是相对于他增大的大小而言的。如果两个半径均以百分比表示,我们既可以将它们都除以2,也可以保留它们,然后将色标除以2。

第二,我们删除at X Y,它将使渐变出现在中心,因此我们需要使用background-position校正位置。显然,如果渐变为0 0,则需要使用background-position:100% 100%

enter image description here

绿色框是我们背景的两倍,是元素(黑色框)的两倍,红色圆圈是我们的渐变。通过调整背景位置,我们可以将渐变直观地定位在0 0处。

对于任何XY值,我们在逻辑上将具有background-position:calc(100% - X) calc(100% - Y)

如果X,Y是像素值,我们也可以使用background-position: right -X bottom -Y(请注意,它是-X而不是- X,我们使用负值)

例子:

带像素值



.box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
}

<div class="box" style="background:radial-gradient(20% 100px at 20px 30px,red 30%,blue 60%);"></div>
<div class="box" style="background:radial-gradient(10% 100px,red 30%,blue 60%) right -20px bottom -30px/200% 200%;"></div>
<br>
<div class="box" style="background:radial-gradient(40% 40% at 40px 50px,yellow 30%,blue);"></div>
<div class="box" style="background:radial-gradient(40% 40%,yellow 15%,blue 50%) right -40px bottom -50px/200% 200%;"></div>
<div class="box" style="background:radial-gradient(20% 20%,yellow 30%,blue) right -40px bottom -50px/200% 200%;"></div>





有百分比值



.box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
}

<div class="box" style="background:radial-gradient(20% 100px at 50% 10%,red 30%,blue 60%);"></div>
<div class="box" style="background:radial-gradient(10% 100px,red 30%,blue 60%) calc(100% - 50%) calc(100% - 10%)/200% 200%;"></div>
<br>
<div class="box" style="background:radial-gradient(40% 40% at 30% 70%,yellow 30%,blue);"></div>
<div class="box" style="background:radial-gradient(40% 40%,yellow 15%,blue 50%) calc(100% - 30%) calc(100% - 70%)/200% 200%;"></div>
<div class="box" style="background:radial-gradient(20% 20%,yellow 30%,blue) calc(100% - 30%) calc(100% - 70%)/200% 200%;"></div>





因此,如果我们想从以下对象制作动画:

radial-gradient(Rh Rv at X Y, color1 p1, color2 p2)




radial-gradient(Rh Rv at X1 Y2, color1 p1, color2 p2)


我们以不同的方式编写它,并为background-position设置动画:



.box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
}
.first {
  background:radial-gradient(10% 100px,red 30%,blue 60%) calc(100% - 50%) calc(100% - 10%)/200% 200%;
  animation:change1 2s linear infinite alternate;
}
.second {
  background:radial-gradient(20% 20%,yellow 30%,blue)right -50px bottom 0/200% 200%;
  animation:change2 2s linear infinite alternate;
}

@keyframes change1 {
  to {
    background-position:calc(100% + 10%) calc(100% - 80%);
  }
}

@keyframes change2 {
  to {
    background-position:right -100px bottom -100px;
  }
}

<div class="box first" ></div>
<div class="box second"></div>







现在,让我们考虑更棘手的情况,例如我们的初始示例,使用farthest-side来定义大小。我们将执行相同的逻辑并转换

radial-gradient(farthest-side at X Y, color1 p1, color2 p2);




radial-gradient(farthest-side, color1 p1, color2 p2) Px Py/Sx Sy no-repeat;


我将解释一个轴(X),同样适用于另一轴

farthest-side定义半径为从渐变中心到渐变框最远端的距离(默认情况下,渐变框是元素本身,因为我们没有定义任何大小)。如果X是百分比值,则半径是X100% - X之间的最大值,并且在变换的渐变中,由于我们位于中心,因此半径将是50%。因此,我们需要将第一个半径与50%*Sx匹配

如果X50%,则Sx应该是100%,如果X0100%,则Sx应该是200%

公式是Sx = max(X,100% - X)*2

在这种情况下,由于渐变的性质(形状应接触一侧),位置更容易


如果X [0 50%[中的Px应该是100%right
如果X50%,则Px的任何值都将起作用,因为Sx=100%
如果X ]50% 100%]内的Px应该是0%left


相关问题:Using percentage values with background-position on a linear gradient

例子:



.box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
}

<div class="box" style="background:radial-gradient(farthest-side at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(farthest-side, red 20%, blue 100%, yellow 50%) 100% 0/calc(80%*2) calc(60%*2)"></div>
<br>
<div class="box" style='background:radial-gradient(farthest-side at 22% 100%,red 40%, blue 100%,yellow 100%)'></div>
<div class="box" style="background:radial-gradient(farthest-side,red 40%, blue 100%,yellow 100%) 100% 0/calc(78%*2) calc(100%*2)"></div>





对于farthest-corner,我们执行完全相同的操作:



.box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
}

<div class="box" style="background:radial-gradient(farthest-corner at 20% 60%, red 20%, blue 50%, yellow 60%)" ></div>
<div class="box" style="background:radial-gradient(farthest-corner, red 20%, blue 50%, yellow 60%) 100% 0%/calc(80%*2) calc(60%*2)"></div>
<br>
<div class="box" style="background:radial-gradient(farthest-corner at 40% 100%, red 20%, blue 50%, yellow 60%)" ></div>
<div class="box" style="background:radial-gradient(farthest-corner, red 20%, blue 50%, yellow 60%) 100% 0%/calc(60%*2) calc(100%*2)"></div>





我们也可以将farthest-side(或farthest-corner)转换为Rh Rv并进行先前的计算,但是它对于动画没有用,因为我们将具有两个半径不同的渐变,而我们需要相同的渐变。



.box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
}

<div class="box" style="background:radial-gradient(farthest-side at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(80% 60% at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(80% 60%, red 10%, blue 50%, yellow 50%) 80% 40%/200% 200%"></div>





如果X是像素值,则有两种情况:


元素具有固定的宽度:在这种情况下,我们可以简单地将X的像素值转换为宽度的百分比,并执行与上述相同的逻辑。
元素具有可变的宽度:在这种情况下,转换渐变非常困难(可能是不可能的),因为形状会根据宽度而变化。当width-X > X时,我们将有一个可变的半径,而当width-X < X时,我们将有一个固定的半径。我认为我们无法使用background-sizebackground-position来表达这一点。例:




body {
  margin:0;
  height:100vh;
  background:radial-gradient(farthest-side at 400px 200px,blue 40%,yellow 50%);
}





考虑到closest-sideSx=min(X,100% - X)*2会执行相同的逻辑,但是我们应该添加no-repeatbackground-color等于渐变中的最后一种颜色,因为尺寸小于100%



.box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
}

<div class="box" style="background:radial-gradient(closest-side at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(closest-side, red 20%, blue 100%, yellow 100%) 0 100%/calc(20%*2) calc(40%*2)"></div>
<div class="box" style="background:radial-gradient(closest-side, red 20%, blue 100%, yellow 100%) 0 100%/calc(20%*2) calc(40%*2) no-repeat,yellow"></div>
<br>
<div class="box" style='background:radial-gradient(closest-side at 22% 10%,red 40%, blue 100%,yellow 100%)'></div>
<div class="box" style="background:radial-gradient(closest-side,red 40%, blue 100%,yellow 100%) 0 0/calc(22%*2) calc(10%*2)"></div>
<div class="box" style="background:radial-gradient(closest-side,red 40%, blue 100%,yellow 100%) 0 0/calc(22%*2) calc(10%*2) no-repeat,yellow"></div>





我们可以对closest-corner执行相同的操作,但是由于渐变会使渐变框溢出,因此我们会遇到一些问题。



.box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
}

<div class="box" style="background:radial-gradient(closest-corner at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(closest-corner, red 20%, blue 100%, yellow 100%) 0 100%/calc(20%*2) calc(40%*2)"></div>
<div class="box" style="background:radial-gradient(closest-corner, red 20%, blue 100%, yellow 100%) 0 100%/calc(20%*2) calc(40%*2) no-repeat,yellow"></div>









为了纠正这一点,我们可以将色标除以2,以确保将整个渐变保留在内部。然后我们将尺寸增大两倍,并调整位置



.box {
  height:150px;
  width:150px;
  border:1px solid;
  display:inline-block;
}

<div class="box" style="background:radial-gradient(closest-corner at 20% 60%, red 20%, blue 100%, yellow 100%)" ></div>
<div class="box" style="background:radial-gradient(closest-corner, red 10%, blue 50%, yellow 50%) -100% 33%/calc(20%*4) calc(40%*4)"></div>
<div class="box" style="background:radial-gradient(closest-corner, red 10%, blue 50%, yellow 50%) -100% 33%/calc(20%*4) calc(40%*4) no-repeat,yellow"></div>
<br>
<div class="box" style='background:radial-gradient(closest-corner at 22% 10%,red 40%, blue 100%,yellow 100%)'></div>
<div class="box" style="background:radial-gradient(closest-corner,red 20%, blue 50%,yellow 50%) -100% 0%/calc(22%*4) calc(10%*4)"></div>
<div class="box" style="background:radial-gradient(closest-corner,red 20%, blue 50%,yellow 50%) -164% -18%/calc(22%*4) calc(10%*4) no-repeat,yellow"></div>











即使没有动画,也更支持不带at X Y的渐变语法。某些浏览器(如Safari)不支持atHow to make radial gradients work in Safari?

关于css - 如何使用CSS为径向渐变设置动画?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58718140/

相关文章:

html - 如何通过将鼠标悬停在不同的元素上来激活元素上的 CSS 动画?

javascript - 如何更改已经显示的 Bootstrap 弹出窗口的内容?

java - 使用 Apache Batik 调整 svg 文件大小时内存不足

css - 如果已经在应用动画的类中声明了某个属性,那么从 CSS 动画的 `0%` 关键帧中删除该属性是否安全?

css - SVG 无法在 Firefox 中呈现(最新版本)

javascript - 使用 d3.js 的 svg View 框 : space above graph is still too large

javascript - 从中断的地方重新启动 CSS3 动画?

javascript - 在事件目标上添加 css tilde 从 element1 到 element2

jquery - 如何在不缩放内容的情况下缩放 div

css - Bootstrap 下拉菜单不支持悬停时的单个元素