Coder Social home page Coder Social logo

react-scroll-to-component's Introduction

react-scroll-to-component

Smooth srolls to react component via reference

(To support the server side rendering, please refer to : https://github.com/flyingant/react-scroll-to-component-ssr

Install

With npm

  npm install react-scroll-to-component --save

With Yarn

  yarn add react-scroll-to-component

scrollToComponent(ref, <options>)

Valid options:
offset : number

Add an offset to the final position. if > 0 then page is moved to the bottom otherwise the page is moved to the top.

align : string

Alignment of the element. Can be one of 'top', 'middle' or 'bottom'. Defaulting to 'middle'.

ease : string

Easing function defaulting to "out-circ" (view ease for more)

duration : number

Animation duration defaulting to 1000

Example

import scrollToComponent from 'react-scroll-to-component';

// without options
scrollToComponent(this.refs.name);

//with options
scrollToComponent(this.refs.name, {
	offset: 1000,
	align: 'top',
	duration: 1500
});
import React, { Component } from 'react';
import './App.css';
import scrollToComponent from 'react-scroll-to-component';

class App extends React.Component {

  constructor(props) {
    super(props);
    this.scrollToTopWithCallback = this.scrollToTopWithCallback.bind(this)
  }

  componentDidMount() {
    scrollToComponent(this.Blue, { offset: 0, align: 'middle', duration: 500, ease:'inCirc'});
  }

  scrollToTopWithCallback() {
    let scroller = scrollToComponent(this.Violet, { offset: 0, align: 'top', duration: 1500});
    scroller.on('end', () => console.log('Scrolling end!') );
  }

  render() {
    return (
      <div className='main'>
        <div className='button_group'>
          <button onClick={this.scrollToTopWithCallback}>Go To Violet</button>
          <button onClick={() => scrollToComponent(this.Indigo, { offset: 0, align: 'bottom', duration: 500, ease:'inExpo'})}>Go To Indigo</button>
          <button onClick={() => scrollToComponent(this.Blue, { offset: -200, align: 'middle', duration: 1500, ease:'inCirc'})}>Go To Blue</button>
          <button onClick={() => scrollToComponent(this.Green, { offset: 0, align: 'middle', duration: 500, ease:'inExpo'})}>Go To Green</button>
          <button onClick={() => scrollToComponent(this.Yellow, { offset: 0, align: 'top', duration: 1500, ease:'inCirc'})}>Go To Yellow</button>
          <button onClick={() => scrollToComponent(this.Orange, { offset: 0, align: 'top', duration: 500, ease:'inCirc'})}>Go To Orange</button>
          <button onClick={() => scrollToComponent(this.Red, { offset: 0, align: 'top', duration: 500})}>Go To Red</button>
        </div>
        <section className='violet' ref={(section) => { this.Violet = section; }}>Violet</section>
        <section className='indigo' ref={(section) => { this.Indigo = section; }}>Indigo</section>
        <section className='blue' ref={(section) => { this.Blue = section; }}>Blue</section>
        <section className='green' ref={(section) => { this.Green = section; }}>Green</section>
        <section className='yellow' ref={(section) => { this.Yellow = section; }}>Yellow</section>
        <section className='orange' ref={(section) => { this.Orange = section; }}>Orange</section>
        <section className='red' ref={(section) => { this.Red = section; }}>Red</section>
        <b>Inspired By <a href="https://hopechen1028.github.io/hopechen.me/" target="_blank">Hope</a> with Love and Peace</b>
      </div>
    )
  }
}

export default App;

License

MIT

react-scroll-to-component's People

Contributors

flyingant avatar ryandekker avatar serranoarevalo avatar wwayne avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

react-scroll-to-component's Issues

Offset does not do anything

The offset value does not seem to do anything. The scroll works fine but it always scrolls exactly to the top of the component. I have tried many different values for offset including negative values.

`scroll = () => {
scrollToComponent(this.productInfo, {
offset: 400,
align: 'top',
duration: 1000
});
};

render () {
    return (
    <div>
        <Nav/>
        <MastHead clickHandler={this.scroll}/>
        <ProductInfo inputRef={node => this.productInfo = node}/>
    </div>
    );
}`

Allow easing functions

Please allow easing functions. For instance I use this set:

function B1(t) { return t*t*t }
function B2(t) { return 3*t*t*(1-t) }
function B3(t) { return 3*t*(1-t)*(1-t) }
function B4(t) { return (1-t)*(1-t)*(1-t) }
export function getBezier(percent,x2,y2,x3,y3) {
  var pos = {x:0, y:0};
  pos.x = 0*B1(percent) + x2*B2(percent) + x3*B3(percent) + 1*B4(percent);
  pos.y = 0*B1(percent) + y2*B2(percent) + y3*B3(percent) + 1*B4(percent);
  return pos;
}

Then I calculate timing and values. I actually had my own scroll function, but came to yours and loved it. Just missing these easing functions.

This was my scroll to function:

export const scrollIntoView = async function(domel, {duration=500, align='top', behavior='smooth', needed=0.5, smooth='ease'}={}) {
    // domel can be element or string, if string starts with space, dot, hash then it users querySelector
    // only does Y right now
    // duration - ms
    // align - top, none
    // bheavior - smooth, instant
    // needed - is the if needed part. portion of the domel that should be visible. with respect to align. its a decimal percent. so align=top and portion=0.5 means top 50% shoudl be visible at least. if it is not then scrolling is done
    // smooth - css smoothing - accepts: ease, linear, ease-in, ease-out, ease-in-out, or array of 4 numbers

    if (!domel) throw new Error('scrollIntoView: domel does not exist');

    if (typeof(domel) == 'string') {
        let selector = domel;
        let method = [' ', '.', '#'].includes(domel[0]) ? 'querySelector' : 'getElementById';
        domel = await retry(async () => {
            let domel = document[method](selector);
            if (!domel) throw new Error('retry');
            return domel;
        }, { interval:50, sec:1 });
    }

    if (!Array.isArray(smooth)) {
		let special_smooth = {
			ease: [.25,.1,.25,1],
			linear: [0,0,1,1],
			'ease-in': [.42,0,1,1],
			'ease-out': [0,0,.58,1],
			'ease-in-out': [.42,0,.58,1]
		};
		smooth = special_smooth[smooth];
    }

    let scroll = getScroll();
    let domel_ytop = parseInt(getElementScrollPosition(domel).y);

    if (align === 'top') {
        if (behavior === 'smooth') {
            let end = domel_ytop;
            let start = scroll.y;

            let steps = [];
            let lasttime = -10000000;
            const MIN_TIME_GAP = 10; // ms
            for (let i=0; i<101; i++) {
        		let scale = getBezier((100-i)/100, ...smooth);
        		let cur_val = Math.round((scale.y * (end - start)) + start);

        		if (!steps.length || steps[steps.length-1].val !== cur_val) {
        			let cur_time = Math.round(scale.x * duration);
                    if (cur_time - lasttime >= MIN_TIME_GAP) {
                        lasttime = cur_time;
            			steps.push({time:cur_time,val:cur_val});
                    }
        		}
            }
            // console.log('steps:', steps);


            // let timeouts = [];
            steps.forEach(step => {
            	// timeouts.push( setTimeout(()=>window.scrollTo(scroll.x, step.val), step.time) );
            	setTimeout(()=>window.scrollTo(scroll.x, step.val), step.time);
            });
        } else {
            // behavior == 'instant'
            window.scrollTo(scroll.x, domel_ytop);
        }
    }
}

Other features in my function that might be cool here are:

  • Pass in element id or querySelector string
    • If passed in string, then it will keep trying every 50ms to getElementById/querySelector - and only after then it will continue - maybe we can extend this to ref. if ref is null then wait till it becomes non-null.

Invalid calling object at animate(eval code:46:5) at scrollTo in IE

I get the below error in IE
TypeError: Invalid calling object at animate (eval code:46:5) at scrollTo (eval code:50:3) at module.exports (eval code:31:3) at Anonymous function (eval code:136:11) at callCallback (eval code:16433:152) at commitUpdateEffects (eval code:16472:29) at commitUpdateQueue (eval code:16460:19) at commitLifeCycles (eval code:17365:3) at commitAllLifeCycles (eval code:18736:44) at callCallback (eval code:150:1)

Does not work in production mode when used on a Gatsby site

"dependencies": {
    "gatsby": "^2.0.0",
    "react-scroll-to-component-ssr": "^1.0.0",
    ...
}

Tried with the ssr version and the original one. Works with gatsby develop but not when built and served. Is there a plugin I need or have I missed something?

Offset not working

The offset value does not seem to do anything. The scroll works fine but it always scrolls exactly to the top of the component. I have tried many different values for offset including negative values.

`scroll = () => {
scrollToComponent(this.productInfo, {
offset: 400,
align: 'top',
duration: 1000
});
};

render () {
    return (
    <div>
        <Nav/>
        <MastHead clickHandler={this.scroll}/>
        <ProductInfo inputRef={node => this.productInfo = node}/>
    </div>
    );
}`

License?

What license does this fall under? Can I use it in a commercial application?

Is it possible to scroll to component after the component shown?

I need to scroll to the component after it gets rendered to the page. The component itself is not shown bu default (the component will be rendered when example_shown is true). Something like this:
{props.example_shown && ( <ExtraComponent /> )}

and inside the ExtraComponent, I give ref={(section) => { this.ExtraComponent = section }}.
I tried to call scrollToComponent inside componentDidMount() but this.ExtraComponent returns to null. How can I scroll to position

code question

return Math.min(scrollPosition + offset + window.pageYOffset, maxScrollPosition); }

