使用原生js + css 实现一个文字轮播效果(一)

1、思路:

因为offsetTop、scrollTop等不属于css属性,所以这些无法用css动画或过度来实现。首先想到的是使用position + top 定位结合 transition 来实现。

2、效果:

使用原生js + css 实现一个文字轮播效果(一)

3、原生代码:

<!DOCTYPE html>
<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title></title>
    <script language="javascript" type="text/javascript">
       window.onload=function(){
        var boxContainer =  document.getElementById(boxContainer);
        var ulList = document.getElementById(ulList);
        var ulListLen = ulList.children.length;
        var speed = 3000;//移动速度,值越大速度越慢
        var timer = null;//定时器
        var liHeight = 30;//li列表的高度
              function marquee() {
          console.log(ulList.offsetTop, ulList.style.top)
          if (ulList.offsetTop <= -(liHeight * (ulListLen - 1))){//判断复制的信息是否到达box的最左边
            ulList.style.top = 0;
            ulList.style.transition = none;
            marquee();
          }else {
            ulList.style.transition = all .5s ease-in-out;
            ulList.style.top = (ulList.offsetTop - liHeight) + px;
          }
        }
        timer = setInterval(marquee, speed);//设置定时器
       }
    </script>
    <style>
      #boxContainer{
        overflow:hidden;
        height:32px;
        width:300px;
        border:1px solid #000;
        position: relative;
      }
        .liItems{
            width: 300px;
        height: 30px;
        line-height: 30px;
        text-align: center;
        }
      #ulList{
        list-style-type: disc;
        margin-block: 0;
        margin-inline: 0;
        padding-inline: 0;
        position: absolute;
        top: 0;
        /* transition: all .5s ease-in-out; */
      }
    </style>
</head>
<body>
<div  id="boxContainer">
  <ul id="ulList">
    <li class="liItems">人生在世须尽欢 莫使金樽空对月</li>
    <li class="liItems">我寄愁心与明月,随风直到夜郎西</li>
    <li class="liItems">不是花中偏爱菊,此花开尽更无花</li>
    <li class="liItems">辛苦遭逢起一经,干戈寥落四周星</li>
    <li class="liItems">山河破碎风飘絮,身世浮沉雨打萍。</li>
    <li class="liItems">惶恐滩头说惶恐,零丁洋里叹零丁。</li>
    <li class="liItems">人生自古谁无死?留取丹心照汗青。</li>

    <!-- 将第一条信息复制 -->
    <li class="liItems">人生在世须尽欢 莫使金樽空对月</li>
  </ul>
</div>
</body>
</html>

4、封装使用在react项目中:

import React, { useEffect, useRef } from ‘react‘;
import { experimentalStyled } from ‘@material-ui/core‘;
import moment from ‘moment‘;
import PropTypes from ‘prop-types‘;

moment.locale(‘zh-cn‘);

const MainLayoutContent = experimentalStyled(‘div‘)({
  margin: ‘0 20px‘,
  overflow: ‘hidden‘,
  height: ‘100%‘,
  display: ‘flex‘,
  alignItems: ‘center‘,
  justifyContent: ‘center‘,
});

function WorldCarousel({
  dataList,
  liHeight,
  speed,
  liWidth
}) {
  const boxContentRef = useRef();
  const ulRef = useRef();
  const timerRef = useRef();

  const marquee = () => {
    const ulListLen = ulRef.current.children.length;
    if (ulRef.current.offsetTop <= -(liHeight * (ulListLen - 1))) { // 判断复制的信息是否到达box的最左边
      ulRef.current.style.top = 0;
      ulRef.current.style.transition = ‘none‘;
      marquee();
    } else {
      ulRef.current.style.transition = ‘all .5s ease-in-out‘;
      ulRef.current.style.top = `${ulRef.current.offsetTop - liHeight}px`;
    }
  };

  const setEffectFunction = () => {
    timerRef.current = setInterval(marquee, speed * 1000);
  };

  const removeEffectFunction = () => {
    clearInterval(timerRef.current);
  };

  useEffect(() => {
    timerRef.current = setInterval(marquee, speed * 1000); // 设置定时器
    boxContentRef.current.addEventListener(‘mouseenter‘, removeEffectFunction);
    boxContentRef.current.addEventListener(‘mouseleave‘, setEffectFunction);
    return () => {
      clearInterval(timerRef.current);
      boxContentRef.current.removeEventListener(‘mouseleave‘, setEffectFunction);
      boxContentRef.current.removeEventListener(‘mouseenter‘, removeEffectFunction);
    };
  }, []);

  const content = () => {
    dataList?.push(dataList[0]);
    return dataList.map((item, index) => (
      <li
        key={(index === (dataList.length - 1)) ? ‘firstDataCope‘ : item.data}
        style={{
          width: liWidth,
          height: liHeight,
          lineHeight: `${liHeight}px`,
          textAlign: ‘center‘,
          fontSize: ‘18px‘,
        }}
      >
        <span>{ item.content }</span>
        &nbsp;&nbsp;
        <span>{ moment(item.data, ‘YYYYMMDD‘).fromNow() }</span>
      </li>
    ));
  };

  return (
    <MainLayoutContent>
      <div
        ref={boxContentRef}
        style={{
          overflow: ‘hidden‘,
          height: `${liHeight}px`,
          width: liWidth,
          border: 0,
          position: ‘relative‘
        }}
      >
        <ul
          ref={ulRef}
          style={{
            listStyleType: ‘disc‘,
            marginBlock: 0,
            marginInline: 0,
            paddingInline: 0,
            position: ‘absolute‘,
            top: 0
          }}
        >
          { content() }
        </ul>
      </div>
    </MainLayoutContent>
  );
}

WorldCarousel.propTypes = {
  dataList: PropTypes.array, // 数据列表
  liHeight: PropTypes.number, // 移动速度,值越大速度越慢
  liWidth: PropTypes.number, // 宽度
  speed: PropTypes.number, // li列表的高度
};

WorldCarousel.defaultProps = {
  dataList: [],
  liHeight: 30,
  liWidth: 300,
  speed: 3,
};

export default WorldCarousel;

5、使用:

const dataList = [
  {
    data: 20200101,
    address: ‘杭州‘,
    content: ‘元旦抓娃娃开心啊‘,
  },
  {
    data: 20200202,
    address: ‘杭州‘,
    content: ‘二月二,炒大豆‘,
  },
  {
    data: 20200303,
    address: ‘杭州‘,
    content: ‘西湖美景,三月天哎‘,
  },
  {
    data: 20200404,
    address: ‘杭州‘,
    content: ‘愚人节快乐‘,
  },
  {
    data: 20200505,
    address: ‘杭州‘,
    content: ‘五月,我们来啦‘,
  },
  {
    data: 202006066,
    address: ‘杭州‘,
    content: ‘六月的雨,下个不停...‘,
  },
];

<WorldCarousel dataList={dataList} liHeight={60} speed={3} />

 6、效果展示:

使用原生js + css 实现一个文字轮播效果(一)

 

使用原生js + css 实现一个文字轮播效果(一)

上一篇:Django创建表单上传图片


下一篇:mac版 eclipse 只能run不能debug的解决方案