PK创意闹新春,我正在参加「春节创意投稿大赛」,详情请看:春节创意投稿大赛”
春节家家户户都会挂灯笼,产品经理说了,春节期间,咱们系统也要挂灯笼。于是在React项目中用Div画了个大红灯笼。
项目中使用了React、less、classNames。
结构拆解
首先是灯笼结构拆解:挂灯线,灯身,灯身上口&下口,灯笼骨架线,文字,灯穗。
// 灯身
// 灯身上口&下口,使用灯身的:before&:after实现
<div>
// 挂灯线
<div />
// 灯笼骨架线-外层
<div>
// 灯笼骨架线-内层
<div>
<div>文字</div>
</div>
</div>
// 灯穗
<div>
// 灯穗线
<div />
<div />
</div>
</div>
灯笼样式
给html结构加上class,这里使用到了classNames,请自行install,如果不想用可以自行修改。
// 灯身
<div className={styles.deng}>
// 挂灯线
<div className={styles.xian} />
// 灯笼骨架线-外层
<div className={classNames(styles.arc, styles.arcA)}>
// 灯笼骨架线-内层
<div className={classNames(styles.arc, styles.arcB)}>
// 文字
<div className={styles.dengTxt}>春</div>
</div>
</div>
// 灯穗
<div className={styles.sui}>
// 灯穗线
<div className={styles.sui1} />
<div className={styles.sui2} />
</div>
</div>
接下来就是调整css样式,灯笼大小采用固定宽高,主要css如下。
灯身
border-radius圆形,红色背景,再用box-shadow加上朦胧灯光效果。
.deng {
position: relative;
width: 120px;
height: 90px;
margin: 30px;
background: #d8000f;
background: rgba(216, 0, 15, 0.8);
border-radius: 50% 50%;
// 灯笼的灯光效果
box-shadow: -5px 5px 50px 4px rgba(250, 108, 0, 1);
}
挂灯线
宽高调整粗细,背景色控制颜色,绝对定位控制位置。
.xian {
position: absolute;
top: -30px;
left: 60px;
width: 2px;
height: 30px;
background: #dc8f03;
}
灯笼骨架线
border控制粗细和颜色。
.arc {
height: 90px;
background: rgba(216, 0, 15, 0.1);
border-radius: 50% 50%;
border: 2px solid #dc8f03;
}
- 灯笼骨架线-外层 宽度控制位置。。
.arcA {
width: 100px;
margin: 12px 8px 8px 10px;
}
- 灯笼骨架线-内层 宽度控制位置。
.arcB {
width: 45px;
margin: -2px 8px 8px 26px;
}
文字
应该也可以替换成图片,感兴趣的同学可以自行尝试。
.dengTxt {
font-family: Arial, Lucida Grande, Tahoma, sans-serif;
font-size: 3.2rem;
color: #dc8f03;
font-weight: bold;
line-height: 85px;
text-align: center;
}
灯穗
.sui {
position: relative;
width: 5px;
height: 20px;
margin: -5px 0 0 59px;
background: #ffa500;
border-radius: 0 0 5px 5px;
}
- 灯穗线
.sui1 {
position: absolute;
top: 18px;
left: -2px;
width: 10px;
height: 35px;
background: #ffa500;
border-radius: 0 0 0 5px;
}
.sui2 {
position: absolute;
top: 14px;
left: -2px;
width: 10px;
height: 10px;
background: #dc8f03;
border-radius: 50%;
}
灯身上口
.deng:before {
position: absolute;
top: -7px;
left: 29px;
height: 12px;
width: 60px;
content: ' ';
display: block;
z-index: 999;
border-radius: 5px 5px 0 0;
border: solid 1px #dc8f03;
background: #ffa500;
background: linear-gradient(to right, #dc8f03, #ffa500, #dc8f03, #ffa500, #dc8f03);
}
灯身下口
.deng:after {
position: absolute;
bottom: -7px;
left: 10px;
height: 12px;
width: 60px;
content: ' ';
display: block;
margin-left: 20px;
border-radius: 0 0 5px 5px;
border: solid 1px #dc8f03;
background: #ffa500;
background: linear-gradient(to right, #dc8f03, #ffa500, #dc8f03, #ffa500, #dc8f03);
}
灯笼画好了,什么,不会动,风一吹要让它动起来,安排,那就使用animation+transform给灯笼加上动效。
动效
摆动动效css。
@keyframes swing {
0% {
transform: rotate(-10deg);
}
50% {
transform: rotate(10deg);
}
100% {
transform: rotate(-10deg);
}
}
给灯和灯穗加上动效。
.deng {
transform-origin: 50% -100px;
animation: swing 3s infinite ease-in-out;
}
.sui {
transform-origin: 50% -45px;
animation: swing 4s infinite ease-in-out;
}
没录制动图,请自行想象。
一个灯笼有点单调,多挂几个,直接复制前面的结构即可,样式大部分可以复用。
再将所有灯笼包起来,使用绝对定位调整每个灯笼的位置,再修改下每个灯笼的动效时间,制造伪随机的晃动。
最终的成品效果如下。
完整代码如下。
html部分。
<div className={classNames(styles.dengBox, styles.dengBox1)}>
<div className={styles.deng}>
<div className={styles.xian} />
<div className={classNames(styles.arc, styles.arcA)}>
<div className={classNames(styles.arc, styles.arcB)}>
<div className={styles.dengTxt}>春</div>
</div>
</div>
<div className={styles.sui}>
<div className={styles.sui1} />
<div className={styles.sui2} />
</div>
</div>
</div>
<div className={classNames(styles.dengBox, styles.dengBox2)}>
<div className={styles.deng}>
<div className={styles.xian} />
<div className={classNames(styles.arc, styles.arcA)}>
<div className={classNames(styles.arc, styles.arcB)}>
<div className={styles.dengTxt}>节</div>
</div>
</div>
<div className={styles.sui}>
<div className={styles.sui1} />
<div className={styles.sui2} />
</div>
</div>
</div>
<div className={classNames(styles.dengBox, styles.dengBox3)}>
<div className={styles.deng}>
<div className={styles.xian} />
<div className={classNames(styles.arc, styles.arcA)}>
<div className={classNames(styles.arc, styles.arcB)}>
<div className={styles.dengTxt}>乐</div>
</div>
</div>
<div className={styles.sui}>
<div className={styles.sui1} />
<div className={styles.sui2} />
</div>
</div>
</div>
<div className={classNames(styles.dengBox, styles.dengBox4)}>
<div className={styles.deng}>
<div className={styles.xian} />
<div className={classNames(styles.arc, styles.arcA)}>
<div className={classNames(styles.arc, styles.arcB)}>
<div className={styles.dengTxt}>快</div>
</div>
</div>
<div className={styles.sui}>
<div className={styles.sui1} />
<div className={styles.sui2} />
</div>
</div>
</div>
css部分。
@keyframes swing {
0% {
transform: rotate(-10deg);
}
50% {
transform: rotate(10deg);
}
100% {
transform: rotate(-10deg);
}
}
.dengBox {
position: absolute;
top: 0px;
z-index: 9999;
pointer-events: none;
.deng {
position: relative;
width: 120px;
height: 90px;
margin: 30px;
background: #d8000f;
background: rgba(216, 0, 15, 0.8);
border-radius: 50% 50%;
box-shadow: -5px 5px 50px 4px rgba(250, 108, 0, 1);
transform-origin: 50% -100px;
animation: swing 3s infinite ease-in-out;
}
.xian {
position: absolute;
top: -30px;
left: 60px;
width: 2px;
height: 30px;
background: #dc8f03;
}
.arc {
height: 90px;
background: rgba(216, 0, 15, 0.1);
border-radius: 50% 50%;
border: 2px solid #dc8f03;
}
.arcA {
width: 100px;
margin: 12px 8px 8px 10px;
}
.arcB {
width: 45px;
margin: -2px 8px 8px 26px;
}
.dengTxt {
font-family: Arial, Lucida Grande, Tahoma, sans-serif;
font-size: 3.2rem;
color: #dc8f03;
font-weight: bold;
line-height: 85px;
text-align: center;
}
.sui {
position: relative;
width: 5px;
height: 20px;
margin: -5px 0 0 59px;
background: #ffa500;
border-radius: 0 0 5px 5px;
transform-origin: 50% -45px;
animation: swing 4s infinite ease-in-out;
}
.sui1 {
position: absolute;
top: 18px;
left: -2px;
width: 10px;
height: 35px;
background: #ffa500;
border-radius: 0 0 0 5px;
}
.sui2 {
position: absolute;
top: 14px;
left: -2px;
width: 10px;
height: 10px;
background: #dc8f03;
border-radius: 50%;
}
.deng:before {
position: absolute;
top: -7px;
left: 29px;
height: 12px;
width: 60px;
content: ' ';
display: block;
z-index: 999;
border-radius: 5px 5px 0 0;
border: solid 1px #dc8f03;
background: #ffa500;
background: linear-gradient(to right, #dc8f03, #ffa500, #dc8f03, #ffa500, #dc8f03);
}
.deng:after {
position: absolute;
bottom: -7px;
left: 10px;
height: 12px;
width: 60px;
content: ' ';
display: block;
margin-left: 20px;
border-radius: 0 0 5px 5px;
border: solid 1px #dc8f03;
background: #ffa500;
background: linear-gradient(to right, #dc8f03, #ffa500, #dc8f03, #ffa500, #dc8f03);
}
}
.dengBox1 {
left: 60px;
.deng {
animation: swing 3s infinite ease-in-out;
box-shadow: -5px 5px 50px 4px rgba(250, 108, 0, 1);
}
}
.dengBox2 {
left: 120px;
.deng {
animation: swing 4s infinite ease-in-out;
box-shadow: -5px 5px 30px 4px rgba(252, 144, 61, 1);
}
}
.dengBox3 {
right: 60px;
.deng {
animation: swing 5s infinite ease-in-out;
box-shadow: -5px 5px 50px 4px rgba(250, 108, 0, 1);
}
}
.dengBox4 {
right: 120px;
.deng {
animation: swing 4s infinite ease-in-out;
box-shadow: -5px 5px 30px 4px rgba(252, 144, 61, 1);
}
}
以上其实是html和css就可以实现的,所以如果不是React的项目也是可以移植的。以上代码中css并没有做兼容性处理,移植时需要注意。
好了,灯笼就到这里了。 春节还搞了个烟花,参见春节放# 春节用JS在系统里放烟花。