css3实现一个3d楼梯动画

1.实现效果

2.实现步骤

  • 定义css变量:宽w、高h、个数count
/* 楼梯高度 */
--h: 40px;
/* 楼梯宽度 */
--w: 50px;
/* 楼梯节数 */
--count: 5; 
  • 写一个容器,宽为count * w; 高为count * h;设置transform-style: preserve-3d,让转换的子元素保留3D转换。
.container {position: relative;width: calc(var(--count) * var(--w));height: calc(var(--count) * var(--h));transform-style: preserve-3d;} 
  • 在容器内写count个div,给每个div标签定义css变量c,表示当前位置,从1~count,设置width为w,高为h * c,transform-style为preserve-3d;基于父容器absolute定位,bottom都为0,left从0开始,为w*(c-1);实现效果如下:
<div class="container"><div class="step" style="--c: 1"></div><div class="step" style="--c: 2"></div><div class="step" style="--c: 3"></div><div class="step" style="--c: 4"></div><div class="step" style="--c: 5"></div>
</div> 
.container .step {position: absolute;--i: calc(var(--c) - 1);left: calc(var(--w) * var(--i));bottom: 0;width: var(--w);height: calc(var(--h) * var(--c));border: 1px solid orange;} 
  • 对父容器进行transform偏移,看看效果
.container{
 + transform: rotateX(-30deg) rotateY(30deg);
} 
  • 为每个div设置前伪元素,宽度为w,高度为count * h,设置X轴方向旋转从0-90deg,效果如下:
.container .step::before {content: "";position: absolute;top: 0;left: 0;width: var(--w);height: calc(var(--count) * var(--h));background: orange;transform: rotateX(90deg);} 
  • 前伪元素设置z轴方向的偏移,偏移量为总高度(count * h)的一半
.container .step::before {/* z轴偏移为高度的2分之一 */--z: calc(var(--count) * var(--h) / 2);transform: rotateX(90deg) translateZ(var(--z));
 } 
  • 为每个div设置后伪元素,高度为h,宽度为count* h(这个值与前伪元素的高度对应),设置Y轴方向旋转从0-90deg,效果如下:
.container .step::after {content: "";position: absolute;top: 0;left: 0;width: calc(var(--count) * var(--h));height: var(--h);background: orangered;transform: rotateY(90deg);
} 
  • 后伪元素设置z轴方向的偏移,偏移量为总高度(count * h)的一半
.container .step::after {/* z轴偏移为高度的2分之一 */--z: calc(var(--count) * var(--h) / 2);transform: rotateY(90deg) translateZ(calc(-1 * var(--z)));
 } 
  • 为前伪元素添加hover效果
.container .step:hover::before {cursor: pointer;filter: brightness(1.1);
} 
  • 将父容器进行旋转,可以看到已经有大概的轮廓了
  • 在每个div下添加两个span标签,宽度为w,高度为父元素step的高度,做为梯形的左右两侧
<div class="container"><div class="step" style="--c: 1"><span></span><span></span></div>
 ... //4个相同的标签
</div> 
.container .step span {position: absolute;display: block;width: var(--w);height: 100%;background: orchid;transform-style: preserve-3d;
} 
  • 设置第一个span的位置,z轴方向的偏移,偏移量为总高度(count * h)的一半
.container .step span:nth-child(1) {/* z轴偏移为高度的2分之一 */--z: calc(var(--count) * var(--h) / 2);transform: translateZ(var(--z));
} 
  • 设置第二个span的位置,z轴方向的偏移,偏移量为总高度(count * h)的一半
.container .step span:nth-child(2) {/* z轴偏移为高度的2分之一 */--z: calc(var(--count) * var(--h) / 2);transform: translateZ(calc(-1 * var(--z)));
} 
  • 可以看到,现在还剩两处需要填充
  • 填补第一处内容,将最后一个div标签中的最后一个span为容器,添加一个伪元素,高度100%,宽度为counut * h
.container .step:last-child span:nth-child(2)::before {content: "";position: absolute;top: 0;left: 0;width: calc(var(--counut) * var(--h));height: 100%;background: #222;
} 
  • 将该伪元素y轴方向旋转90deg
  • 调整其在x,y,z轴各个方向的偏移量,x轴方向为总高度的一半 即 -1 * (count * h) /2,y轴方向为0,z轴方向为-1 * ((count * h) /2 - w)
.container .step:last-child span:nth-child(2)::before {/* z轴偏移为总高度的2分之一 */--z: calc(var(--count) * var(--h) / 2);/*总高度的2分之一 - 宽度*/--k: calc(var(--z) - var(--w));transform: rotateY(90deg)translate3d(calc(-1 * var(--z)), 0, calc(-1 * var(--k)));
} 
  • 填补第二处内容,将第一个div标签中的第二个span为容器,添加一个伪元素,高度counut * h,宽度为span元素的高度* count
.container .step:first-child span:nth-child(2)::after {content: "";position: absolute;left: 0;top: 0;background: #222;width: calc(100% * var(--count));height: calc(calc(var(--count) * var(--h)));transform: rotateX(90deg);
} 
  • 将该伪元素X轴方向旋转90deg
  • 调整其在x,y,z轴各个方向的偏移量,x轴方向为0,y轴为总高度的一半 即 (count * h) /2,z轴方向为 ((count * h) /2 - h)
