纯CSS生成伪球体附Vue实现源码

效果展示

请添加图片描述
成品的效果如上所示,如果懒得看具体实现过程,可以点这里直接跳转到源码部分。今天也算是突发奇想,想手搓个太阳系出来,那就先从最具代表性的土星做起。

实现逻辑

主要的构造很简单:.ballContainer用来储存球体,.ball是球体本身。

<div class="ballContainer">
	<div class="ball"></div>
</div>

先给球体容器一些初始属性,比如位置和颜色:

.ballContainer {
  position: absolute;
  width: 600px;
  height: 600px;
  top: 200px;
  left: 500px;
  background: radial-gradient(circle at 33% 33%, rgba(255, 255, 255, 0.8) 0%, rgba(231, 146, 61, 0.85) 80%);
}

球体目前看起来是这样的。
球体目前看起来是这样的
颜色看起来不错,接着让它变成一个圆形,添加border-radius属性。

border-radius: 50%;

形状变成了圆形
球体的容器到这一步已经实现完成,接下来我们要实现球体本身的作用 —— 旋转。我的思路是这样的,首先让球体容器的配色看起来像是一个球体,但它实质上只是一个正面对面观察者的圆形平面,该平面本身不会做任何运动。运动都交给球体容器内的.ball和.halo。
我们给球体添加一个子div —— .halo,我们的光环。并为球体添加一个充满3d感的运动效果。

<div class="ballContainer">
	<div class="ball">
    	<div class="halo"></div>
  	</div>
</div>

<style>
@keyframes ballRotate {
  0% {
    transform: rotateX(10deg) rotateY(0deg) rotateZ(10deg) ;
  }
  50% {
    transform: rotateX(-15deg) rotateY(720deg) rotateZ(-10deg) ;
  }
  100% {
    transform: rotateX(10deg) rotateY(0deg) rotateZ(10deg) ;
  }
}
.ball {
  transform-style: preserve-3d;
  animation: ballRotate 20s infinite linear;
  width: 100%;
  height: 100%;
}

.halo {
  transform-style: preserve-3d;
  position: absolute;
  top: -200px;
  left: -200px;
  width: 1000px;
  height: 1000px;
  transform: rotateX(90deg);
  background: conic-gradient(#FF5800, #FF8100, #FEAC00, #FFCC00, #EDE604);
  border-radius: 50%;
  /*中间镂空*/
  mask: radial-gradient(transparent 400px, #000 200px);
}
</style>

球体的旋转是真实存在的,它带动着光环做三个方向的转动。
光环跟着旋转
从图中可以看到,光环遮挡了球体容器,这导致3d效果大幅降低。解决办法是在球体容器上添加 transform-style: preserve-3d属性。至此,主要的效果已经实现,接下来是锦上添花环节。我们在.ballContainer外侧套上一个.body div,将背景设置为黑色;接着为.ballContainer添加一个景深效果。

transform: translateZ(2000px);
perspective: 1000px;

这里添加这两行样式的原因是,之后可以通过修改perspective属性,改变观察者与球体之间的距离,实现更好的3d效果。

源码

<template>
  <div class="body">
    <div class="ballContainer">
      <div class="ball">
        <div class="halo"></div>
      </div>
    </div>
    <div class="visionControl">
      <span>拖动我!</span>
      <input type="range" class="rangeInput" min="250" max="1000" v-model="range">
    </div>
  </div>
</template>

<script>
export default {
  name: "ZTest",
  data() {
    return {
      range: 750
    }
  },
  watch: {
    range(input) {
      let ballContainer = document.querySelector('.ballContainer')
      ballContainer.style.perspective = input + 'px'
    }
  }
}
</script>

<style scoped>
@keyframes ballRotate {
  0% {
    transform: rotateX(10deg) rotateY(0deg) rotateZ(10deg) ;
  }
  50% {
    transform: rotateX(-15deg) rotateY(720deg) rotateZ(-10deg) ;
  }
  100% {
    transform: rotateX(10deg) rotateY(0deg) rotateZ(10deg) ;
  }
}
* {
  margin: 0;
  padding: 0;
}
.body {
  height: 100vh;
  width: 100vw;
  background-color: #000;
  overflow: hidden;
}
.visionControl {
  z-index: 1000;
  background-color: white;
  height: 75px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.ballContainer {
  transform-style: preserve-3d;
  position: absolute;
  width: 600px;
  height: 600px;
  top: 200px;
  left: 500px;
  background: radial-gradient(circle at 33% 33%, rgba(255, 255, 255, 0.8) 0%, rgba(231, 146, 61, 0.85) 80%);
  border-radius: 50%;
  transform: translateZ(2000px);
  perspective: 1000px;
}

.ball {
  transform-style: preserve-3d;
  animation: ballRotate 20s infinite linear;
  width: 100%;
  height: 100%;
}

.halo {
  transform-style: preserve-3d;
  position: absolute;
  top: -200px;
  left: -200px;
  width: 1000px;
  height: 1000px;
  transform: rotateX(90deg);
  background: conic-gradient(#FF5800, #FF8100, #FEAC00, #FFCC00, #EDE604);
  border-radius: 50%;
  /*中间镂空*/
  mask: radial-gradient(transparent 400px, #000 200px);
}
</style>

总结

当时做这个模拟球体的时候,也是考虑了很多可能性和方法,无奈一直都没办法用纯CSS实现真正意义上的球体。所以如果想要绘制真正的球体,还是交给canvas吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值