滑动表

116 阅读2分钟

tsx

import React,{ useCallback, useEffect, useRef, useState } from 'react'
import list_Data from './data'

import './index.scss'

interface listData {
  userName: string,
  text: string,
  likes: number
}
const SlideListItemModel = ({ data,onClose}: { data: listData ,onClose:()=>void}) => {
  let { userName, text, likes } = data
  return (
    <div className='list-item-model'>
      <div onClick={onClose} className="list-item-model-close">关闭</div>
      <div>{userName}</div>
      <div>{text}</div>
      <div>{likes}</div>
    </div>
  )
}

const SlideListItem = ({ data,autoScroll }: { data: listData,autoScroll:()=>void }) => {
  let { userName, text, likes } = data
  let [isShow, setIsShow] = useState(false)
  const showModel = () => {
    setIsShow(true)
  }
  const closeModel = () => {
    setIsShow(false)
    autoScroll()
  }
  return (
    <>
      <div className='slide-list-item' onClick={showModel}>
        <div className='slide-list-item-avatar'>
          <img
            className='slide-list-item-avatar-img'
            src={"https://p26-passport.byteacctimg.com/img/user-avatar/1e1b1258b43b135af6a1c7b591ab95b5~300x300.image"}
            alt="" />
        </div>
        <div className='slide-list-item-info'>
          <div className='slide-list-item-info-head'>
            <div className='slide-list-item-info-username'>{userName}</div>
            <div className='slide-list-item-info-likes'>{likes}</div>
          </div>
          <div className='slide-list-item-info-content'>
            {text}
          </div>
        </div>
      </div>
      {
        isShow && <SlideListItemModel data={data} onClose={closeModel}/>
      }
    </>

  )
}

const SlideList = ({ data }: {
  data: listData[]
}) => {
  let adata = [...data.slice(0, 10), ...data.slice(0, 10)]
  let [isScrolling, setIsScrolling] = useState(true)
  let wrapper = useRef<HTMLDivElement>(null)
  let timer = useRef<number>()

  useEffect(() => {
    let step = 1
    const render = () => {
      if (wrapper.current) {
        wrapper.current.scrollLeft += step;
        if (wrapper.current.offsetWidth + wrapper.current.scrollLeft >= wrapper.current.scrollWidth / 2) {
          wrapper.current.scrollLeft %= wrapper.current.scrollWidth / 2;
        }
        timer.current = window.requestAnimationFrame(render)
      }
    }
    isScrolling && render()
    return () => {
      timer.current && window.cancelAnimationFrame(timer.current)
    }
  }, [isScrolling]);

  const MouseDown = useCallback(() => {
    setIsScrolling(false)
  }, [])
  const autoScroll = useCallback(()=>{
    let timer = setTimeout(() => setIsScrolling(true), 3000)
    return () => {
      clearTimeout(timer)
    }
  },[])
  return (
    <>
      <div className="slide-list" ref={wrapper}
        onMouseDown={MouseDown}
      >
        {
          adata.map((i, index) => <SlideListItem key={index} data={i} autoScroll={autoScroll}/>)
        }
      </div>
    </>

  )
}

const App = ()=>{
  console.log(list_Data);
  return (
    <div>
      <SlideList data={list_Data}/>
    </div>
  )
}
export default ()=> <App/>

CSS

.slide-list{
  margin: 0 auto;
  height: 150px;
  max-width: 375px;
  background-image: linear-gradient(to top, #a18cd1 0%, #fbc2eb 100%);
  display: flex;
  flex-wrap: wrap;
  flex-direction: column;
  justify-content: center;
  overflow: auto;
  &::-webkit-scrollbar {
  display: none; /* Chrome Safari */
}
  .slide-list-item{
    background-image: linear-gradient(to top, #a8edea 0%, #fed6e3 100%);
    margin: 3px;
    padding: 3px;
    border: 1px solid #a18cd1;
    border-radius: 5px;
    display: flex;
    background-color: white;
    font-size: 8px;
    min-width: 110px;
    max-width: 150px;
    height: 50px;
    overflow: hidden;
    .slide-list-item-avatar{
      width: 40px;
      height: 40px;
      .slide-list-item-avatar-img{
        width: 100%;
        height: 100%;
      }
    }
    .slide-list-item-info{
      flex:1;
      .slide-list-item-info-head{
        height: 15px;
        position: relative;
        transform: scale(0.75);
        .slide-list-item-info-username{
          left: 5px;
          position: absolute;
        }
        .slide-list-item-info-likes{
          position: absolute;
          right: 5px;
        }
      }
      .slide-list-item-info-content{
        height: 28px;
        position: relative;
        bottom: 2px;
        line-height: 14px;
        transform: scale(0.8);
        display: -webkit-box;
        -webkit-box-orient: vertical;
        -webkit-line-clamp: 2;
        overflow: hidden;
      }
    }
  }
}
.list-item-model{
  position: absolute;
  top: 80px;
  left: 50%;
  transform: translateX(-50%);
  width: 325px;
  height: 400px;
  padding: 10px;
  background-color: gainsboro;
  z-index: 1;
  border: #a18cd1 1px solid;
  box-shadow: 0 0 3px 5px #a18cd1 ;
  border-radius: 5px;
  .list-item-model-close{
    position: absolute;
    right: 5px;
  }
}

data

export default [
  {
      "userName": "加生准",
      "text": "快将张列共民党青员回效意图非候美就结还科现太目般接。",
      "likes": 2587
  },
  {
      "userName": "都多音查",
      "text": "接全力们统红却京信要原形队速取片改写必养象放步划确。",
      "likes": 1201
  },
  {
      "userName": "难及",
      "text": "素日至感低候今口从那论合出情该得称面精。",
      "likes": 12112
  },
  {
      "userName": "老志率价",
      "text": "西五按人市己处千此约山品进段以际交引动厂现再中必才。",
      "likes": 546
  },
  {
      "userName": "表低济准",
      "text": "劳族除就是斗需车再没指山导自难流题的达节低务以队资确。",
      "likes": 2359
  },
  {
      "userName": "治其农据极",
      "text": "装国至接价权确被都经亲法口省率美低我老办。",
      "likes": 6793
  },
  {
      "userName": "是节",
      "text": "基等权书一军表还率中切亲称生值备。",
      "likes": 1541
  },
  {
      "userName": "月种型代",
      "text": "段米了算离连队记如决九养他几持系领须等价带。",
      "likes": 5389
  },
  {
      "userName": "条务立",
      "text": "文专去自应于同般情称会许江无应变分候置划都引统。",
      "likes": 9311
  },
  {
      "userName": "金月强",
      "text": "难无和阶通金眼自干么算如为斗各近身水真证况全。",
      "likes": 16010
  }
]