水平无限循环弹幕

by Mike Lin

HTML

<div id="app"></div>
<div id="app1"></div>

SCSS

.scroll-list{
  display: flex;
  &.horizon {
    flex-direction: row;
  }
  &.vertical{
    flex-direction: column;
  }
}

#app, #app1{
  overflow: hidden;
  width: 100%;
  position: absolute;
  top:0px;
  .bullet-screen{
    padding-top: 0.7567567567567568rem;
    height: 1.3783783783783783rem;
    transform: translateX(calc(100vw));
    .item{
      margin-left: 1.0810810810810811rem;
    }
  }
  .item{
    height: 0.6216216216216216rem;
    display: flex;
    padding: 0.16216216216216217rem 0.2702702702702703rem 0.13513513513513514rem 0.2702702702702703rem;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    background: rgba(255,255,255,0.8);
    border-radius: 12px;
  }
}

#app1{
  top: 30px;
}

React

class InfiniteScroll extends React.Component {
  componentDidMount() {
    const { animationName, scrollDirection } = this.props
    setTimeout(() => {
      if (this.scrollInstance) {
        const appendElementWidth = []
        const appendElement = []
        const visibleWidth = this.scrollInstance.clientWidth
        // 滚动的初始位置从视口的最右边开始,后面支持更多方向
        const initPosition = visibleWidth
        let scrollContainerWidth = 0
        let isCoverViewPort = false
        // 遍历滚动的所有元素
        for (let i = 0; i < this.scrollInstance.children.length; i += 1) {
          const style = this.scrollInstance.children[i].currentStyle || window.getComputedStyle(this.scrollInstance.children[i])
          // width 已经包含了border和padding,如果box-sizing变化了呢?
          const width = this.scrollInstance.children[i].offsetWidth// or use style.width
          const margin = parseFloat(style.marginLeft) + parseFloat(style.marginRight)

          const clientWidth = (width + margin)
          scrollContainerWidth += clientWidth
          // 保存需要追加到原有滚动元素的列表后面
          if (scrollContainerWidth < visibleWidth * 2 && !isCoverViewPort) {
            appendElementWidth.push(clientWidth)
            appendElement.push(this.scrollInstance.children[i].cloneNode(true))

            if (scrollContainerWidth >= visibleWidth && !isCoverViewPort) {
              isCoverViewPort = true
            }
          }
        }

        const isScrollWidthLargeViewPort = scrollContainerWidth > visibleWidth

        // const styleSheet = document.styleSheets[0]

        const keyframes = `
        @keyframes ${animationName}{
          from{
            transform: ${scrollDirection === 'horizon' ? `translateX(${isScrollWidthLargeViewPort ? 0 : initPosition}px)` : 'translateY(0px)'};
          }
          to {
            transform: ${scrollDirection === 'horizon' ? `translateX(-${scrollContainerWidth}px)` : `translateX(-${scrollContainerWidth}px)`};
          }
        }
        @-webkit-keyframes...