I have a question about your code , why do you return the min height

between (scrollPosition + offset + window.pageYOffset) and (documentHeight - clientHeight).
this will cause the offset as we pass to the plugin would be unuse if the min heght has return

Getting a warning accessing findDOMNode inside render

Warning: {COMPONENT} is accessing findDOMNode inside its render(). render() should be a pure function of props and state. It should never access something that requires stale data from the previous render, such as refs. Move this logic to componentDidMount and componentDidUpdate instead.

I could be doing it wrong, my ref looks like this:
<tr ref={row => { this.row = row; }} >

Scroll from child component

Hi,

I have a parent and a child component. I want to have a button in the child component which onclick calls a function in the parent component. Inside this function I have the scrollToComponent method.

Inside the render method in the parent class I have this

<Home scroll={this.scrollToBooking} />

and in my child I have this

<button className="book-button" onClick={() => props.scroll()}>ORDER NOW</button>

The scroll() method does get executed but the scrolling is not working, anybody know why or is it another way to do this?

scrollToBooking looks like this:

scrollToBooking() { scrollToComponent(this.Booking, { offset: 0, align: 'top', duration: 1000}); }

TypeError: Cannot set property x of undefined

I believe the new update of react scripts may have broken this package
My code

    <Button
    onClick={() => scrollToComponent(this.Description, {offset: 0, align: 'top',duration: 1200})}>
    </Button>

...
<section className='description' ref={(section) => { this.Description = section; }}>
  <Description />
  </section>

Yields TypeError: Cannot set property 'Description' of undefined on start. Worked fine before updating to the latest version of react-scripts

scroll not working properly

I am having an issue when testing in low speed 3G.

If there are components still loading and the scrolls-to-component function is triggered it scrolls to the component as expected but strangely immediately after the delay period it scrolls back to the previous place.
Once everything is loaded, the scroll-to component then works fine

Anyone experiencing this and know a work around? Much appreciated.

Tween is not a function on meteor.

Using meteor 1.8, not doing server side rendering.

First on meteor startup after installing this module I have the following warning :

Unable to resolve some modules:

  "tween" in project/node_modules/scroll-to/index.js (web.browser.legacy)

If you notice problems related to these missing modules, consider running:

  meteor npm install --save tween

I also tried to install npm install component/tween but issue remained.

Then when trying scrollToComponent(someRef) I got the error Tween is not a function.

I tried to require it in componentDidMount and also tried react-scroll-to-component-ssr (see issue #8)
but same error.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.