Published
Edited
Mar 29, 2021
15 stars
Insert cell
Insert cell
Insert cell
Insert cell
example0 = html`
<style>
.bar {
width: 100%;
height: 40px;
background-color: hsl(180, 50%, 50%);
margin-bottom: 20px;
transform: scaleX(0.1);
}
</style>

<div class="container">
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
<div class="bar"></div>
</div>`
Insert cell
Insert cell
{
// Selecting just the first of my bars
const myBar = example0.querySelector('.bar');

function callback (entries, observer) {
console.log('entries:', entries);
console.log('observer:', observer);
}
// Instancing a new IntersectionObserver
const observer = new IntersectionObserver(callback);

// Adding a target to be observed
observer.observe(myBar);
}
Insert cell
Insert cell
{
// Selecting all bars instead of just the first one
const myBars = example1.querySelectorAll('.bar');

// No need to change this part. Though we'll have multiple targets,
// we still have a single observer and a single callback
const observer = new IntersectionObserver((entries, observer) => {

// Each of the bars will make up an “entry”
entries.forEach(entry => {

// If our target enters the viewport, add an “active” class to it
if (entry.isIntersecting) {
entry.target.classList.add('active');
// Otherwise, remove the “active” class
} else {
entry.target.classList.remove('active');
}
});
});

// Looping through the bars and adding them as targets of the observer
Array.prototype.forEach.call(myBars, (el) => {
observer.observe(el);
});
}
Insert cell
Insert cell
Insert cell
html`
<style>
.bar {
transform-origin: left;
transition: transform 0.25s ease-out;
}

.bar.active {
transform: scaleX(1);
}
</style>
`
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
callback = (entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
console.log(entry.target);
entry.target.classList.add('active');
} else {
entry.target.classList.remove('active');
}
})
}
Insert cell
{
const myBars = example2.querySelectorAll('.scrolling-element');
const options = {
root: example2.querySelector('.frame')
}
const observer = new IntersectionObserver(callback, options);

Array.prototype.forEach.call(myBars, (el) => {
observer.observe(el);
});
}
Insert cell
Insert cell
{
const myBars = example3.querySelectorAll('.scrolling-element');
const options = {
root: example3.querySelector('.frame'),
rootMargin: '0px 0px -50% 0px'
}
const observer = new IntersectionObserver(callback, options);

Array.prototype.forEach.call(myBars, (el) => {
observer.observe(el);
});
}
Insert cell
Insert cell
Insert cell
Insert cell
{
const myBars = example4.querySelectorAll('.scrolling-element');
const options = {
root: example4.querySelector('.frame'),
rootMargin: '0px', // Removing the margins for clarity
threshold: 0.5
}
const observer = new IntersectionObserver(callback, options);

Array.prototype.forEach.call(myBars, (el) => {
observer.observe(el);
});
}
Insert cell
Insert cell
Insert cell
Insert cell
{
const myBars = example5.querySelectorAll('.scrolling-element');
function callback(entries, observer) {
entries.forEach(entry => {
if (entry.isIntersecting) {
// Rounding the intersectionRatio to 2 decimals
const scale = Math.round((entry.intersectionRatio)*100)/100;
entry.target.style.transform = `scaleX(${scale})`;
}
});
}
// Building an array of numbers starting at 0.00 and incrementing at every 0.01
const options = {
root: example5.querySelector('.frame'),
threshold: Array.apply(null, {length: 100}).map((n, i) => i/100)
}
const observer = new IntersectionObserver(callback, options);
Array.prototype.forEach.call(myBars, (el) => {
observer.observe(el);
});
}
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more