Intersection Observation continues when intersectionRatio is 1 - javascript

Want to get some perspective on the Intersection Observer API.
For simplicity, I have a div element (Square 500px x 500px) that will rotate based on the user's scroll position. This is obtained by entry.boundingClientRect.top.
However, once the intersectionRatio reaches 1 (the element is in full view of the window), the square will stop rotating until it begins to fall outside of the viewport.
The threshold of the observer is set to an array from [0-100] and I understand once the element is in full view, the observer's job is more or less done but I want the rotation to still occur as the user scrolls down further and the square is still in view.
Some workarounds I found..
Div container with 100vh
Square height to be a percentage and offset the rootMargin within observer options.
Is it possible for the observer to still work when it is fully in view?
Would like to hear other approaches!

Related

Can I trigger an animation when an element reaches half way in the viewport?

(JavaScript)
I can see that it is possible to trigger an animation using an IntersectionObserver when an element enters and leaves the viewport - but is there a way to trigger an animation when an element reaches half way in the view port?
you can use something like
new IntersectionObserver(yourAnimation, {rootMargin: "0px 0px -50% 0px"})
your element will be intersecting when it enters the top half of the viewport. basically adding a minus margin of half its height to the bottom edge of your root (here viewport)
You can use
if(elment.offsetLeft==window.offsetWidth) {startAnimation()}
// or element.offsetTop and window.offsetHeight
//you should write the startAnimation function, it not a built-in function

Can Intersection observer be used to calculate/trigger at specific offset top of target?

TL,DR:
I don't care how much of the target container is visible, I just want to know when the target container reaches a specific offset from top of the viewport (window). Should I stick with the good old scroll event or can this be done with Intersection observer?
Long story:
For a project I need to create a vertical scrolling parallax effect (as seen on this page, when viewed on large screens).
The parallax animation needs to detect when the target container reaches a specific offset from top of the viewport. And it needs to know the scroll direction.
I've found this question that explains how the visibilty percentage can be used to determine the scoll direction, which solves my 2nd problem.
So my question is: Can I use Intersection observer to trigger a callback when my target container reaches a specific offset from top of the viewport?
In pseudo-code, I'd need something like this:
var observer = new IntersectionObserver(offsetReached, {root: null});
function offsetReached(entries, observer) {
entries.forEach(entry => {
if (entry.offsetFromTop == '200px') {
entry.target.classList.add('container--fixed');
}
});
}
observer.observe('.container');
Intersectionobserver's purpose is to detect when a portion of element becomes visible, if you want to watch for offSetthe best option is to use the old fashioned scroll event and getBoundingClientRect() on the element you need to watch on.
Use the rootMargin option on the IntersectionObserver:
var observer = new IntersectionObserver(offsetReached, {rootMargin: '-200px'});
Each side of the rectangle represented by rootMargin is added to the corresponding side in the root element's bounding box before the intersection test is performed. (MDN Web Docs: Intersection)Observer.rootMargin)

Intersection observer rootBound gives incorrect value

I have a scroll container where children are scrolling in vertical direction. It has many small elements. The height of my scroll container is 100vh. My task is to observe them as soon as they reach 100px below top border(which is top of viewport in my case).
To achieve this I am creating an intersection observer on my scroll container element with rootmargin as -100px 0px 0px 0px.
I am observing on threshold 1.
In the intersection observer callback I am checking: entry.intersectionRect.top === entry.rootBound.top. This ensures that I am checking only topmost element.
All these operations are happening as expected but with one problem: intersection is not being observed 100px below top, but 81px below top. I confirmed this when I checked that in callback, value of entry.rootBound.top is 81px.
I suppose this should not be the case, the rootBound should have top similar to top margin that I gave in constructor option.
Very new to intersection observer and I want to use it in my project, but cannot do so with inconsistencies.
The only possible solution that seemed to be working correctly to me is to put an intersection observer on whole viewport, but pass a top margin of 10px(could be any value). Then observe that when the page loads, we would get a rootBounds value and that could indicate what is rootBounds.top. From there we could infer what is the device pixel ratio(givenMargin/rootBounds.top). Then we can simply unobserve that Infinite intersection observer.
This works generic for any browser, without worrying about to check which browser are we working on. Or we could check for browser and it's version and then import this kind of utility in our code.

Force element to scroll when it is slightly off screen

I need an element to scroll into the screen when it is partially out of it. I already have a function that is detecting whether or not it is within the viewport, but I would like to bring the element completely into the viewport using its size. Think of it as a square element which is half way in the viewport, I would like to scroll in a way that will bring that element completely in.
This may be off to the side or above or beneath the current viewport. How do I scroll the element into the viewport when it is detected to be out?
Here is the current code:
const $target = $(evt.target) // this is the current target which will be tested whether or not is outside of the viewport
if (isOutsideOfViewport($target)) {
$target.scrollToBringTargetCompletelyToViewport() // how to make something like this work?
}
Edit: to show in more details what I am trying to do, I have drawn the following diagram.
As you can see, the target is slightly outside of the viewport. The objective is to bring the target completely in the viewport.
Before:
After:
This would happen no matter where the target is on the screen, I just want to scroll just enough for it to be completely within the viewport.

How to obtain clientWidth & clientHeight before DIV is visible

I want to obtain the dimensions of a DIV element (used to display a popup menu at the cursor position) while it's style.display='none;', however the dimensions of the DIV always return 0. The only way I seem to be able to get the dimensions is to make the DIV style.display='block;' at 0,0 and then move it to the required position, but that looks jumpy.
I've tried making the DIV visible outside of the visible screen area but that doesn't work. Is there a way to get the clientWidth and clientHeight values whilst the DIV is hidden?
If your DIV is not visible, you won't be able to get its dimensions.
However, there is a workaround. Your div has to be "visible", but that doesn't mean it's opacity and position have to be 1 and relative.
Set the opacity to 0 and the position to "absolute" and you'll be able to get the DIV dimensions.
EDIT
Since I think more people will have a similar problem, I feel I should explain my answer a little more.
If you try to get the size of a hidden element with JavaScript, you will always get 0.
So there are techniques to get the real size without displaying the element to the user. My favourite is the one I already wrote about above. Here are the more detailed steps:
you set the elements opacity to 0. This way it won't be displayed to the end user while you are getting the dimensions.
you set the element position to "absolute". This way it won't take up any space.
now it's safe to set the display to "inline-block".
you read the elements dimensions. This time you'll get the real values.
You set the display back to "hidden" and set the opacity and position back to its original values.
And now you have the size of a hidden element.
If you'd like to know the size of an element onscreen without it being visible you need it to be painted to the screen but not shown.
In order to get clientHeight and clientWidth you need it to be rendered so the calculations can be performed based on the screens current state (unless you have pre-programmed width and height, which I'm guessing you don't)
you can find out more information at MDN here
So you have options:
create your div offscreen using positioning (fixed or absolute) combined with z-index or opacity
use width: 0 and height: 0 and overflow: hidden then use scrollHeight and scrollWidth to find the overflow size
choose which option is best for your site, considering things like responsiveness and screen reflows and repaints

Categories

Resources