antd项目如何实现彩蛋效果

我报名参加金石计划1期应战——分割10万奖池,这是我的第2篇文章,点击检查活动概况

马上就要过节了,想把自己的项目搞得酷炫一些,对整个网站的按钮添加图标、飘花作用、首屏大图展现、顶部导航背景图,于是就写了这一遍文字,如有爱好的小伙伴们能够一同学习进步,仅供参考。

1、作用图

作用图如下:

antd项目如何实现彩蛋效果

2、首要在components目录下创立Transform目录,包含index.css、index.js

index.css首要界说了几种漂浮时的动画轨道

/* index.css */
.animation1 {
  display: inline-block;
  position: fixed;
  z-index: 2000;
  opacity: 0;
  top: -40px;
  left: -40px;
  animation: animation1 8s linear infinite;
}
.animation2 {
  display: inline-block;
  position: fixed;
  z-index: 2000;
  opacity: 0;
  top: -40px;
  left: -40px;
  animation: animation2 9s 1s linear infinite;
}
.animation3 {
  display: inline-block;
  position: fixed;
  z-index: 2000;
  opacity: 0;
  top: -40px;
  left: -40px;
  animation: animation3 9s linear infinite;
}
.animation4 {
  display: inline-block;
  position: fixed;
  z-index: 2000;
  opacity: 0;
  top: -40px;
  left: -40px;
  animation: animation4 9s 2s linear infinite;
}
.animation5 {
  display: inline-block;
  position: fixed;
  z-index: 2000;
  opacity: 0;
  top: -40px;
  left: -40px;
  animation: animation5 9s 1s linear infinite;
}
.animation6 {
  display: inline-block;
  position: fixed;
  z-index: 2000;
  opacity: 0;
  top: -40px;
  left: -40px;
  animation: animation6 9s 3s linear infinite;
}
.animation7 {
  display: inline-block;
  position: fixed;
  z-index: 2000;
  opacity: 0;
  top: -40px;
  left: -40px;
  animation: animation7 8s linear infinite;
}
.animation8 {
  display: inline-block;
  position: fixed;
  z-index: 2000;
  opacity: 0;
  top: -40px;
  right: -200px;
  animation: animation8 10s linear infinite;
}
@keyframes animation1 {
  0% {
    top: 50%;
    left: -80px;
    opacity: 0;
  }
  90% {
    opacity: 1;
  }
  100% {
    top: 100%;
    left: 20%;
    opacity: 0;
  }
}
@keyframes animation2 {
  0% {
    top: 80px;
    left: -80px;
    opacity: 0;
  }
  90% {
    opacity: 1;
  }
  100% {
    top: 100%;
    left: 50%;
    opacity: 0;
  }
}
@keyframes animation3 {
  0% {
    top: 30%;
    left: 20%;
    opacity: 0;
  }
  90% {
    opacity: 1;
  }
  100% {
    top: 110%;
    left: 75%;
    opacity: 0;
  }
}
@keyframes animation4 {
  0% {
    top: -80px;
    left: -80px;
    opacity: 0;
  }
  90% {
    opacity: 1;
  }
  100% {
    top: 101%;
    left: 80%;
    opacity: 0;
  }
}
@keyframes animation5 {
  0% {
    top: 10%;
    left: 40%;
    opacity: 0;
  }
  90% {
    opacity: 1;
  }
  100% {
    top: 100%;
    left: 120%;
    opacity: 0;
  }
}
@keyframes animation6 {
  0% {
    top: -80px;
    left: 50%;
    opacity: 0;
  }
  90% {
    opacity: 1;
  }
  100% {
    top: 100%;
    left: 110%;
    opacity: 0;
  }
}
@keyframes animation7 {
  0% {
    top: -80px;
    left: 70%;
    opacity: 0;
  }
  90% {
    opacity: 1;
  }
  100% {
    top: 50%;
    left: 110%;
    opacity: 0;
  }
}
@keyframes animation8 {
  0% {
    top: -75px;
    right: -200px;
    opacity: 0;
    transform: rotate(0)
  }
  50% {
    transform: rotate(-30deg)
  }
  90% {
    opacity: 1;
  }
  100% {
    top: 100%;
    right: 100%;
    transform: rotate(0);
    opacity: 0;
  }
}
:global .switchStyle {
  z-index: 31;
}
.shadeWrapper {
  z-index: 1050;
  position: fixed;
  top: 0;
  left: 200px;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.3);
  display: flex;
  justify-content: center;
  align-items: center;
}
.shadeWrapper .shadeClose {
  cursor: pointer;
  font-size: 30px;
  position: absolute;
  right: 30px;
  top: 30px;
  color: #fff;
}

index.js是首要的逻辑代码,下面临代码进行分析,完好代码如下

  • 进入页面调用this.getTableList() 办法,获取展现的图片列表,包含btn(按钮)、burst(首图)、float(漂浮)、header(顶部);
  • 紧接着调用this.initStyle() 办法,首要对列表进行循环,挑选出当时时间在开端时间、结束时间之间的一条数据,然后再依据showoption对展现方位进行判别,并增加flag标志;
  • 接下来调用this.loadStyleString(sty) ,传入处理后的款式字符串,创立style标签,添加到head中。

