Задать вопрос
@alex_vma

Как правильно писать анимации?

Идея проста. Хочу создать компонент, внутрь которого я буду класть например текст или заголовок, задавать параметры, и если до этого компонента доскролить, то компонент анимируется.
Например:
<Animation timing='linear' position='left'>
<h1>Hello world</h1>
</Animation>


И вот сам код, который пытался написать я:
Component

import React, {useEffect, ReactDOM} from 'react';
import {makeStyles} from "@material-ui/core/styles";
import clsx from "clsx";


const useStyles = makeStyles({
    root: {
        overflow: 'hidden'
    },
    wrapper: {
        color: 'red'
    }
})

const Animation = (props) => {
    const classes = useStyles();

    function defineElementPosition(side){
        switch(side.position){
            case('left'):
                return 'translateX(-120%)'
            case('right'):
                return 'translateX(120%)'
            case('top'):
                return 'translateY(-120%)'
            case('bottom'):
                return 'translateY(120%)'
            default: return 'translateY(100%)'
        }
    }
    let styles = {
        transform: defineElementPosition(props.position),
        transition: props.transition,
        transitionTimingFunction: props.timing
    }
    useEffect(() => {
        window.addEventListener('scroll', () => {
            const elems = document.querySelectorAll('scroll-component');
            const clientWindowHeight = document.documentElement.clientHeight || window.innerHeight;
            elems.forEach(elem => {
                if(elem.getBoundingClientRect().top <= clientWindowHeight){
                    styles = {
                        transform: 'translate(0,0)',
                    }
                }
            })
        })
    })

    return(
        <div className={classes.root}>
            <div className={clsx(classes.wrapper, 'scroll-component')} style={styles}>
                {props.children}
            </div>
        </div>
    )
}
export default Animation;


Помогите исправить ошибки. не могу понять как правильно найти все элементы с определенным классом(так как ожидается что их будет неизвестное количество), и как правильно повесить обработчик скрола.
  • Вопрос задан
  • 61 просмотр
Подписаться 1 Простой 1 комментарий
Решения вопроса 1
@alex_vma Автор вопроса
Решил вопрос самостоятельно, возможно кому-то будет
полезно

import React, {useEffect, useState, useRef} from 'react';
import {makeStyles} from "@material-ui/core/styles";


const useStyles = makeStyles({
    root: {
        overflow: 'hidden',
        display: 'inline-block'
    },
    wrapper: {
        color: 'red',
        display: 'inline-block'
    }
})

const Animation = (props) => {
    const classes = useStyles();
    const [styles, setStyles] = useState({
        transform: defineElementPosition(props),
        transition: props.transition,
        transitionTimingFunction: props.timing,
        opacity: props.opacityEffect === true ? 0 : 1
    })

    const elementWrapperRef = useRef(null);

    function defineElementPosition(side){
        switch(side.position){
            case('left'):
                return `translateX(${side.deep !== undefined ? side.deep.offset + 'px' : '-120%' })`
            case('right'):
                return `translateX(${side.deep !== undefined ? side.deep.offset + 'px' : '120%' })`
            case('top'):
                return `translateY(${side.deep !== undefined ? side.deep.offset + 'px' : '-120%' })`
            case('bottom'):
                return `translateY(${side.deep !== undefined ? side.deep.offset + 'px' : '120%' })`
            default: return 'translateY(100%)'
        }
    }
    function scrollElement(){
        const clientWindowHeight = document.documentElement.clientHeight || window.innerHeight;
        if(elementWrapperRef.current.getBoundingClientRect().top <= clientWindowHeight){
            setStyles({...styles, transform: 'translate(0,0)', opacity: 1})
        }
    }

    useEffect(() => {
        window.addEventListener('scroll', scrollElement)
        return () => window.removeEventListener('scroll', scrollElement) // Сброс эффекта - исправляет утечку памяти
    }, [])


    return(
        <div className={classes.root}>
            <div className={classes.wrapper} style={styles} ref={elementWrapperRef}>
                {props.children}
            </div>
        </div>
    )
}
export default Animation;

Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы