index.tsx 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. import React, { useRef, useEffect, useState } from 'react'
  2. import './index.less'
  3. import styled from 'styled-components'
  4. interface TextScrollProps {
  5. /**
  6. * 持续时间/s
  7. */
  8. duration: number,
  9. children: React.ReactElement,
  10. }
  11. function TextScroll(props: TextScrollProps) {
  12. const { duration, children } = props
  13. const defaultState = {
  14. contentWidth: 0,
  15. right: 0,
  16. duration,
  17. }
  18. const [state, setState] = useState(defaultState)
  19. let ref = useRef<HTMLParagraphElement>(null)
  20. useEffect(() => {
  21. const { offsetWidth, parentElement } = ref.current as HTMLParagraphElement
  22. setState({
  23. ...state,
  24. contentWidth: offsetWidth,
  25. right: parentElement!.offsetWidth,
  26. })
  27. }, [])
  28. const { contentWidth, right, duration: timing } = state
  29. const animationName = `marquee_${contentWidth}`
  30. console.log(11111, right, contentWidth);
  31. const Text = styled.div`
  32. position: relative;
  33. left: ${right}px;
  34. animation: ${animationName} ${timing}s linear infinite both;
  35. animation-play-state: running;
  36. animation-fill-mode: forwards;
  37. @keyframes ${animationName} {
  38. 0% {
  39. transform: translateX(0px);
  40. }
  41. 100% {
  42. transform: translateX(${contentWidth - right}px);
  43. }
  44. }
  45. `
  46. return (
  47. <div className="marquee_box">
  48. <Text ref={ref}>{children}</Text>
  49. </div>
  50. )
  51. }
  52. TextScroll.defaultProps = {
  53. content: '',
  54. duration: 3,
  55. }
  56. export default React.memo(TextScroll)