Как получить позицию элемента после анимации css (vanilla js) - PullRequest
0 голосов
/ 04 июня 2018

Я работаю над проектом, включающим несколько анимаций, и, хотя большинство из них легко сделать с помощью анимации ключевых кадров css, другим требуется javascript, и я немного разбираюсь в том, как их выполнять.Я сделаю все возможное, чтобы описать то, что я не могу показать в скрипке (я кодирую то, что в видео показано на демоверсии).

На странице есть несколько разделов, каждый из которых имеет различные элементы, исчезающиевход и выход, вращение и т. д. Когда каждая секция прокручивается до вида, к ней добавляется класс «animate» для запуска анимации css, одним из которых является элемент svg, спускающийся с севера области просмотра до нижней части области просмотра, гдеэто парки.Но затем, когда пользователь продолжает прокручивать вниз, мне нужно анимировать этот элемент svg вне поля зрения к югу от области просмотра, а затем повторно войти, когда следующий раздел прокручивается в поле зрения.Поэтому я пытаюсь получить положение (vanilla js, пожалуйста) элемента в функции findSection, когда он припаркован, то есть после завершения анимации ключевого кадра , но методы, которые я пробовал до сих пор, получаютвместо предварительной анимации позиции.Как я могу получить текущую позицию абсолютно позиционированного элемента после , который был анимирован с помощью CSS?И я не сомневаюсь, что в целом подход лучше, чем то, что я делаю до сих пор, особенно если я могу использовать один элемент SVG вместо дублирования его в каждом разделе.

Большое спасибо за любую помощь /предложения.

Виски T.

разметка (каждый раздел):

<div class="section" id="section-1">
    <svg version="1.1" class="thing-svg" [ etc. ] >
        <g class="thing-path-group">
            <path class="thing-path" d=" ... " />
        </g>
    </svg>
    <!-- content -->
</div><!-- #section-1 -->

css:

.thing-svg {
    position: absolute;
    width: 60px;
    height: 60px;
    left: calc(50% - 30px);
    top: -60px;
    opacity: 0;
    z-index: 9;
}

.animate .thing-svg {
    animation: dropIt 1.8s ease-in-out forwards .3s;
}

@keyframes dropIt {
    0% {
        top: -60px;
        opacity: 0;
    }
    3% {
        opacity: 1;
    }
    100% {
        top: calc(100vh - 60px);
        opacity: 1;
    }
}

javascript:

const sections = document.querySelectorAll('.section');
const svgEl = document.querySelector('#svg-el');


window.addEventListener('scroll', debounce(findSection)); // yes, there's a debounce fn

function findSection(e) {

    let svgElPosition = svgEl.getBoundingClientRect();

    sections.forEach(section => {

        const sectionInAt = (window.scrollY + window.innerHeight) - section.offsetHeight / 2;

        // these both get the pre-css keyframe animation value of 'top', but I need the post-keyframe animation 'top' value
        console.log("svgElPosition.top", svgElPosition.top);
        console.log(window.getComputedStyle(svgEl, null).getPropertyValue("top"));


        // bottom of the section:
        const sectionBottom = section.offsetTop + section.offsetHeight;

        // isHalfShown is true while sectionInAt/triggerCoord > section.offsetTop (i.e., section is half viz)
        const isHalfShown = sectionInAt > section.offsetTop;

        // isNotScrolledPast is true while window.scrollY < imageBottom (i.e., image is still viz)
        const isNotScrolledPast = window.scrollY < sectionBottom;

        if (isHalfShown && isNotScrolledPast) {
            section.classList.add('animate');
        } else {
            section.classList.remove('animate');
        }

    });
}

Ответы [ 2 ]

0 голосов
/ 04 июня 2018

Вы должны зарегистрировать прослушиватель событий animationend на вашем элементе:

svgEl.addEventListener('animationend', function (event) {
    const svgRect = this.getBoundingClientRect();
});

Это срабатывает всякий раз, когда анимация CSS заканчивается на вашем элементе, и это верный способ узнать, что он имеетзавершено.Также обратите внимание, что вы можете использовать animationstart , animationiteration и animationcancel события.

0 голосов
/ 04 июня 2018

В этом случае, я полагаю, вам лучше всего использовать setTimeout (), чтобы подождать соответствующее количество времени для завершения анимации, а затем получить позицию в функции закрытия.Вот пример фрагмента:

if (isHalfShown && isNotScrolledPast) {
    section.classList.add('animate');
    let timer = setTimeout(function() {
    let rect = element.getBoundingClientRect();
    console.log(rect.top, rect.right, rect.bottom, rect.left);
    },300); //.3 seconds, if I read that correctly from the CSS (maybe an extra .01 seconds or something as well for good measure)
}

Переменная «таймер» явно не используется в этом примере, но она может быть полезна, если вам когда-либо понадобится отменить анимацию, чтобы отменить таймер (хотя вы будетенеобходимо выйти за рамки этого условного утверждения).

...