Я пытаюсь создать эффект блеска с радиальным градиентом для блока 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), где Rh и Ry — это соответственно горизонтальный радиус и вертикальный радиус нашего эллипса (если оба равны или используется только одно значение, то это круг).
Во-первых, мы удваиваем размер градиента. Этот трюк позволит нам легко настроить положение градиента, используя процентное значение (объяснено здесь: Использование процентных значений с фоновым положением на линейном градиенте)
Если радиус определяется значениями в пикселях, мы сохраняем его, но если он определяется процентным значением, мы делим его на 2, поскольку он относится к размеру, который он увеличил. Если оба радиуса указаны в процентах, мы можем либо разделить оба на 2, либо сохранить их и разделить точки цвета на 2.
Во-вторых, мы удаляем at X Y, что сделает градиент в центре, поэтому нам нужно исправить положение, используя background-position. Понятно, что если бы градиент был на 0 0, нам нужно использовать background-position:100% 100%
Зеленая рамка — это наш фон, в два раза больше, чем элемент (черная рамка), а красный кружок — наш градиент. Регулируя положение фона, мы визуально размещаем градиент на 0 0.
Для любых значений X, Y мы логически будем иметь 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;
I will explain for one axis (X) and the same apply to the other
farthest-side определите радиус как расстояние от центра градиента до самой дальней стороны поля градиента (поле градиента по умолчанию является самим элементом, поскольку мы не определяли размер). Если X является процентным значением, то радиус является максимальным между X и 100% - X, а в преобразованном градиенте радиус будет 50%, поскольку мы находимся в центре. Итак, нам нужно сопоставить первый радиус с 50%*Sx
Если X равно 50%, то Sx должно быть 100%, а если X равно 0 или 100%, то Sx должно быть 200%.
Формула Sx = max(X,100% - X)*2
В этом случае положение проще из-за характера градиента, когда фигура должна касаться одной стороны.
X внутри [0 50%[Px должно быть 100% (right)X равно 50%, любое значение для Px будет работать, поскольку Sx=100%X внутри ]50% 100%]Px должно быть 0% (left)Связанный вопрос: Использование процентных значений с фоновым положением на линейном градиенте
Примеры:
.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-size и background-position. Пример:body {
margin:0;
height:100vh;
background:radial-gradient(farthest-side at 400px 200px,blue 40%,yellow 50%);
}Для closest-side будет действовать та же логика, учитывая Sx=min(X,100% - X)*2, НО мы должны добавить no-repeat и background-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, не поддерживают at (Как заставить работать радиальные градиенты в Safari?)
Автор не просил решения своей проблемы с помощью SVG. Но наверное будет полезно решить один вопрос несколькими способами.
Значения атрибутов градиента были взяты из ответа @Temani Afif.
Формула радиального градиента SVG для этого вопроса:
<radialGradient id = "radGrad" fx = "0%" fy = "5%" r = "200%">
<stop offset = "0%" stop-color = "#FFFFFF" />
<stop offset = "4%" stop-color = "#ffb3ff" />
<stop offset = "12.25%" stop-color = "#ff33ff" />
<stop offset = "31.25%" stop-color = "#800080" />
<stop offset = "50%" stop-color = "#b300b3" />
</radialGradient>
Чтобы анимировать градиент, вы можете использовать любой атрибут, включенный в формулу.
В приведенных ниже примерах будут использоваться атрибуты fx и fy.
Анимация начинается после нажатия на прямоугольник
svg {
width:50%;
height:50%;
}
.txt {
font-family:sans-serif;
font-size:28px;
font-weight:bold;
text-anchor:middle;
fill:#FFDD00;
}<div id = "shine-div">
<svg xmlns = "http://www.w3.org/2000/svg"
xmlns:xlink = "http://www.w3.org/1999/xlink" viewBox = "0 0 400 100">
<defs>
<radialGradient id = "radGrad" fx = "0%" fy = "0%" r = "200%">
<stop offset = "0%" stop-color = "#FFFFFF" />
<stop offset = "4%" stop-color = "#ffb3ff" />
<stop offset = "12.25%" stop-color = "#ff33ff" />
<stop offset = "31.25%" stop-color = "#800080" />
<stop offset = "50%" stop-color = "#b300b3" />
</radialGradient>
</defs>
<g id = "gr1" >
<rect id = "rect1" fill = "url(#radGrad)" x = "5%" y = "5%" width = "95%" height = "95%" rx = "10%"/>
<text class = "txt" x = "50%" y = "60%"> Sun shine </text>
</g>
<animate xlink:href = "#radGrad"
attributeName = "fx"
dur = "3s"begin = "gr1.click"
values = "0%;100%;0%"
repeatCount = "1"
restart = "whenNotActive" />
</svg>
</div>svg {
width:50%;
height:50%;
}
.txt {
font-family:sans-serif;
font-size:28px;
font-weight:bold;
text-anchor:middle;
fill:#FFDD00;
}<div id = "shine-div">
<svg xmlns = "http://www.w3.org/2000/svg"
xmlns:xlink = "http://www.w3.org/1999/xlink" viewBox = "0 0 400 100">
<defs>
<radialGradient id = "radGrad" fx = "48%" fy = "0%" r = "200%">
<stop offset = "0%" stop-color = "#FFFFFF" />
<stop offset = "4%" stop-color = "#ffb3ff" />
<stop offset = "12.25%" stop-color = "#ff33ff" />
<stop offset = "31.25%" stop-color = "#800080" />
<stop offset = "50%" stop-color = "#b300b3" />
</radialGradient>
</defs>
<g id = "gr1" >
<rect id = "rect1" fill = "url(#radGrad)" x = "5%" y = "5%" width = "95%" height = "95%" rx = "10%"/>
<text class = "txt" x = "50%" y = "60%"> Sun shine </text>
</g>
<animate xlink:href = "#radGrad"
attributeName = "fy"
dur = "2s"begin = "gr1.click"
values = "0%;50%;50%;100%;50%;50%;0%"
keyTimes = "0;0.1;0.5;0.6;0.7;0.9;1"
repeatCount = "1"
restart = "whenNotActive" />
</svg>
</div>Одновременно анимируются два атрибута: fx и fy
svg {
width:50%;
height:50%;
}
.txt {
font-family:sans-serif;
font-size:28px;
font-weight:bold;
text-anchor:middle;
fill:#FFDD00;
}<div id = "shine-div">
<svg xmlns = "http://www.w3.org/2000/svg"
xmlns:xlink = "http://www.w3.org/1999/xlink" viewBox = "0 0 400 100">
<defs>
<radialGradient id = "radGrad" fx = "0%" fy = "0%" r = "200%">
<stop offset = "0%" stop-color = "#FFFFFF" />
<stop offset = "4%" stop-color = "#ffb3ff" />
<stop offset = "12.25%" stop-color = "#ff33ff" />
<stop offset = "31.25%" stop-color = "#800080" />
<stop offset = "50%" stop-color = "#b300b3" />
</radialGradient>
</defs>
<g id = "gr1" >
<rect id = "rect1" fill = "url(#radGrad)" x = "5%" y = "5%" width = "95%" height = "95%" rx = "10%"/>
<text class = "txt" x = "50%" y = "60%"> Sun shine </text>
</g>
<animate xlink:href = "#radGrad"
attributeName = "fy"
dur = "2s"begin = "gr1.click"
values = "0%;50%;50%;100%;0%"
keyTimes = "0;0.1;0.5;0.9;1"
repeatCount = "1"
restart = "whenNotActive" />
<animate xlink:href = "#radGrad"
attributeName = "fx"
dur = "2s"begin = "gr1.click"
values = "0%;50%;50%;100%;0%"
keyTimes = "0;0.1;0.5;0.9;1"
repeatCount = "1"
restart = "whenNotActive" />
</svg>
</div>Используя переменные CSS и новый @property, мы можем легко анимировать radial-gradient (или любой градиент). Поддержка пока охватывает только Chrome и Edge.
@property --x {
syntax: '<percentage>';
inherits: false;
initial-value: 0%;
}
#shine-div {
height: 30vh;
width: 60vw;
margin: auto;
border-radius: 10px;
background: radial-gradient(ellipse farthest-corner at var(--x) 0%, #FFFFFF 0%, #ffb3ff 8%, #ff33ff 25%, #800080 62.5%, #b300b3 100%);
animation: colorChange 5s infinite alternate;
}
@keyframes colorChange {
0% {
--x:0%;
}
50% {
--x:50%;
}
100% {
--x:100%;
}
}<div id = "shine-div"></div>Все, что нам нужно сделать, это определить положение с помощью переменной --x, которая будет использовать процентные значения, и мы анимируем эту переменную. Так просто, как, что!