我正在参加「初夏创意投稿大赛」详情请看:初夏创意投稿大赛
效果图
实现思路
电扇分为头部和底部俩个盒子,头部装风叶,脚部装遥控装置和电扇底座
电扇头部使用一个盒子包住之后在写一个无序列表用来装风叶,然后通过css扭曲属性和旋转属性在结合定位的方式实现头部的样式,在通过css3动画的方式使得风叶有旋转的效果
电扇脚部分为遥控器和底座和电扇杆,遥控器通过无序列表结合flex布局的方式实现开关的排列,在通过电线杆伪元素的方式实现一个底座,底座采用定位的方式定位到最底部
在通过类名管理转速,用js给按钮添加上管理类名的函数
页面结构
<div class="box">
<!-- 电扇圈 -->
<div class="fanbox">
<!-- 电扇叶盒子 -->
<ul id="motor">
<!-- 扇叶 -->
<li></li>
<li></li>
<li></li>
</ul>
</div>
<!-- 电扇座 -->
<div class="pedestal">
<!-- 遥控 -->
<ul class="telecontrol">
<li id="slow">1</li>
<li id="middle">2</li>
<li id="tall">3</li>
<li id="derail">开/关</li>
</ul>
</div>
</div>
电扇外框
我们先画一个盒子,用盒子来装电扇头部,给上边框,这样电扇头外框的样式就好了,我们这里提前给盒子设置好flex布局主轴侧轴居中,这是为了风扇叶盒子能够居中在电扇头的最中心
/* 电扇圈 */
.fanbox {
box-sizing: border-box;
width: 300px;
height: 300px;
background: rgb(215, 202, 145);
border-radius: 50%;
padding: 15px;
display: flex;
justify-content: center;
align-items: center;
border: 2px solid #000;
overflow: hidden;
}
电扇内框
我们给个比外框小的盒子,然后设置宽高,也同样给盒子设定一个边框及通过边框的属性实现圆形,这里我们采用无序列表实现,因为风叶采用li比较层次分明
/* 电扇叶盒子 */
.fanbox>ul {
position: relative;
box-sizing: border-box;
width: 100%;
height: 100%;
background: rgb(242, 235, 135);
border-radius: 50%;
padding: 10px;
border: 2px solid #000;
}
电扇风叶
这里我们用到css的扭曲属性,先是用css属性做出一个扇形在通过扭曲属性把他延伸成一个长方形的扇形,充当扇叶
/* 扇叶 */
.fanbox>ul li {
position: absolute;
top: 35px;
left: 50%;
width: 100px;
height: 100px;
border-radius: 100px 0 0;
background: rgb(248, 222, 70);
}
这里我们把扇叶进行扭曲
transform: translate(-50%, -43%) rotate(45deg) skew(12deg, 11deg);
电扇总共三个扇叶,其他俩个照搬,跳转好旋转角度,在通过扭曲属性进行扭曲
.fanbox>ul li:nth-child(1) {
transform: translate(-50%, -43%) rotate(45deg) skew(12deg, 11deg);
}
.fanbox>ul li:nth-child(2) {
transform-origin: 71% 117%;
transform: translate(-50%, -40%) rotate(168deg) skew(12deg, 11deg);
}
.fanbox>ul li:nth-child(3) {
transform-origin: 88% 141%;
transform: translate(-50%, -40%) rotate(278deg) skew(12deg, 11deg);
}
通过CSS属性进行扭曲,在使用边框属性设置边框
border: 2px solid #000;
在使用电扇内框盒子做一个风扇电机的盖子这样显得好看,且能遮盖住三个扇叶之间的空隙,这里我们使用内框的伪元素来做
.fanbox>ul::after {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 20px;
height: 20px;
border-radius: 50%;
background: rgb(230, 216, 109);
border: 2px solid #000;
}
电扇杆
这里我们给个宽高就在通过定位的方式,定位到头部上一点的位置就好了
.pedestal {
position: relative;
top: -10px;
width: 30px;
height: 300px;
background: rgb(157, 152, 128);
border: 2px solid #000;
}
电扇底座
底座我们采用电扇杆的伪元素来做,在通过定位,定位到最下面,底座上面是有一个鼓起的圆包的,我们这里采用css的边框圆角的方式实现
先设置搞宽高,定位到最底部
/*底座 */
.pedestal::after{
content:'';
width: 200px;
height: 30px;
background: rgb(157, 152, 128);
border: 2px solid #000;
position: absolute;
left: 50%;
bottom: 0;
transform: translate(-50%, 94%);
}
在通过边框属性实现圆包
border-top-left-radius: 50%;
border-top-right-radius: 50%;
遥控器
遥控器我们也采用无序列表的方式实现,先给一个大盒子,定位到电扇杆合适的位置,在设置上边框,采用flex布局的方式让子元素能够平分空间这样显得好看,我们先设置好
/* 遥控器 */
.telecontrol {
box-sizing: border-box;
position: absolute;
top: 0;
left: 50%;
transform: translate(-50%, 50%);
width: 90px;
height: 100px;
padding: 5px 0;
background: rgb(232, 223, 150);
border-radius: 5px;
border: 2px solid #000;
display: flex;
flex-direction: column;
justify-content: space-around;
align-items: center;
}
在通过子元素实现开关和开关的样式
.telecontrol>li {
cursor: pointer;
user-select: none;
padding: 0 10px;
height: 15px;
display: flex;
justify-content: center;
align-items: center;
font-size: 12px;
border: 1px solid #000;
border-radius: 8px;
background: rgb(169, 157, 90);
color: #fff;
}
电扇转动的实现
样式排完了之后,我们来让电扇转起来,电扇转起来使用css动画结合css类名的方式,每个类名对应了不同的档位触发不同转速的动画
/* 档位 */
.gear1 {
animation: Firstgearrotate1 3s linear infinite;
}
.gear2 {
animation: Firstgearrotate2 3s linear infinite;
}
.gear3 {
animation: Firstgearrotate3 3s linear infinite;
}
/* 一档 */
@keyframes Firstgearrotate1 {
from {
transform: rotate(0deg);
}
to {
transform: rotate(1080deg);
}
}
/* 二档 */
@keyframes Firstgearrotate2 {
from {
transform: rotate(0deg);
}
to {
transform: rotate(2160deg);
}
}
/* 三档 */
@keyframes Firstgearrotate3 {
from {
transform: rotate(0deg);
}
to {
transform: rotate(3240deg);
}
}
风扇按钮控制
最后在通过js获取到按钮元素,进行管理,在通过不同的下标值给风扇内框盒子添加上不同的类名实现转动
// 获取档位和开关
// 低档
const slow = document.getElementById('slow');
// 中档
const middle = document.getElementById('middle');
// 高档
const tall = document.getElementById('tall');
// 开关
const derail = document.getElementById('derail');
// 风扇
const motor = document.getElementById('motor');
// 转速
const speed = ['gear1', 'gear2', 'gear3'];
//按钮,开关按钮必须在最后一个
const disjunctor = [slow, middle, tall, derail];
disjunctor.map((R, index) => {
const fn=Gear.bind(this,index)
R.addEventListener('click', fn, false);
});
// 按钮函数
function Gear(index){
// 删除所有类名,存在即删除
speed.map(A=>{
if(motor.classList.contains(A)){
motor.classList.remove(A);
}
})
// 如果当前是开关按钮则不继续,开关按钮必须在最后一个
if (!speed[index])return;
motor.classList.add(speed[index]);
};
代码我放到码上掘金上面了,大家感兴趣可以看看
祝大家每天开开心心的,美好的未来在向我们招手!