antd项目实现彩蛋效果的详细代码
作者:小小愿望 发布时间:2023-09-14 12:51:20
标签:antd,彩蛋
马上就要过节了,想把自己的项目搞得酷炫一些,对整个网站的按钮添加图标、飘花效果、首屏大图展示、顶部导航背景图,于是就写了这一遍文字,如有兴趣的小伙伴们可以一起学习进步,仅供参考。
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布局中全局引入组件
来源:https://juejin.cn/post/7140658007599218695


猜你喜欢
- 0. 学习目标栈和队列是在程序设计中常见的数据类型,从数据结构的角度来讲,栈和队列也是线性表,是操作受限的线性表,它们的基本操作是线性表操作
- model:class Profile(models.Model): user = models.OneToOneField(User, o
- 前言聚簇索引就是innodb默认创建的基于主键的索引结构,而且表里的数据就是直接放在聚簇索引里,作为叶节点的数据页:基于主键的数据搜索:从聚
- 这篇文章主要介绍了jekins配置python脚本定时任务过程图解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价
- 前言现如今我们生活在一个二维码的时代,生活中处处都是二维码,支付要使用二维码,微信加好友要使用二维码,乘坐公共交通要使用二维码,那么,如果要
- 使用expdp时,遇到”ORA-39002、ORA-39070......”连续报错。1、 遇到的问题C:\Users\Admi
- SQL SERVER 2012中新增了CHOOSE,该函数可以从值列表返回指定索引处的项。例如:select CHOOSE(3,'A
- 最近在作图时需要将输出的图片紧密排布,还要去掉坐标轴,同时设置输出图片大小。要让程序自动将图表保存到文件中,代码为:plt.savefig(
- python3.6.2环境安装配置图文教程,具体如下一、需要下载的软件》python3.6.2.exe (也可以选择更新的版本) ----
- 关于窗口函数的基础,请看文章SQL窗口函数取值窗口函数可以用于返回窗口内指定位置的数据行。常见的取值窗口函数如下:LAG函数可以返回窗口内当
- 本文实例讲述了Python pandas自定义函数的使用方法。分享给大家供大家参考,具体如下:自定义函数的使用import numpy as
- 便携文档格式 (PDF) 是由 Adobe 开发的格式,主要用于呈现可打印的文档,其中包含有 pixel-perfect 格式,嵌入字体以及
- 我们在使用Django的models查询数据库时,可以看到有这种写法:form app.models import&nb
- 默认情况下,Python 源码文件以 UTF-8 编码方式处理。在这种编码方式中,世界上大多数语言的字符都可以同时用于字符串字面值、变量或函
- 用pycharm和pyqt5,想写一个弹出窗口的程序,如下:class video_record(QWidget): &nbs
- 分享由字符“\”转义引起的SQL数据库实例名称找不到或远程连接失败并显示错误error40的解决办法:一、问题介绍很久没有用c#去连数据库程
- 前言当我们需要对列表(list)、元组(tuple)、字典(dictionary)和集合(set)的元素进行遍历时,其实Python内部都是
- Javascript中标签(label)是一个标识符。标签可以与变量重名,它是一个独立的语法元素(既不是变量,也不是类型),其作用是标识”标
- sub test { my $head = "abc"; &n
- mmh3安装方法哈希方法主要有MD、SHA、Murmur、CityHash、MAC等几种方法。mmh3全程murmurhash3,是一种非加