Я пытаюсь добиться какого-то Степпера. Все работает хорошо, за исключением перехода на заливке.
let step = 0;
document.querySelector("button").addEventListener('click', () => {
step++;
document.querySelector("svg").style.fill = `url(#lg-step-${step})`
})
.stepper {
transition-property: fill;
transition-duration: 1s;
transition-timing-function: ease-in-out;
}
<svg id = "test_svg" viewBox = "0 0 620 50" width = "300" height = "20" fill = "url(#lg-step-0)" stroke = "black" stroke-width = "1" class = "stepper">
<path d = "m 71 29 h -60 c -14 0 -14 -19 0 -19 h 60 c 6 -10 19 -10 25 0 h 200 c 6 -10 19 -10 25 0 h 200 c 6 -10 19 -10 25 0 h 60 c 14 0 14 19 0 19 h -60 c -6 10 -19 10 -25 0 h -200 c -6 10 -19 10 -25 0 h -200 c -6 10 -19 10 -25 0" />
<linearGradient id = "lg-step-0">
<stop offset = "0%" stop-color = "blue" />
<stop offset = "6%" stop-color = "blue" stop-opacity = "60%" />
<stop offset = "6%" stop-color = "transparent" />
</linearGradient>
<linearGradient id = "lg-step-1" >
<stop offset = "0%" stop-color = "blue" />
<stop offset = "14%" stop-color = "blue" stop-opacity = "60%"/>
<stop offset = "14%" stop-color = "transparent" />
</linearGradient>
<linearGradient id = "lg-step-2">
<stop offset = "0%" stop-color = "blue" />
<stop offset = "50%" stop-color = "blue" stop-opacity = "60%" />
<stop offset = "50%" stop-color = "transparent" />
</linearGradient>
<linearGradient id = "lg-step-3">
<stop offset = "0%" stop-color = "blue" />
<stop offset = "87%" stop-color = "blue" stop-opacity = "60%" />
<stop offset = "87%" stop-color = "transparent" />
</linearGradient>
</svg>
<button> Next step </button>
Весь js здесь взят не из моего реального кода, а для целей тестирования на SO.
Я хотел бы добиться плавного перехода между всеми моими шагами, но, как вы можете видеть, ни один переход никогда не срабатывает. Любая помощь приветствуется.
P.S. На самом деле я работаю над Blazor, поэтому чем меньше J, тем лучше решение.
МСП? Но хорошая идея, попробую после обеда
Эксперт по предметной области ☺ - stackoverflow.com/questions/7850915/svg-animate-gradient-stop
@Symtox, это может быть полезно codepen.io/chirag0456/pen/KKjVdbR
transition
может интерполировать только между числами какого-либо типа, а не между строками, и уж точно не в том случае, если это ссылки на полные поддеревья DOM.
На самом деле вы хотите интерполировать значения атрибута offset
элемента <stop>
. Это возможно, но не с помощью CSS. В SVG есть два типа атрибутов: атрибуты чистого XML и «атрибуты представления», где вы можете записать их как атрибуты или как свойства CSS. Только второй доступен с помощью переходов CSS.
offset
относится к первой категории. Его можно анимировать, но только с помощью SMIL-анимации. Результат громоздкий, но работает.
let step = 0;
document.querySelector("button").addEventListener('click', () => {
step++;
document.querySelectorAll(`.lg-step-${step}`).forEach(el => {
el.beginElement();
})
})
<svg id = "test_svg" viewBox = "0 0 620 50" width = "300" height = "20" fill = "url(#lg-step-0)" stroke = "black" stroke-width = "1" class = "stepper">
<path d = "m 71 29 h -60 c -14 0 -14 -19 0 -19 h 60 c 6 -10 19 -10 25 0 h 200 c 6 -10 19 -10 25 0 h 200 c 6 -10 19 -10 25 0 h 60 c 14 0 14 19 0 19 h -60 c -6 10 -19 10 -25 0 h -200 c -6 10 -19 10 -25 0 h -200 c -6 10 -19 10 -25 0" />
<linearGradient id = "lg-step-0">
<stop offset = "0%" stop-color = "blue" />
<stop offset = "6%" stop-color = "blue" stop-opacity = "60%">
<animate class = "lg-step-1" attributeName = "offset" from = ".06" to = ".14"
begin = "indefinite" dur = "1s" fill = "freeze"
calcMode = "spline" keySplines = "0.42, 0, 0.58, 1" />
<animate class = "lg-step-2" attributeName = "offset" from = ".14" to = ".5"
begin = "indefinite" dur = "1s" fill = "freeze"
calcMode = "spline" keySplines = "0.42, 0, 0.58, 1" />
<animate class = "lg-step-3" attributeName = "offset" from = ".5" to = ".87"
begin = "indefinite" dur = "1s" fill = "freeze"
calcMode = "spline" keySplines = "0.42, 0, 0.58, 1" />
</stop>
<stop offset = "6%" stop-color = "transparent">
<animate class = "lg-step-1" attributeName = "offset" from = ".04" to = ".14"
begin = "indefinite" dur = "1s" fill = "freeze"
calcMode = "spline" keySplines = "0.42, 0, 0.58, 1" />
<animate class = "lg-step-2" attributeName = "offset" from = ".14" to = ".50"
begin = "indefinite" dur = "1s" fill = "freeze"
calcMode = "spline" keySplines = "0.42, 0, 0.58, 1" />
<animate class = "lg-step-3" attributeName = "offset" from = ".5" to = ".87"
begin = "indefinite" dur = "1s" fill = "freeze"
calcMode = "spline" keySplines = "0.42, 0, 0.58, 1" />
</stop>
</linearGradient>
</svg>
<button> Next step </button>
Когда я нажимаю Next Step
, ничего не происходит, это моя машина или проблема с кодом?
Протестировано с Firefox 128 в Linux. Хром 126 не работает, теперь вижу. Я догадываюсь, что это такое, попробую...
Я разочаровался, когда нажал кнопку «Далее» на Chrome lmao. Отлично работает на firefo, огромное спасибо за отправную точку!!
Работает сейчас. В Chromium нужны безразмерные значения, проценты не работают (.14
вместо 14%
). Я не знал об этом баге.
Ты просто сделал мой день, еще раз спасибо
Кстати, я пытаюсь «сделать это по-своему», но откуда это begin
? он даже не упоминается в MDN, есть ли у вас более надежный источник по этой теме (кроме спецификации 2 тыс. строк?)
AnimationElement.beginElement()
.
Это сложно, но управление временем стоит прочитать, потому что SMIL имеет больше возможностей, чем CSS-анимация/переходы. Однако обратите внимание, что wallclock-sync-value
не реализован ни в одном браузере.
Я не малый и средний бизнес, но не думаю, что вы анимируете
fill
, необходимый для анимации размера/положения градиента.