Guest User

Untitled

a guest
Nov 13th, 2018
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.21 KB | None | 0 0
  1. import React, { PureComponent } from 'react';
  2. import PropTypes from 'prop-types';
  3.  
  4. export default class ViewportTrigger extends PureComponent {
  5. static propTypes = {
  6. onViewportEnter: PropTypes.func,
  7. onViewportLeave: PropTypes.func,
  8. children: PropTypes.node,
  9. threshold: PropTypes.number,
  10. };
  11.  
  12. static defaultProps = {
  13. threshold: 0,
  14. };
  15.  
  16. state = {
  17. hasEntered: false,
  18. };
  19.  
  20. componentDidMount() {
  21. window.addEventListener('scroll', this.onToggle, false);
  22. window.addEventListener('resize', this.onToggle, false);
  23. }
  24.  
  25. componentWillUnmount() {
  26. window.removeEventListener('scroll', this.onToggle, false);
  27. window.removeEventListener('resize', this.onToggle, false);
  28. }
  29.  
  30. onToggle = () => {
  31. if (this.trigger) {
  32. if (!this.state.hasEntered && this.isInViewport()) {
  33. this.onViewportEnter();
  34. } else if (this.state.hasEntered && !this.isInViewport()) {
  35. this.onViewportLeave();
  36. }
  37. }
  38. }
  39. onViewportEnter() {
  40. const { onViewportEnter } = this.props;
  41.  
  42. if (onViewportEnter) onViewportEnter();
  43.  
  44. this.setState({
  45. hasEntered: true,
  46. });
  47. }
  48.  
  49. onViewportLeave() {
  50. const { onViewportLeave } = this.props;
  51.  
  52. if (onViewportLeave) onViewportLeave();
  53.  
  54. this.setState({
  55. hasEntered: false,
  56. });
  57. }
  58.  
  59. isInViewport() {
  60. const { threshold } = this.props;
  61.  
  62. if (!this.trigger) return false;
  63.  
  64. const {
  65. top,
  66. left,
  67. bottom,
  68. right,
  69. } = this.trigger.getBoundingClientRect();
  70.  
  71. const width = document.documentElement.clientWidth
  72. || document.body.clientWidth
  73. || window.innerWidth;
  74. const height = document.documentElement.clientHeight
  75. || document.body.clientHeight
  76. || window.innerHeight;
  77.  
  78. const maxWidth = width + threshold;
  79. const maxHeight = height + threshold;
  80.  
  81. return ((
  82. (top >= -threshold && top <= maxHeight) || (bottom >= -threshold && bottom <= maxHeight)
  83. )
  84. && (
  85. (left >= -threshold && left <= maxWidth) || (right >= -threshold && right <= maxWidth)
  86. ));
  87. }
  88.  
  89. setTrigger = (ref) => {
  90. this.trigger = ref;
  91. };
  92.  
  93. render() {
  94. const { children } = this.props;
  95.  
  96. return (
  97. <span ref={this.setTrigger}>
  98. {children}
  99. </span>
  100. );
  101. }
  102. }
Add Comment
Please, Sign In to add comment