当一个圆的父节滚动到视图中时,我想要更改它的位置。
当父对象在视图中之后向下滚动时,它应该向右移动,当向上滚动时,它应该回到原来的位置。(-200px向左)它应该只在用户主动滚动时移动。
如果用户一直向下滚动到圆的父部分的最底部,或者如果他们已经向下滚动到底部并重新加载页面,圆应该会出现在它完全显示的位置。
我当前的代码部分正常工作,但我在根据父元素的可见程度显示整个元素以及在滚动到最底部后重新加载页面时将其显示在最终位置时遇到了问题。
JSFiddle:https://jsfiddle.net/thebluehorse/gu2rvnsw/
var $window = $(window),
$sectionFour = $('.section-four'),
$circle = $sectionFour.find('.circle'),
lastScrollTop = 0,
position = -200;
function revealCircle() {
var isVisible,
st = $window.scrollTop();
isVisible = isInView($sectionFour);
if (isVisible) {
// console.log('section four is in view, so lets do stuff!');
if (st > lastScrollTop) {
if (position === 0) {
return false
}
$circle.css('transform', 'translateX(' + position + 'px')
position++;
} else {
if (position === -200) {
return false
}
$circle.css('transform', 'translateX(' + position + 'px')
position--;
}
}
}
function isInView(node) {
var rect;
if (typeof jQuery === 'function' && node instanceof jQuery) {
node = node[0];
}
rect = node.getBoundingClientRect();
return (
(rect.height > 0 || rect.width > 0) &&
rect.bottom >= 0 &&
rect.right >= 0 &&
rect.top <= (window.innerHeight || document.documentElement.clientHeight) &&
rect.left <= (window.innerWidth || document.documentElement.clientWidth)
);
}
$window.on('scroll', revealCircle);
.circle {
width: 400px;
height: 400px;
background: #fff;
-webkit-border-radius: 200px;
-moz-border-radius: 200px;
border-radius: 200px;
transform: translateX(-200px); }
.section {
min-height: 400px; }
.section-one {
background-color: red; }
.section-two {
background-color: orange; }
.section-three {
background-color: yellow; }
.section-four {
background-color: green; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section class="section section-one"></section>
<section class="section section-two"></section>
<section class="section section-three"></section>
<section class="section section-four">
<div class="circle"></div>
</section>
发布于 2019-09-13 03:29:46
你的代码可以简化一点。在滚动页面时,唯一需要跟踪的值是scrollTop()
。因为$sectionFour
的几何体永远不会改变,所以您可以立即缓存它的getBoundingClientRect()
。
一旦知道$sectionFour
在视图中,就需要计算出它的总高度中有多少像素在视图中,将其转换为百分比,然后将该百分比应用于初始位置-200。本质上,当只显示几个像素时,这是一个很小的百分比,例如10%,-200变成-180。当元素完全显示在视图中时,百分比应接近100%,-200变为0。这意味着您没有跟踪上一个位置或滚动的方向,您只是计算应该基于当前视口(scrollTop)的值。
var $window = $(window),
$sectionFour = $('.section-four'),
$circle = $sectionFour.find('.circle');
rect = $sectionFour[0].getBoundingClientRect();
function revealCircle() {
var scrollTop = $window.scrollTop();
var windowHeight = $window[0].innerHeight;
if (scrollTop + windowHeight > rect.top) {
var percentVisible = (scrollTop - (rect.top - windowHeight)) / rect.height;
var position = 200 - (percentVisible * 200);
$circle.css('transform', 'translateX(-' + position + 'px');
}
}
$window.on('scroll', revealCircle);
body { margin:0;}
.circle {
width: 400px;
height: 400px;
background: #fff;
-webkit-border-radius: 200px;
-moz-border-radius: 200px;
border-radius: 200px;
transform: translateX(-200px); }
.section {
min-height: 400px; }
.section-one {
background-color: red; }
.section-two {
background-color: orange; }
.section-three {
background-color: yellow; }
.section-four {
background-color: green; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section class="section section-one"></section>
<section class="section section-two"></section>
<section class="section section-three"></section>
<section class="section section-four">
<div class="circle"></div>
</section>
发布于 2019-09-13 03:56:17
对于纯JS解决方案,使用css变量可能会更简单:
const sectFour = document.querySelector('#section-four')
, divCircle = sectFour.querySelector('.circle')
function percentVisible(elm)
{
let rect = elm.getBoundingClientRect()
, viewHeight = Math.max(document.documentElement.clientHeight, window.innerHeight)
, visu = viewHeight-rect.top
return (visu<0) ? -1 : Math.min( 100, (visu/rect.height*100))
// return !(rect.bottom < 0 || rect.top - viewHeight >= 0) => checkVisible
}
window.onscroll=_=>
{
let circlePos = percentVisible(sectFour) *2
if (circlePos>=0)
{
divCircle.style.setProperty('--circle-pos', `-${200-circlePos}px`)
// IE 11 : // divCircle.style=('transform:translateX(-'+(200-circlePos)+'px')
}
}
* { margin: 0 }
.circle {
--circle-pos :-200px;
width : 400px;
height : 400px;
background-color : #fff;
-webkit-border-radius: 200px;
-moz-border-radius: 200px;
border-radius: 200px;
transform : translateX(var(--circle-pos));
/* IE 11 ........... : translateX(-200px); */
}
section { min-height: 400px; }
section:nth-of-type(1) { background-color: red; }
section:nth-of-type(2) { background-color: orange; }
section:nth-of-type(3) { background-color: yellow; }
section:nth-of-type(4) { background-color: green; }
<section></section>
<section></section>
<section></section>
<section id="section-four"> <div class="circle"></div> </section>
发布于 2019-09-13 05:54:00
你应该看看Intersection Observer (IO),它是用来解决像你这样的问题的。侦听scroll事件并计算位置可能会导致性能下降。
首先,您必须定义IO的选项:
let options = {
root: document.querySelectorAll('.section-four'),
rootMargin: '0px',
threshold: 1.0
}
let observer = new IntersectionObserver(callback, options);
在定义了选项之后,您必须告诉观察者要观察哪些元素,我猜在您的例子中应该是.section-four
let targets = document.querySelectorAll('.section-four');
targets.forEach(target => {
observer.observe(target) }
)
最后一步是定义在.section-four
进入视图后应该执行的回调函数:
let callback = (entries, observer) => {
entries.forEach(entry => {
// Each entry describes an intersection change for one observed
// target element
// here you can do something like $(entry.target).find('circle') to get your circle
});
};
看看this demo,这取决于元素背景颜色变化的程度。我认为这接近于你的问题,你只是不改变bg-color,而是在元素中设置圆的动画。
网站上还有另一个演示,可以显示元素在屏幕上的可见程度,也许这个更适合你。
您还可以使用此polyfill from w3c来支持较旧的浏览器。
https://stackoverflow.com/questions/57916123
复制相似问题