Прокрутка прокручиваемого div замораживает движущийся контент

#css #reactjs

Вопрос:

Когда я вертикально прокручиваю движущийся div, часть содержимого зависает. Мне интересно, как бы я это исправил. Это также не согласуется, так как нажатие кнопки «Пуск/стоп» иногда устраняет проблему на несколько секунд. Очень смущен.

 import { useEffect, useRef, useState } from "https://cdn.skypack.dev/react"
import ReactDOM from "https://cdn.skypack.dev/react-dom"

const Graph = ({ references: { trackerRef, wholeRef } }) => {
    return (
        <div
            ref={wholeRef}
            style={{
                overflow: 'scroll',
                height: '400px',
                backgroundColor: '#333',
                cursor: 'default',
                userSelect: 'none'
            }}
        >
            <div style={{ position: 'relative' }}>
                <div>
                    {(() => {
                        const items = []

                        for (let i = 1; i < 100; i  ) {
                            items.push(
                                <div
                                    key={i}
                                    style={{
                                        position: 'absolute',
                                        left: i * 1000,
                                        height: '100%',
                                        display: 'flex',
                                    }}
                                >
                                    <div
                                        style={{
                                            width: '1px',
                                            backgroundColor: '#888',
                                        }}
                                    ></div>
                                    <div style={{ color: '#ddd', marginLeft: 8, fontSize: 14 }}>
                                        {i}s
                                    </div>
                                </div>
                            )
                        }

                        return items
                    })()}
                    {(() => {
                        const items = []

                        for (let i = 1; i < 1000; i  ) {
                            if ((i * 100) % 1000 === 0) continue

                            items.push(
                                <div
                                    key={i}
                                    style={{
                                        position: 'absolute',
                                        left: i * 100,
                                        height: '100%',
                                        display: 'flex',
                                    }}
                                >
                                    <div
                                        style={{
                                            width: '1px',
                                            backgroundColor: '#555',
                                        }}
                                    ></div>
                                    <div style={{ color: '#aaa', marginLeft: 5, fontSize: 10 }}>
                                        {i * 100}ms
                                    </div>
                                </div>
                            )
                        }

                        return items
                    })()}
                    <div
                        ref={trackerRef}
                        style={{
                            position: 'absolute',
                            height: '100%',
                            display: 'flex',
                            width: '1px',
                            backgroundColor: 'lightgreen',
                        }}
                    ></div>
                </div>
                <div>
                    <div style={{ height: '2000px', width: '20px' }}></div>
                </div>
            </div>
        </div>
    )
}

const App = () => {
    const trackerRef = useRef(null)
    const wholeRef = useRef(null)
    const [paused, setPaused] = useState(false)
    const animationFrames = useRef([]).current
    const intervals = useRef([]).current
    const time = useRef(0)

    useEffect(() => {
        // Increase time when unpaused
        intervals.push(setInterval(() => !paused amp;amp; (time.current  = 1), 1))
    }, [paused])

    useEffect(() => {
        const refreshTrackbar = () => {
            if (trackerRef.current amp;amp; wholeRef.current amp;amp; !paused) {
                trackerRef.current.style.left = time.current   'px'
                wholeRef.current.scrollLeft = time.current - 100
                requestAnimationFrame(refreshTrackbar)
            }
        }

        animationFrames.push(requestAnimationFrame(refreshTrackbar))
    }, [paused])

    return (
        <>
            <h1>Scrollbug</h1>
            <button
                onClick={() => {
                    if (paused) {
                        setPaused(false)
                    } else {
                        setPaused(true)
                        animationFrames.forEach(frame => cancelAnimationFrame(frame))
                        intervals.forEach(interval => clearInterval(interval))
                    }
                }}
            >
                {paused ? 'Start' : 'Stop'}
            </button>
            <br />
            <br />
            <Graph references={{ trackerRef, wholeRef }} />
        </>
    )
}

ReactDOM.render(<App />, document.getElementById("root"))
 

Вот кодовый код, чтобы проверить проблему самостоятельно

https://codepen.io/springer268/pen/PomjVvw

РЕДАКТИРОВАТЬ: Итак, я попробовал этот код на своем mac, и ошибки не произошло, что заставляет меня думать, что это проблема, связанная с версией/платформой Chrome, а не со мной.

Комментарии:

1. Функция, которую вы написали , является очень дорогой операцией , поверх нее событие прокрутки-это перегрузка , из-за этого она отстает , вот несколько советов , которые могут помочь уменьшить ее , не используйте цикл внутри компонента React, он будет выполняться каждый раз, попробуйте получить значение только один раз, прежде чем compoent отрисовает

2. Хорошая идея. Преобразовали циклы в их собственные компоненты, и производительность действительно кажется лучше. К сожалению, все еще испытываю заморозки.

Ответ №1:

Я не совсем уверен, как заставить его перестать замерзать, но если бы вы добавили overflow:scroll; в свой #root div с большей высотой, чем у вашего бокового прокрутки, вы могли бы прокрутить его без замерзания.

Создание боковой прокрутки div определенной высоты также overflow-y: hidden; может помочь.

Своего рода обходной путь, но он работает.

Комментарии:

1. вопрос не в этом