Я пытаюсь понять, возможно ли накапливать анимацию с помощью анимации веб-API, но не могу этого понять.
//move element very fast to 100,100 with no duration
el.animate([{transform: 'translate(100px, 100px)'}], {duration: 0, fill: 'forwards'});
//add another movement after that with duration
el.animate([{transform: 'translateX(200px)'}], {duration: 0, fill: 'forwards', composite: 'accumulate'});
Все происходит правильно, поле перемещается на 100,100, после чего начинается анимация. Проблема в том, что в конце анимации прямоугольники перемещаются вверх, как будто они внезапно потеряли Y-преобразование. Можно ли сохранить преобразование Y в конце? Я думал fill: 'forwards' + composite : 'accumulate'
так и сделаю...
Примечание: время от времени он ведет себя правильно, поэтому я не уверен, что происходит. Ожидаемое поведение
const el = document.querySelector('.box');
el.animate([{transform: 'translate(100px, 100px)'}], {duration: 0, fill: 'forwards'});
el.animate([{transform: 'translateX(200px)'}], {duration: 2000, fill: 'forwards', composite: 'accumulate'});
.container{
display: block;
height: 100vh;
overflow: hidden;
}
.box{
position: absolute;
width: 300px;
height: 200px;
background-color: brown;
}
<div class = "container">
<div class = "box">
</div>
</div>
Кроме того, я не думаю, что это проблема, но вам не хватает закрывающей скобки в translate(100px, 100px
Хороший улов, отредактированный, но ведет себя так же. Что вы подразумеваете под «накоплением», которое не применяется глобально? Какой тогда смысл накапливать?
Я думаю, что для этого вам нужно будет удалить преобразование и установить функцию анимации со свойствами left
и top
.
Как я ясно понимаю из вашего поста и немного его протестировал, вы хотели, чтобы ваш текущий блок оставался в последней позиции, где заканчивается вторая анимация. Функция преобразования, я думаю, немного сложна, поскольку она каким-то образом сбрасывает положение оси Y и по какой-то причине подталкивает ваш блок к верху контейнера.
Я считаю, что лучше работать с обеими анимациями с вышеупомянутыми свойствами.
Я прилагаю вам воспроизводимый пример, в котором, по моему мнению, анимация работает так, как и ожидалось, исходя из того, что вы описали.
Я надеюсь, что это поможет вам в том, что вы ищете.
const el = document.querySelector('.box');
el.animate([{left: '100px', top:'0'}], {duration: 0, fill: 'both'});
el.animate([{left: '200px', top: '100px'}], {duration: 2000, fill: 'both', composite: 'accumulate'});
.container{
display: block;
height: 100vh;
overflow: hidden;
}
.box{
position: absolute;
width: 300px;
height: 100px;
background-color: brown;
}
<div class = "container">
<div class = "box">
</div>
</div>
Да, он вроде как делает то, что я хочу, но на самом деле речь шла не о перемещении коробки, а о возможности «объединять» преобразования с помощью анимации. Это была скорее проверка концепции, чтобы проверить, действительно ли «накопление» объединяется или накапливает преобразования, но я думаю, что это не то, для чего оно было создано.
Я считаю, что встроенная функция Transforms лучше подходит для использования с ключевыми кадрами. Проверьте этот пост: stackoverflow.com/questions/44110205/… он делает то, чего вы хотите достичь, с помощью ключевых кадров CSS-анимации.
Ну, я пытался проверить, стоит ли мне отойти от CSS-анимации и использовать новую «замещающую» анимацию веб-API, которая поддерживает ключевые кадры. Насколько я понимаю, мне нужно вычислить и обновить ключевые кадры, что в некотором роде контрпродуктивно по сравнению с вычислением и применением преобразования непосредственно в коде...
да, я читал, что вы можете значительно сократить время загрузки с помощью анимации веб-API вместо того, чтобы делать это с помощью ключевых кадров CSS.
Насколько я помню, опция composite
не такая уж и умная, она компилирует разные типы преобразований в одно, а больше похоже на конкатенацию строк. Это поведение может измениться в будущем в зависимости от разных поставщиков.
На данный момент вы можете использовать DOMMatrix
для выполнения нужных операций перед анимацией элемента. Это дает вам некоторый контроль над тем, как вы хотите, чтобы «композит» вел себя.
В этом примере я использую библиотеку манипуляций с dom, но вы можете легко получить обещание из нативного Element.animate
через finished
prop. Остальное — получить текущую матрицу преобразования через getComputedStyle
и использовать ее для накопления преобразований через DOMMatrix.prototype
. В этом примере я использую DOMMAtrix.prototype.translateSelf
.
Следует отметить, что при умеренном использовании getComputedStyle в своих сценариях вы обычно делают это посредством опроса/регулирования функции, которая делает позвоните туда. Другой вариант — установить свойство или символ для элемента, который отслеживает текущую DOMMatrix, чтобы вам не приходилось вызывать getComputedStyle.
(async () => {
const el = document.querySelector('.box');
await ch(el).animate([{transform: 'translate(100px, 100px)'}], {duration: 2000, fill: 'forwards'}).promiseAnimate();
const currMatrix = new DOMMatrix(getComputedStyle(el).transform);
ch.animate([{transform: currMatrix.translateSelf(200)}], {duration: 2000, fill: 'forwards'})
})()
.container{
display: block;
height: 100vh;
overflow: hidden;
}
.box{
position: absolute;
width: 300px;
height: 200px;
background-color: brown;
}
<script src = "https://cdn.jsdelivr.net/npm/[email protected]/dist/cahir.0.0.6.evergreen.umd.min.js"></script>
<script src = "https://cdn.jsdelivr.net/npm/[email protected]/collections/DOM/ch.js"></script>
<div class = "container">
<div class = "box">
</div>
</div>
Спасибо, на самом деле я уже получал/устанавливал матрицу и какое-то время думал, что «аккумулировать» на самом деле делает это, а не просто объединяет строки... разочарован этой функцией.
Я не думаю, что
composite: 'accumulate'
применяется глобально, я ожидаю, что стили будут сочетаться только в одном наборе ключевых кадров. Вы уверены, что вам нужны две совершенно разные анимации для одного и того же элемента?