对于漂浮的特效,因为只界说了七种轨道,所以最多上传七张图片,initList(data, cb) 办法进行了处理,假如不行七张,则会递归重复传入数组,超越七张后截取前七张,然后回调。

对于首屏大图,一天内只出现一次,封闭时会一起设置localStorage的有效期,设置有效期一天,这样就能够判别当时日期是否和localStorage中存的相同啦。

顶部的敞开、封闭特效只对float(漂浮)做了控制,有效期为七天,超时会重新显现。

// index.js
import React, { PureComponent } from 'react';
import { Switch } from 'antd';
import { CloseCircleOutlined } from '@ant-design/icons';
import './index.css';
import moment from 'moment';
Storage.prototype.setExpire = (key, value, expire) => {
  let obj = {
    data: value,
    time: Date.now(),
    expire: expire,
  };
  //localStorage 设置的值不能为对象,转为json字符串
  localStorage.setItem(key, JSON.stringify(obj));
};
Storage.prototype.getExpire = (key) => {
  let val = localStorage.getItem(key);
  if (!val) {
    return val;
  }
  val = JSON.parse(val);
  if (Date.now() - val.time > val.expire) {
    localStorage.removeItem(key);
    return null;
  }
  return val.data;
};
export default class Transform extends PureComponent {
  constructor(props) {
    super(props);
    let storage = localStorage.getExpire(`floatFlag`);
    if (storage == 'false' || storage == false) {
      storage = false;
    } else {
      storage = true;
    }
    this.state = {
      showBurst: false, // burst
      pathBurst: '', // burst path
      timeBurst: '', // burst time
      showFloat: false,
      showBtn: false,
      floatFlag: storage,
      floatList: [],
    };
  }
  componentDidMount() {
    this.getTableList();
  }
  // 获取七条数据
  initList(data, cb) {
    if (data && data.length < 7) {
      let dt = data.concat(data);
      this.initList(dt, cb);
    } else {
      cb(data.slice(0, 7));
    }
  }
  // 获取列表
  getTableList() {
    let list = [
      {
        showoption: 'btn',
        starttime: '2022-09-03',
        endtime: '2023-09-03',
        imagaddress: [
          {
            path: 'https://www.6hu.cc/wp-content/uploads/2022/10/1666727624-07f4ad79aa5cb16.png',
          },
        ],
      },
      {
        showoption: 'burst',
        starttime: '2022-09-03',
        endtime: '2023-09-03',
        imagaddress: [
          {
            path: 'https://www.6hu.cc/wp-content/uploads/2022/10/1666727625-1c35c0202163a76.jpeg',
          },
        ],
      },
      {
        showoption: 'float',
        starttime: '2022-09-03',
        endtime: '2023-09-03',
        imagaddress: [
          {
            path: 'https://www.6hu.cc/wp-content/uploads/2022/10/1666727624-07f4ad79aa5cb16.png',
          },
          {
            path: 'https://www.6hu.cc/wp-content/uploads/2022/10/1666727624-07f4ad79aa5cb16.png',
          },
        ],
      },
      {
        showoption: 'header',
        starttime: '2022-09-03',
        endtime: '2023-09-03',
        imagaddress: [
          {
            path: 'https://www.6hu.cc/wp-content/uploads/2022/10/1666727625-1c35c0202163a76.jpeg',
          },
        ],
      },
    ];
    this.setState(
      {
        tableList: list,
      },
      () => {
        this.initStyle();
      },
    );
  }
  add0(m) {
    return m < 10 ? '0' + m : m;
  }
  initStyle() {
    try {
      let tableList = JSON.parse(JSON.stringify(this.state.tableList));
      let resDt = [];
      let time = new Date();
      var y = time.getFullYear();
      var m = time.getMonth() + 1;
      var d = time.getDate();
      var H = time.getHours();
      var FEN = time.getMinutes();
      var Miao = time.getSeconds();
      let newDe = moment(
        `${y}-${this.add0(m)}-${this.add0(d)} ${this.add0(H)}:${this.add0(FEN)}:${this.add0(Miao)}`,
      ).format('YYYY-MM-DD HH:mm:ss');
      for (let index = 0; index < tableList.length; index++) {
        const element = tableList[index];
        let strDe = moment(`${element.starttime} 00:00:00`).format('YYYY-MM-DD HH:mm:ss');
        let endDe = moment(`${element.endtime} 23:59:59`).format('YYYY-MM-DD HH:mm:ss');
        if (moment(strDe).isBefore(moment(newDe)) && moment(newDe).isBefore(moment(endDe))) {
          resDt.push(element);
          // break;
        }
      }
      if (resDt && resDt.length > 0) {
        for (let idx = 0; idx < resDt.length; idx++) {
          const element = resDt[idx];
          if (element.showoption == 'float') {
            let str = element.imagaddress;
            let list = [];
            this.initList(str, (dt) => {
              list = dt;
            });
            this.setState({
              showFloat: true,
              showBtn: true,
              floatList: list,
            });
          } else if (element.showoption == 'btn') {
            let strBtn = element.imagaddress[0].path;
            let sty = `
              .ant-btn::before {
                  content: " ";
                  display: block;
                  background: url(${strBtn}) no-repeat!important;
                  background-size: 20px !important;
                  height: 100%;
                  width: 100%;
                  position: absolute;
                  top: -10px;
                  left: -10px;
                  opacity: 1;
              }
              `;
            let sty2 = `
              .ant-btn::before {
                  content: " ";
                  display: block;
                  background: transparent!important;
                  background-size: 20px !important;
                  height: 100%;
                  width: 100%;
                  position: absolute;
                  top: -10px;
                  left: -10px;
                  opacity: 1;
              }
              `;
            this.loadStyleString(sty);
          } else if (element.showoption == 'burst') {
            let tmZl = `${y}-${this.add0(m)}-${this.add0(d)}`;
            let flag = true;
            if (localStorage.getExpire(`timeBurstLocal`) == `${tmZl}`) {
              flag = false;
            }
            this.setState({
              showBurst: flag,
              pathBurst: element.imagaddress[0].path,
              timeBurst: tmZl,
            });
          } else if (element.showoption == 'header') {
            let strH = element.imagaddress[0].path;
            let styH = `
              .ant-pro-global-header {
                background-image: url(${strH});
                background-repeat: no-repeat;
                background-size: cover;
                // opacity: 0.8;
              }
              `;
            this.loadStyleString(styH);
          }
        }
      } else {
        this.setState({
          showFloat: false,
          showBtn: false,
          floatFlag: false,
          floatList: [],
        });
      }
    } catch (error) {
      this.setState({
        showFloat: false,
        showBtn: false,
        floatFlag: false,
        floatList: [],
      });
    }
  }
  loadStyleString(css) {
    var style = document.createElement('style');
    style.type = 'text/css';
    try {
      style.appendChild(document.createTextNode(css));
    } catch (ex) {
      style.styleSheet.cssText = css; //兼容IE
    }
    var head = document.getElementsByTagName('head')[0];
    head.appendChild(style);
  }
  // burst封闭
  CloseBurst() {
    this.setState(
      {
        showBurst: false,
        timeBurstLocal: this.state.timeBurst,
      },
      () => {
        // 有效期两天
        localStorage.setExpire(`timeBurstLocal`, `${this.state.timeBurstLocal}`, 86400000 * 2);
      },
    );
  }
  // 调用示例
  //   loadStyleString("body{background-color:red}");
  selectHtml() {
    if (this.state.showFloat && this.state.floatFlag) {
      return (
        <React.Fragment>
          {this.state.floatList
            ? this.state.floatList.map((item, index) => {
                let width = Math.round(Math.random() * 20 + 30);
                return (
                  <div key={index} className={`animation${index}`}>
                    <img width={width} src={item.path} />
                  </div>
                );
              })
            : ''}
        </React.Fragment>
      );
    } else {
      return null;
    }
  }
  // 调用示例
  selectHtmlBurst() {
    var tempHeightRight = document.documentElement.clientHeight - 100;
    if (this.state.showBurst && this.state.pathBurst) {
      return (
        <React.Fragment>
          <div
            onClick={() => {
              this.CloseBurst();
            }}
            className="shadeWrapper"
            style={{ cursor: 'pointer' }}
          >
            <div
              onClick={() => {
                this.CloseBurst();
              }}
              className="shadeClose"
            >
              <CloseCircleOutlined />
            </div>
            <div>
              <img style={{ maxHeight: tempHeightRight }} src={this.state.pathBurst} />
            </div>
          </div>
        </React.Fragment>
      );
    } else {
      return null;
    }
  }
  // 敞开/封闭特效
  switchCheck(e) {
    // 有效期七天
    localStorage.setExpire(`floatFlag`, e, 86400000 * 7);
    this.setState(
      {
        floatFlag: e,
      },
      () => {
        console.log('e', e);
        // this.initStyle();
      },
    );
  }
  render() {
    return (
      <React.Fragment>
        {this.state.showBtn ? (
          <div
            style={{
              display: 'inline-block',
              position: 'fixed',
              top: '10px',
              right: '300px',
              zIndex: '31',
            }}
          >
            <Switch
              checkedChildren="封闭特效"
              unCheckedChildren="敞开特效"
              checked={this.state.floatFlag}
              onChange={(e) => this.switchCheck(e)}
            />
          </div>
        ) : null}
        {this.selectHtmlBurst()}
        {this.selectHtml()}
      </React.Fragment>
    );
  }
}

3、大局引入

在layout布局中大局引入组件

评论

发表回复