.container .step:first-child span:nth-child(2)::after {/* z轴偏移为总高度的2分之一 */--z: calc(var(--count) * var(--h) / 2);/*总高度的2分之一 - 高度*/--k: calc(var(--z) - var(--h));transform: rotateX(90deg) translate3d(0, var(--z), var(--k));
} 
  • 到此,我们就是写了一个完整的3d楼梯了,去掉辅助线,将各边的颜色风格统一一致
  • 为底部添加一个阴影效果,选择最底部的区域,设置scale
.container .step:first-child span:nth-child(2)::after{+ transform: rotateX(90deg) translate3d(0, var(--z), var(--k)) scale(1.25);
} 
  • 设置filter的blur滤镜
.container .step:first-child span:nth-child(2)::after{+filter: blur(20px);
} 
  • 父容器添加animation动画,改变rotateX, rotateY的位置
.container {+ transform: rotateX(-30deg) rotateY(30deg);+ animation: animate 10s linear infinite;
}

@keyframes animate {0% {transform: rotateX(-30deg) rotateY(0deg);}100% {transform: rotateX(-30deg) rotateY(1turn);}
} 
  • 修改w和h,设置不同的count,试试吧
 /* 楼梯高度 */--h: 10px;/* 楼梯宽度 */--w: 50px;/* 楼梯节数 */--count: 6; 

3.实现代码

<style>
:root {--bg: linear-gradient(to top, #fdcbf1 0%, #fdcbf1 1%, #e6dee9 100%);--c1: #6ec5e7;--c3: #c2e9fb;--c2: skyblue;/* 楼梯高度 */--h: 10px;/* 楼梯宽度 */--w: 50px;/* 楼梯节数 */--count: 6;
}
body {background: var(--bg);
}
.container {position: relative;width: calc(var(--count) * var(--w));height: calc(var(--count) * var(--h));transform-style: preserve-3d;transform: rotateX(-30deg) rotateY(30deg);animation: animate 10s linear infinite;
}
@keyframes animate {0% {transform: rotateX(-30deg) rotateY(0deg);}100% {transform: rotateX(-30deg) rotateY(1turn);}
}
.container .step {position: absolute;--i: calc(var(--c) - 1);left: calc(var(--w) * var(--i));bottom: 0;width: var(--w);height: calc(var(--h) * var(--c));transform-style: preserve-3d;
}
.container .step::before {content: "";position: absolute;top: 0;left: 0;width: var(--w);height: calc(var(--count) * var(--h));background: var(--c3);/* z轴偏移为总高度的2分之一 */--z: calc(var(--count) * var(--h) / 2);transform: rotateX(90deg) translateZ(var(--z));
}
.container .step:hover::before {cursor: pointer;filter: brightness(1.1);
}
.container .step::after {content: "";position: absolute;top: 0;left: 0;width: calc(var(--count) * var(--h));height: var(--h);background: var(--c2);/* z轴偏移为总高度的2分之一 */--z: calc(var(--count) * var(--h) / 2);transform: rotateY(90deg) translateZ(calc(-1 * var(--z)));
}
.container .step span {position: absolute;display: block;width: var(--w);height: 100%;background: var(--c1);transform-style: preserve-3d;
}
.container .step span:nth-child(1) {/* z轴偏移为总高度的2分之一 */--z: calc(var(--count) * var(--h) / 2);transform: translateZ(var(--z));
}
.container .step span:nth-child(2) {/* z轴偏移为总高度的2分之一 */--z: calc(var(--count) * var(--h) / 2);transform: translateZ(calc(-1 * var(--z)));
}
.container .step:last-child span:nth-child(2)::before {content: "";position: absolute;top: 0;left: 0;width: calc(var(--count) * var(--h));height: 100%;background: var(--c2);/* z轴偏移为总高度的2分之一 */--z: calc(var(--count) * var(--h) / 2);/*总高度的2分之一 - 宽度*/--k: calc(var(--z) - var(--w));transform: rotateY(90deg)translate3d(calc(-1 * var(--z)), 0, calc(-1 * var(--k)));
}
.container .step:first-child span:nth-child(2)::after {content: "";position: absolute;left: 0;top: 0;background: var(--c1);width: calc(100% * var(--count));height: calc(calc(var(--count) * var(--h)));/* z轴偏移为总高度的2分之一 */--z: calc(var(--count) * var(--h) / 2);/*总高度的2分之一 - 高度*/--k: calc(var(--z) - var(--h));transform: rotateX(90deg) translate3d(0, var(--z), var(--k)) scale(1.25);filter: blur(20px);
}
</style>

<body><div class="container"><div class="step" style="--c: 1"><span></span><span></span></div><div class="step" style="--c: 2"><span></span><span></span></div><div class="step" style="--c: 3"><span></span><span></span></div><div class="step" style="--c: 4"><span></span><span></span></div><div class="step" style="--c: 5"><span></span><span></span></div><div class="step" style="--c: 6"><span></span><span></span></div></div>
</body> 

最后

最近还整理一份JavaScript与ES的笔记,一共25个重要的知识点,对每个知识点都进行了讲解和分析。能帮你快速掌握JavaScript与ES的相关知识,提升工作效率。



有需要的小伙伴,可以点击下方卡片领取,无偿分享

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值