繁体   English   中英

如何在CSS动画之后获取元素的位置(香草JS)

[英]How to get the position of an element after css animation (vanilla js)

我正在从事一个涉及多个动画的项目,尽管大多数动画都可以轻松地通过css关键帧动画完成,但其他动画需要使用javascript,我对如何执行这些动画颇有兴趣。 我将尽我所能描述无法在小提琴中显示的内容(我正在编码视频中的演示内容)。

页面中有几个部分,每个部分具有淡入和淡出,旋转等各种元素。当每个部分滚动到视图中时,将向其中添加一个“动画”类以触发css动画,其中一个是svg元素从视口的北部下降到停放的视口的底部。 但是,当用户继续向下滚动时,我需要对此svg元素进行动画处理,使其离开视口以南的视图,然后在下一部分滚动到视图中时重新进入。 所以我试图在停放时在findSection函数中获取元素的位置(请用香草js),即, 完成其关键帧动画后,但到目前为止我尝试过的方法是获取动画前的位置。 通过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');
        }

    });
}

您应该在元素上注册animationend事件监听器:

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

每当CSS动画在您的元素上完成时,此方法就会触发,这是知道它已完成的可靠方法。 还要注意,您可以使用animationstartanimationiterationanimationcancel事件。

在这种情况下,我认为您最好的选择是使用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)
}

在此示例中未明确使用“ timer”变量,但是如果您还需要取消动画来取消计时器,则它可能很有用(尽管您需要将作用域置于此条件语句之外)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM