index.tsx 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. import { defineComponent, onMounted, reactive, ref, watch } from 'vue';
  2. import styles from './index.module.less';
  3. export default defineComponent({
  4. name: 'TheNoticeBar',
  5. props: {
  6. text: {
  7. type: String,
  8. default: ''
  9. },
  10. isAnimation: {
  11. type: Boolean,
  12. default: false
  13. }
  14. },
  15. setup(props) {
  16. const wrapRef = ref();
  17. const contentRef = ref();
  18. const notiData = reactive({
  19. isActive: false,
  20. wrapWidth: 0,
  21. contentWidth: 0,
  22. contentStyle: {
  23. transitionDuration: '0s',
  24. transform: 'translateX(0px)'
  25. },
  26. time: null as any
  27. });
  28. const init = () => {
  29. if (notiData.isActive || !contentRef.value || !wrapRef.value) return;
  30. notiData.isActive = true;
  31. notiData.contentWidth = contentRef.value.getBoundingClientRect().width;
  32. notiData.wrapWidth = wrapRef.value.getBoundingClientRect().width;
  33. startAnimate();
  34. };
  35. const startAnimate = () => {
  36. if (notiData.contentWidth <= notiData.wrapWidth || !notiData.isActive) {
  37. notiData.contentStyle.transitionDuration = '0s';
  38. notiData.contentStyle.transform = 'translateX(0px)';
  39. return;
  40. }
  41. notiData.contentStyle.transitionDuration = '5s';
  42. notiData.contentStyle.transform = 'translateX(-100%)';
  43. notiData.time = setTimeout(() => {
  44. notiData.contentStyle.transitionDuration = '0s';
  45. notiData.contentStyle.transform = `translateX(${notiData.wrapWidth}px)`;
  46. requestAnimationFrame(() => {
  47. requestAnimationFrame(() => {
  48. startAnimate();
  49. })
  50. });
  51. }, 5 * 1000);
  52. };
  53. const stopAnimate = () => {
  54. clearTimeout(notiData.time);
  55. notiData.isActive = false;
  56. notiData.contentStyle.transitionDuration = '0s';
  57. notiData.contentStyle.transform = 'translateX(0px)';
  58. notiData.time = null;
  59. };
  60. watch(() => props.isAnimation, (val) => {
  61. if (val) {
  62. init();
  63. } else {
  64. stopAnimate();
  65. }
  66. })
  67. return () => (
  68. <div
  69. ref={wrapRef}
  70. class={styles.wrap}
  71. onMouseenter={() => init()}
  72. onMouseleave={() => stopAnimate()}>
  73. <div
  74. ref={contentRef}
  75. style={notiData.contentStyle}
  76. class={styles.notice}>
  77. {props.text}
  78. </div>
  79. </div>
  80. );
  81. }
  82. });