jsonkao / react-scrollama Goto Github PK
View Code? Open in Web Editor NEWSimple scrollytelling with the IntersectionObserver in React.
Home Page: https://jsonkao.github.io/react-scrollama
License: MIT License
Simple scrollytelling with the IntersectionObserver in React.
Home Page: https://jsonkao.github.io/react-scrollama
License: MIT License
Consider Symbols.
Hi, the last version 2.2.13
is not compatible with server side rendering
error occurs when calling window.innerHeight
.
I need to downgrade to version 2.2.7
to make react-scrollama
work with SSR
As of React #25699, usage of defaultProps
will result in a warning:
Support for defaultProps will be removed from function components in a future major release. Use JavaScript default parameters instead.
This impacts the Scrollama
and Step
component.
Right now, React Scrollama simply adds Scrollama.handleResize
as a resize event to the window. Ideally, users should be able to throttle this resizing. It would also be great to just be able to call it somehow after updating DOM/Step elements.
Hi, so I've gotten super slow at responding to issues and pull requests. I'm tagging all the beautiful people who have helped make React Scrollama possible today. Would anyone like to become a maintainer with me? It would involve responding to issues and PRs faster than my current average time (1 month lol.. sorry).
@maerzhase @fschwander @davidnmora @tuckergordon
Sorry if I forgot anyone!
fire incremental step progress update
Version 2.3.0-beta.0 introduces an incompatibility with next.js SSR. As v2.3.0-beta.0 fixes other dealbreaker issues (#19 (comment)) this is a blocker problem for me.
Server Error
ReferenceError: window is not defined
Unhandled Runtime Error
SyntaxError: Failed to construct 'IntersectionObserver': rootMargin must be specified in pixels or percent
So at present it looks like using the library with next.js is not possible at all.
(the no-frills example from the Readme, unmodified):
pages/index.js
import React, { useState } from 'react';
import { Scrollama, Step } from 'react-scrollama';
const ScrollamaDemo = () => {
const [currentStepIndex, setCurrentStepIndex] = useState(null);
// This callback fires when a Step hits the offset threshold. It receives the
// data prop of the step, which in this demo stores the index of the step.
const onStepEnter = ({ data }) => {
setCurrentStepIndex(data);
};
return (
<div style={{ margin: '50vh 0', border: '2px dashed skyblue' }}>
<div style={{ position: 'sticky', top: 0, border: '1px solid orchid' }}>
I'm sticky. The current triggered step index is: {currentStepIndex}
</div>
<Scrollama onStepEnter={onStepEnter} debug>
{[1, 2, 3, 4].map((_, stepIndex) => (
<Step data={stepIndex} key={stepIndex}>
<div
style={{
margin: '50vh 0',
border: '1px solid gray',
opacity: currentStepIndex === stepIndex ? 1 : 0.2,
}}
>
I'm a Scrollama Step of index {stepIndex}
</div>
</Step>
))}
</Scrollama>
</div>
);
};
export default ScrollamaDemo;
pages/index.js
import React, {useState} from "react"
import dynamic from 'next/dynamic'
const ScrollamaDemo = dynamic(
() => import('../components/ScrollamaDemo'),
{ ssr: false }
)
const Page = () =>
<div><ScrollamaDemo/></div>
export default Page
components/ScrollamaDemo.js
import React, {useState} from "react"
import { Scrollama, Step } from 'react-scrollama'
const ScrollamaDemo = () => {
const [currentStepIndex, setCurrentStepIndex] = useState(null);
const onStepEnter = ({ data }) => {
setCurrentStepIndex(data);
};
return (
<div style={{ margin: '50vh 0', border: '2px dashed skyblue' }}>
<div style={{ position: 'sticky', top: 0, border: '1px solid orchid' }}>
I'm sticky. The current triggered step index is: {currentStepIndex}
</div>
<Scrollama onStepEnter={onStepEnter} debug>
{[1, 2, 3, 4].map((_, stepIndex) => (
<Step data={stepIndex} key={stepIndex}>
<div
style={{
margin: '50vh 0',
border: '1px solid gray',
opacity: currentStepIndex === stepIndex ? 1 : 0.2,
}}
>
I'm a Scrollama Step of index {stepIndex}
</div>
</Step>
))}
</Scrollama>
</div>
)
}
export default ScrollamaDemo
Right now, the versions of react
and react-dom
required are ^16.8.0. However, this library should work fine with React 17 and React 18 (both of which are allowed in the react-intersection-observer dependency.
NPM v8 is enforcing peerDependencies more strictly than previous versions, so trying to install this on a React 17 project errors. I don't think there's anything in the library that would preclude it from working on newer versions of React. Can we add those versions to this package's peer dependencies?
Is there a way to implement where the div container slowly fades out when it hits a specific height of the webpage using the onStepExit
function?
Hey there!
First of all: thanks for the great npm package. <3
It seems that you forgot the default props of of offset equals 0.3 in Scrollama.js (as described in your documentation).
Best, Fabian
If you try to recreate the example in the README, you get this error:
React.Children.only expected to receive a single React element child
The problem is that <Step>
is taking text nodes in the example:
<Scrollama onStepEnter={this.onStepEnter}>
<Step data={1} key='1'>
step 1
</Step>
<Step data={2} key='2'>
step 2
</Step>
</Scrollama>
However, if you replace the text nodes any element, then everything works correctly:
<Scrollama onStepEnter={this.onStepEnter}>
<Step data={1} key='1'>
<div>step 1</div>
</Step>
<Step data={2} key='2'>
<div>step 2</div>
</Step>
</Scrollama>
React.Children.only(children)
throws with a text node: https://github.com/jsonkao/react-scrollama/blob/master/src/Step.js#L25
I don't know if you want to allow text nodes, or update the README to wrap the text in elements.
Relevalent snippet
let jsx=[];
for (let i=0;i<N;i++){
jsx.push(<Step data={{step:i}}><div> {i}</div></Step>);
}
return(<Scrollama onStepEnter={onStepEnter}>{jsx}</Scrollama>);
This works well while N is the same (or smaller) than the original. But if you change N to a larger number afterwards, it will only work up to that number.
Basically, this works:
<Scrollama>
<Step data={1}>
<div style={{ height: "400px" }}>1</div>
</Step>
<Step data={2}>
<div style={{ height: "400px" }}>2</div>
</Step>
</Scrollama>
But this throws runtime error:
<Scrollama>
<>
<Step data={1}>
<div style={{ height: "400px" }}>1</div>
</Step>
<Step data={2}>
<div style={{ height: "400px" }}>2</div>
</Step>
</>
</Scrollama>
Full Error:
Failed to construct 'IntersectionObserver': rootMargin must be specified in pixels or percent.
at new e.IntersectionObserver (chrome-extension://ekhagklcjbdpajgpjgmbionohlpdbjgc/lib/SingleFile/single-file-hooks-frames.js:1:8206)
at createObserver (http://localhost:3000/static/js/bundle.js:41452:22)
at observe (http://localhost:3000/static/js/bundle.js:41509:7)
at http://localhost:3000/static/js/bundle.js:41587:27
at http://localhost:3000/static/js/bundle.js:41683:5
at commitAttachRef (http://localhost:3000/static/js/bundle.js:32135:24)
at commitLayoutEffectOnFiber (http://localhost:3000/static/js/bundle.js:32016:13)
at commitLayoutMountEffects_complete (http://localhost:3000/static/js/bundle.js:33015:13)
at commitLayoutEffects_begin (http://localhost:3000/static/js/bundle.js:33004:11)
at commitLayoutEffects (http://localhost:3000/static/js/bundle.js:32950:7)
This makes it a bit tricky to do array mappings, e.g.
<Scrollama>
{[1, 2].map((i) => (
<>
<Step data={{ step: i, part: 1 }}>
<div style={{ height: "400px" }}>part1</div>
</Step>
<Step data={{ step: i, part: 2 }}>
<div style={{ height: "200px" }}>part2</div>
</Step>
</>
))}
</Scrollama>
A work around is to generate a rolled out array first, and then map each element to a single Step
element.
position: sticky
polyfillExample code throws this error:
SyntaxError: Failed to construct 'IntersectionObserver': rootMargin must be specified in pixels or percent.
When building a Gatsby site (using Server Side Rendering) I got this error:
ReferenceError: regeneratorRuntime is not defined
node_modules/react-scrollama/dist/index.es.js:594:1
I'm testing the example on my local machine, when i try to log progress i just see 0 or 1.
Hi @jsonkao
I am using your awesome react-scrollama npm in my project. I made the background image fixed with the css property "background-attachment: fixed" and added a scrollama component with 3 Steps over the container. Then, when I scroll up or down, the background image gets blurry except for start and end of scrolling. How can I fix it? Thank you in advance!
Hi there it's me again! ๐ธ
I had some time to look into scrollama
and react-scrollama
. With the problems we previously found in e.g. #40 I started to be curious about a modern functional components and hooks approach for react-scrollama
. After I did a short deep dive into both libs and the use of react-intersection-observer-hook
lib, it was actually pretty easy to implement a working version.
The benefits I see in the rewrite is mainly in code maintenance (less code) and smaller bundle size. My build works as a drop-in replacement of the example and is only ~8kb instead of ~26kb.
Since i am not sure if you are at all interested in such a rewrite I wanted to open this issue before I open a PR. Just let me know if you want to integrate this as a release of this library. You can have a look at the code here:
https://github.com/maerzhase/react-scrollama/tree/feature/functional-rewrite
Since there are no tests written i am not 100% sure if I might have missed something. I tried my best to keep up with the existing API and from running the example I actually do not experience any problems.
onContainerEnter
onContainerExit
Also see #39.
Sticky overlay, sticky side by side, just triggers, etc.
I'm trying to get the example working in Gatsby. The component renders, but onStepEnter is never actually called:
import React, { Component } from "react"
import { Scrollama, Step } from 'react-scrollama';
import Layout from "../components/layout"
import Head from '../components/head';
class NarrativePage extends Component {
state = {
data: 0,
steps: [10, 20, 30],
progress: 0,
};
onStepEnter = ({ element, data }) => {
console.log(data);
element.style.backgroundColor = 'lightgoldenrodyellow';
this.setState({ data });
};
onStepExit = ({ element }) => {
element.style.backgroundColor = '#fff';
};
onStepProgress = ({ element, progress }) => {
this.setState({ progress });
};
render() {
const { data, steps, progress } = this.state;
return (
<Layout>
<Head title="Narrative"/>
<div className="graphicContainer">
<div className="scroller">
<Scrollama
onStepEnter={this.onStepEnter}
onStepExit={this.onStepExit}
progress
onStepProgress={this.onStepProgress}
offset={0.4}
debug
>
{steps.map(value => (
<Step data={value} key={value}>
<div className="step">
<p>step value: {value}</p>
{value === data && <p>{Math.round(progress * 100)}%</p>}
</div>
</Step>
))}
</Scrollama>
</div>
<div className="graphic">
<p>{data}</p>
</div>
</div>
</Layout>
)
}
}
export default NarrativePage;
Hi, are there any specific updates related to the v2.2.12 ?
I tried to migrate from 2.2.10 to 2.2.12 and my code doesn't work anymore with the prop progress
:
<Scrollama
onStepEnter={this.onStepEnter}
onStepExit={this.onStepExit}
progress
onStepProgress={this.onStepProgress}
offset={0.42}
threshold={0}
>
Would it be possible to publish types for TypeScript?
On different Android Smartphones that I have tested (e.g. Samsung Galaxy S7 with Android Version 8.0.0 and Chrome Version 73.0.3683.90) scrolling upwards does not trigger anything.
I made a video. Sometimes the step get's triggered, but most of the time it does not:
https://youtu.be/wqNRNE2ZSF4
Howdy,
I've noticed that when I setup Jest Snapshot testing on a page that has Scrollama setup, it continually re-generating ids. E.g:
- id="813dd771-d938-48ca-a2d5-0c7b82d84333"
+ id="588693b2-d464-4ada-8abf-b217a101d32f"
Therefore snapshot tests are always failing. Is it possible to avoid this?
A bug seems to have been introduced when upgrading to version 2.3.0.
react-scrollama/src/Scrollama.js
Line 46 in ba76c02
Gatsby SSR doesn't like this line, it just needs an if to check that window exists really (https://www.gatsbyjs.com/docs/debugging-html-builds/).
Right now it's needed to get the correct step from an intersection observer entry target.
Webpack production build using Gatsby return WebpackError: ReferenceError: window is not defined
.
Should make sure window is define before loading intersection-oberver
. Will also make other window usage in scrollama.js works with that mechanic.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.