如图 最近亲爱的产品同学,提了一个需求:在页面某个角落增加一个旋转的金币来吸引用户参加活动~越快上越好~
拿到这个需求,第一反应 gif+a 标签,简单粗暴+便捷。即将实施就碰到一个问题,UI 小姐姐还没有做设计,排期需要在 x 天后~怎么办?没有难做的工作,只有解决困难的打工人!
链接好说,旋转的金币怎么整?旋转的金币 = 旋转 + 金币。旋转通过 css3 的动画属性 animation+ @keyframes 就可以搞定:
.coin {
transform-style: preserve-3d;
animation: rotate3d 3s linear infinite;
}
@keyframes rotate3d {
0% {
transform: perspective(1000px) rotateY(0deg);
}
100% {
transform: perspective(1000px) rotateY(360deg);
}
}
那么金币怎么办?我们用 div 来 DIY 一下吧~如果把金币的表面图案都擦掉,那金币就是一个特别矮的圆柱体,我们需要一个正面+背面+弯曲的侧面。那么正面+背面很简单
$coin-thickness: 4px;
$coin-front: "https://tosv.byted.org/obj/maat/img/d2FuZ3NoaXpoZW4uNzUzMA/file_178a58ae02711.png";
$coin-back: "https://tosv.byted.org/obj/maat/img/d2FuZ3NoaXpoZW4uNzUzMA/file_178a58ae0276.png";
.coin__front {
background-image: url($coin-front);
background-size: cover;
transform: translateZ($coin-thickness / 2);
}
.coin__back {
background-image: url($coin-back);
background-size: cover;
transform: translateZ(-$coin-thickness / 2) rotateY(180deg);
}
侧面怎么画?翻了不少 css 文档,除了 border-radius 还真没有找到一个弯曲的属性,我徒手 DIY 金币的过程就要这么结束了么?
当然不会!!!敬我中华民族智慧一杯~早在数千年前,祖冲之就告诉我们~实现不了完美的圆,那就让它近似圆就好了!数年前端从业经验告诉我,只要能骗过用户的视觉,那什么都是真的!!!就是你了——多棱柱。
方案有了,但麻烦的是,画多少棱面才能骗过用户的视觉?我得手写多少 css+div?不用慌,less 中的 when 来搞定 n 次循环,前端框架中整个 map 来生成 div
const n = 80
<div className={styles.coin__edge}>
{Array(n).fill(1).map((value, key) => (<div key={key} />))}
</div>
对这些 div 使用 translate + rotate 来确定位置~
// 多棱柱体大小(直径)
$coin-diameter: 320px;
// 多棱柱体高度
$coin-thickness: 40px;
// 颜色
$coin-color: rgb(255, 223, 95);
// 多棱柱的棱数
$edge-faces: 100;
// 每个棱的高度 π * 直径 / 棱数
$edge-face-length: 3.14 * $coin-diameter / $edge-faces;
.coin__edge {
> div {
position: absolute;
height: $edge-face-length;
width: $coin-thickness;
}
@for $i from 1 through $edge-faces {
div:nth-child(#{$i}) {
background: $coin-color;
transform:
// 由于默认绘制div的初始位置在左上角,需要把它移到中心
translateY($coin-diameter / 2 - $edge-face-length / 2)
translateX($coin-diameter / 2 - $coin-thickness / 2)
// 横向旋转
rotateY(90deg)
// 调整每片角度
rotateX(360deg / $edge-faces * $i + 90)
// 移动至多棱柱边缘
translateZ($coin-diameter / 2);
}
}
}
默认绘制的位置移到中心
div:nth-child(#{$i}) {
transform:
// 由于默认绘制div的初始位置在左上角,需要把它移到中心
translateY($coin-diameter / 2 - $edge-face-length / 2)
translateX($coin-diameter / 2 - $coin-thickness / 2)
}
横向旋转
div:nth-child(#{$i}) {
transform:
// 由于默认绘制div的初始位置在左上角,需要把它移到中心
translateY($coin-diameter / 2 - $edge-face-length / 2)
translateX($coin-diameter / 2 - $coin-thickness / 2)
// 横向旋转
rotateY(90deg)
}
调整每片角度
div:nth-child(#{$i}) {
transform:
// 由于默认绘制div的初始位置在左上角,需要把它移到中心
translateY($coin-diameter / 2 - $edge-face-length / 2)
translateX($coin-diameter / 2 - $coin-thickness / 2)
// 横向旋转
rotateY(90deg)
// 调整每片角度
rotateX(360deg / $edge-faces * $i + 90)
// 移动至多棱柱边缘
translateZ($coin-diameter / 2);
}
移动至多棱柱边缘
div:nth-child(#{$i}) {
transform:
// 由于默认绘制div的初始位置在左上角,需要把它移到中心
translateY($coin-diameter / 2 - $edge-face-length / 2)
translateX($coin-diameter / 2 - $coin-thickness / 2)
// 横向旋转
rotateY(90deg)
// 调整每片角度
rotateX(360deg / $edge-faces * $i + 90)
// 移动至多棱柱边缘
translateZ($coin-diameter / 2);
}
最终效果图: 完美解决~
最后附上完整代码
骨架:
const CoinTrans = () => {
return <div class="coin">
<div className="coin__front"></div>
<div className="coin__back"></div>
<div className="coin__edge">
{Array(100).fill(1).map((item,key)=> <div key={key} />)}
</div>
{/* 阴影 */}
<div className="coin__shadow"></div>
</div>
}
$coin-diameter: 320px;
$coin-thickness: 40px;
$coin-color: rgb(255, 223, 95);
$coin-front: "https://tosv.byted.org/obj/maat/img/d2FuZ3NoaXpoZW4uNzUzMA/file_178a58ae02711.png";
$coin-back: "https://tosv.byted.org/obj/maat/img/d2FuZ3NoaXpoZW4uNzUzMA/file_178a58ae0276.png";
$edge-faces: 100;
$edge-face-length: 3.14 * $coin-diameter / $edge-faces;
$turn-time: 8s;
.coin {
position: relative;
width: $coin-diameter;
height: $coin-diameter;
margin: 0 auto;
transform-style: preserve-3d;
animation: rotate3d $turn-time linear infinite;
transition: all 0.3s;
}
.coin__front,
.coin__back {
position: absolute;
width: $coin-diameter;
height: $coin-diameter;
border-radius: 50%;
overflow: hidden;
background-color: $coin-color;
color: #000;
font-size: $coin-diameter * 0.6;
// 金币表面的闪动 buling~buling~~
&:after {
content: "";
position: absolute;
left: -$coin-diameter / 2;
bottom: 100%;
display: block;
height: $coin-diameter / 1.5;
width: $coin-diameter * 2;
background: #fff;
opacity: 0.3;
animation: shine linear $turn-time / 2 infinite;
}
}
.coin__front {
background-image: url($coin-front);
background-size: cover;
transform: translateZ($coin-thickness / 2);
}
.coin__back {
background-image: url($coin-back);
background-size: cover;
transform: translateZ(-$coin-thickness / 2) rotateY(180deg);
}
.coin__edge {
> div {
position: absolute;
height: $edge-face-length;
width: $coin-thickness;
}
@for $i from 1 through $edge-faces {
div:nth-child(#{$i}) {
background: $coin-color;
// 另一种移动逻辑
// transform: translateY($coin-diameter / 2 - $edge-face-length / 2)
// translateX($coin-diameter / 2 - $coin-thickness / 2)
// rotateZ(360deg / $edge-faces * $i + 90)
// translateX($coin-diameter / 2)
// rotateY(90deg);
// rotateZ(360deg / $edge-faces * $i + 90)
transform: translateY($coin-diameter / 2 - $edge-face-length / 2)
translateX($coin-diameter / 2 - $coin-thickness / 2)
rotateY(90deg)
rotateX(360deg / $edge-faces * $i + 90)
translateZ($coin-diameter / 2);
}
}
}
// 阴影 css
.coin__shadow {
position: absolute;
width: $coin-diameter;
height: $coin-thickness;
border-radius: 50%;
background: #000;
box-shadow: 0 0 $coin-thickness * 5 $coin-thickness * 5 #000;
opacity: 0.125;
transform: rotateX(90deg) translateZ(-$coin-diameter * 1.1) scale(0.5);
}
@keyframes rotate3d {
0% {
transform: perspective(1000px) rotateY(0deg);
}
100% {
transform: perspective(1000px) rotateY(360deg);
}
}
@keyframes shine {
0%,
15% {
transform: translateY($coin-diameter * 2) rotate(-40deg);
}
50% {
transform: translateY(-$coin-diameter) rotate(-40deg);
}
}
数据平台前端团队,在公司内负责风神、TEA、Libra、Dorado 等大数据相关产品的研发。我们在前端技术上保持着非常强的热情,除了数据产品相关的研发外,在数据可视化、海量数据处理优化、web excel、WebIDE、私有化部署、工程工具都方面都有很多的探索和积累,有兴趣可以与我们联系。对产品有任何建议和反馈也可以直接找我们进行反馈 ~
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!