BackTop 컴포넌트 만들기

2019.04.25(7달 전)

블로그 개발 중 스크롤이 되었을 때, 상위로 이동시키는 BackTop을 적용하기 위해 Ant.Design의 BackTop 컴포넌트를 사용하려고 했다.

하지만 Ant.Design의 BackTop 컴포넌트를 적용해보니 잘 안된다. 따라서 직접 BackTop 컴포넌트를 구현하기로 결정했다.

Ant.Design 홈페이지에선 잘 동작한다.

구현 코드는 다음과 같다.

BackTop.tsx

import React, { Component } from 'react';
import { Icon, Button } from 'antd';
import throttle from 'lodash/throttle';

interface IProps {
    scrollStep?: number;
    delayMs: number;
    target: string;
}

class BackTop extends Component<IProps> {
    private content: Element;
    private timeoutId: NodeJS.Timeout;
    private intervalId: NodeJS.Timeout;

    static defaultProps = {
        scrollStep: 50,
        delayMs: 16,
    }

    componentDidMount() {
        const { target } = this.props;
        if (target) {
            this.content = document.querySelector(target);
            this.content.addEventListener('scroll', this.onScroll);
        }
    }

    onScroll = throttle((e) => {
        if (e.target.scrollTop >= 64) {
            const backtop = document.querySelector('.backtop');
            if (backtop) {
                content.classList.add('visible');
            }
            if (this.timeoutId) {
                clearTimeout(this.timeoutId);
            }
            this.timeoutId = setTimeout(() => {
                if (backtop) {
                    backtop.classList.remove('visible');
                }
            }, 1500);
        } else {
            const backtop = document.querySelector('.backtop');
            if (backtop) {
                backtop.classList.remove('visible');
            }
        }
    }, 200);

    scrollStep = () => {
        if (this.content.scrollTop === 0) {
            clearInterval(this.intervalId);
        }
        this.content.scrollTo(0, this.content.scrollTop - this.props.scrollStep);
    }

    scrollToTop = () => {
        if (this.content && this.props.target) {
            this.intervalId = setInterval(() => {
                this.scrollStep();
            }, this.props.delayMs);
        }
    }

    render() {
        return (
            <Button className="backtop" type="primary" shape="circle" onClick={this.scrollToTop}>
                <Icon type="to-top" style={{ fontSize: '1.25rem' }} />
            </Button>
        );
    }
}

export default BackTop;

backtop.less

.backtop {
    width: 40px;
    height: 40px;
    position: fixed;
    bottom: 16px;
    right: 16px;
    transition: all 0.25s ease-in;
    transform: translateY(10px);
    opacity: 0;
    &.visible {
        opacity: 1;
        transform: translateY(0);
    }
}

BackTop이 적용된 화면이다.

blog-backtop-apply

react
component
backtop
Sung Gyun Oh
Sung Gyun Oh
Hello world!