马上就要过节了,想把自己的项目搞得酷炫一些,对整个网站的按钮添加图标、飘花效果、首屏大图展示、顶部导航背景图,于是就写了这一遍文字,如有兴趣的小伙伴们可以一起学习进步,仅供参考。
1、效果图
效果图如下:
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://img-blog.csdnimg.cn/3e93fe58b6444c2c8165e85756118888.png', }, ], }, { showoption: 'burst', starttime: '2022-09-03', endtime: '2023-09-03', imagaddress: [ { path: 'https://img-blog.csdnimg.cn/a1c4ddc6b73b48c5a88512eba3a907fa.jpeg', }, ], }, { showoption: 'float', starttime: '2022-09-03', endtime: '2023-09-03', imagaddress: [ { path: 'https://img-blog.csdnimg.cn/3e93fe58b6444c2c8165e85756118888.png', }, { path: 'https://img-blog.csdnimg.cn/3e93fe58b6444c2c8165e85756118888.png', }, ], }, { showoption: 'header', starttime: '2022-09-03', endtime: '2023-09-03', imagaddress: [ { path: 'https://img-blog.csdnimg.cn/a1c4ddc6b73b48c5a88512eba3a907fa.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布局中全局引入组件
到此这篇关于antd项目如何实现彩蛋效果的文章就介绍到这了,更多相关antd彩蛋内容请搜索阿兔在线工具以前的文章或继续浏览下面的相关文章希望大家以后多多支持阿兔在线工具!