Ленивый модуль загрузки изображений склонен к ошибке - PullRequest
0 голосов
/ 22 января 2020

Я пытаюсь реализовать некоторую ленивую загрузку фоновых изображений, которые загружаются асинхронно. Мое намерение состояло в том, чтобы отображать цвет фона, пока изображение не было загружено . Дополнительно изображения должны появляться с непрозрачностью перехода. - Это работает для Chrome. Но почему-то не для некоторых других браузеров, таких как Safari или для мобильных устройств. Часто не всегда, в этих средах либо нет перехода, либо цвет фона скоро исчезнет.

Как я могу улучшить свой код для достижения желаемого поведения?

Вы можете найти его в действии здесь.

class LazyImage extends Component {

    state = {
        src: null,
        transition: false
    };

    componentDidUpdate(prevProps, prevState, snapshot) {

        if (prevProps.image !== this.props.image) {
            this.setState({src: null, transition: false});
            this.loadImage();
        }
    }

    componentDidMount() {
        this.loadImage();
        setTimeout(() => {
            this.setState({transition: true});
        }, 100)
    }

    loadImage = () => {
        const src = this.props.image;

        const imageLoader = new Image();
        imageLoader.src = src;

        imageLoader.onload = () => {
            this.setState({src: src})
        };
    };

    classList = (classes) => {
        return Object
            .entries(classes)
            .filter(entry => entry[1])
            .map(entry => entry[0])
            .join(' ');
    };

    render() {
        const style = {
            backgroundImage: 'url(' + this.state.src + ')',
            transition: this.state.transition ? 'opacity .6s ease' : null
        };

        return(
            <div className="h-image-wrapper" style={{backgroundColor: !this.state.src ? this.props.bgColor : null}}>
                <div className={this.classList({
                    'h-image-holder': true,
                    'h-image-loaded': this.state.src
                })} style={style} />
            </div>
        );
    }
}
.h-image-holder {
    background-repeat: no-repeat;
    background-position: center;
    background-size: cover;
    will-change: opacity, transform;
    pointer-events: none;
    opacity: 0;
    width: 100%;
    height: 100%;
}

.h-image-wrapper {
    position: relative;
    width: 100%;
    height: 100%;
    will-change: transform;
    pointer-events: none;
}

.h-image-loaded {
    opacity: 1;
}
...