gpt4 book ai didi

javascript - 动画回调在错误的时间调用

转载 作者:太空宇宙 更新时间:2023-11-04 09:44:36 25 4
gpt4 key购买 nike

我正在尝试在我的自定义滚动条上制作弹跳效果。 (我正在使用 translate3d 滚动。)我终于能够实现它,但现在唯一的问题是,如果你继续滚动越界(尝试双滚动并一直这样做直到它卡住),然后它会一直处于边界之外,直到您向下滚动(或向上滚动,具体取决于卡住的位置)。

像这样:http://imgur.com/SHAe1E4 (出于某种原因,stackoverflow 不允许我添加 gif。)代码:JSFiddle

问题:

如何使用 JavaScript 和 CSS 制作滚动弹跳效果?

其余部分可选阅读。

不工作的原因:

我认为它这样做的原因是:有一个动画回调事件。因此,如果动画没有发生,即转换没有改变,那么动画回调将不会触发。

所以当它一直滚动到顶部或底部时,你再次滚动,(在动画完成之前,动画回调不会被调用,因为变换值没有改变)动画回调将不会被调用,因此它不会滚动(反弹)回边界。

我尝试了什么:

我试着检查滚动位置是否改变,如果它没有调用动画回调函数,但它没有给出预期的结果。当您尝试一次多次滚动出界时,它会产生“断断续续”的效果,并且不会一直滚动到边界外,它会在中途停止并向后滚动。像这样:http://imgur.com/a/xHYle JSFiddle

每当滚动位置没有改变时,我还尝试将转换值更改为 0.1,因此将调用动画回调。这样做的问题是,如果您滚动到边界之外,它会等待半秒才能弹回。
所以当滚动位置没有改变时,我将动画持续时间设置为较短的时间,但是如果你反复滚动出界,即当它超出范围时,你继续滚动,向上或向下,然后它会等待一秒钟,然后反弹回来。 JSFiddle

console.clear();

var innerWrapper = document.getElementById('innerWrapper');
var scrollBar = document.getElementById('scrollbar');
var scrollBarThumb = scrollBar.firstElementChild;

var scrollPosition = 0;
var scrolledToBottom = innerWrapper.scrollHeight - innerWrapper.parentElement.offsetHeight;

scrollBarThumb.style.height = (innerWrapper.offsetHeight * innerWrapper.offsetHeight / innerWrapper.scrollHeight) + 'px';

innerWrapper.addEventListener('mousewheel', handleScroll);
innerWrapper.addEventListener('DOMMouseScroll', handleScroll);
innerWrapper.addEventListener('transitionend', bounceBack);

innerWrapper.style.transform = 'translate3d(0px, 0px, 0px)';

function handleScroll(e) {
// Prevent parents from scrolling
e.preventDefault();
var direction = (e.detail < 0 || e.wheelDelta > 0) ? 1 : -1; // 1 = scroll down, -1 = scroll

scrollPosition += direction * 100; // Cannot use `deltaY`, because not all browsers support it.
scrollPosition = clamp(scrollPosition, -scrolledToBottom - 40, 40); // 40 = bounce amount

var scrollThumbPosition = (scrollPosition * scrollBarThumb.offsetHeight / innerWrapper.parentElement.offsetHeight);
scrollThumbPosition = clamp(scrollThumbPosition, -scrolledToBottom, 0);

innerWrapper.style.transform = 'translate3d(0px, ' + scrollPosition + 'px, 0px)';
scrollBarThumb.style.transform = 'translate3d(0px, ' + -scrollThumbPosition + 'px, 0px)';
}

function bounceBack(e) {
// Scrolling stopped too high?
if (scrollPosition > 0) {
scrollPosition = 0;
// Scrolling stopped too low?
} else if (scrollPosition < -scrolledToBottom) {
scrollPosition = -scrolledToBottom;
// Scrolling stopped in viewport (i.e. not out of bounds)?
} else {
return;
}

// Bounce back with shorter animation
innerWrapper.style.transitionDuration = '100ms';
innerWrapper.style.transform = 'translate3d(0px, ' + (scrollPosition) + 'px, 0px)';


// Need a 'pause' for the transform to finish with shorter animation
setTimeout(function() {
// Set animation time back to original
innerWrapper.style.transitionDuration = '500ms';
});
}

function clamp(val, min, max) {
if (typeof min !== 'number') min = 0;
if (typeof max !== 'number') max = 1;
return Math.min(Math.max(val, min), max);
}
#outerWrapper {
height: 400px;
overflow: hidden;
display: flex;
background-color: black;
}
#innerWrapper {
transform: translate3d(0px, 0px, 0px);
transition-property: transform;
transition-duration: 500ms;
transition-timing-function: ease;
}
#content {
background-image: url("http://images.freeimages.com/images/premium/previews/3037/30376024-beautiful-flower-portrait.jpg");
width: 400px;
}
#scrollbar {
height: 100%;
width: 50px;
background-color: orange;
}
#scrollbar_thumb {
background-color: yellow;
border: 2px solid blue;
box-sizing: border-box;
transform: translate3d(0px, 0px, 0px);
transition-property: transform;
transition-duration: 500ms;
transition-timing-function: ease;
}
<div id="outerWrapper">
<div id="innerWrapper">
<div id="content">
Lorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero
sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus
Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus
enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar
justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames
ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque
Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem
lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor Lorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie
vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum
vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque
Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci
Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla.
Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet
consectetuer laoreet faucibus id ut et. Consequat Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet
risus Sed condimentum Cras. Nunc massa mauris tempor dolor pulvinar justo neque dui ipsum vitae. Lacinia dui scelerisque Sed convallis nonummy orci Vestibulum orci tempusLorem ipsum dolor sit amet consectetuer laoreet faucibus id ut et. Consequat
Ut tellus enim ante nulla molestie vitae sem interdum turpis. Fames ridiculus cursus pellentesque Vestibulum justo sem lorem neque accumsan nulla. Lacinia Suspendisse vitae libero sem et laoreet risus Sed condimentum Cras. Nunc massa mauris tempor
dolor
</div>
</div>
<div id="scrollbar">
<div id="scrollbar_thumb"></div>
</div>
</div>

最佳答案

我可能会使用 z 组件在每个滚轮事件之间做出细微差别,以触发过渡。 fiddle

var i = 0;
// onmousewheel
.. el.style.transform = `translate3d(0, 40px, ${i^=1}px)`

// ontransitionend
.. el.style.transform = `translate3d(0, 0, -1px)`

如果上面的方法太棘手,我们可能会做一个昂贵的查询来找到当前的翻译 y 是什么。然后将其与 bounceAmount(例如,在您的情况下为 40)进行比较,如果它们几乎相同(差异。< Number.EPSILON),则直接调用 bounceBack()

var m = getComputedStyle(el).transform.match(/,\s*([^,]*?)\s*\)/)
m ? m[1] : 0 // current translation y

更新

如果内容需要立即反弹,我们可以简单地在运动开始时禁用 onwheel ,然后在整个运动完成后重新启用它。这不再需要 z 组件技巧。 fiddle

关于javascript - 动画回调在错误的时间调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39584249/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com