更新于 

CSS3DRenderer:Sprite

Sprite用于创建总是面对相机的实体,
CSS3DSprite则是用于创建总是面对相机的三维定位的dom元素。

创建CSS3DSprite的方法和CSS3DObject一样:

1
const object = new CSS3DSprite(domElement)

金属表层球体实际上是一张图片:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const image = document.createElement('img') // 创建图片元素
image.addEventListener('load', function(){
// 初始化坐标
for(let i = 0; i < particlesTotal; i++){
const object = new CSS3DSprite(image.cloneNode()) // 创建CSS3DSprite
object.position.x = Math.random() * 4000 - 2000
object.position.y = Math.random() * 4000 - 2000
object.position.z = Math.random() * 4000 - 2000
scene.add(object)
objects.push(object)
}
transition()
})
image.src = './assets/img/sprite.png'

这个例子的变换原理和 元素周期表 完全一样,
需要额外介绍的是几种不同图形的坐标的计算方式。

波浪面

这里的波浪面以xz平面为水平面,y方向波形起伏。

由于波浪面形状是由无数点位组成的,首先需要计算出这些点位的坐标:

  • amountX:沿x轴方向,一行的点数
  • amountZ:沿z轴方向,一行的点数
  • separationPlane:点与点之间的间距

知道这些之后就可以得到一张平面,
但是还需要给平面一个位移,使其从xz平面第一象限的位置移动到正中间:

1
2
3
// 实际上就是计算出平面宽高的一半
const offsetX = (amountX-1)*separationPlane/2;
const offsetZ = (amountZ-1)*separationPlane/2;

x轴和z轴的计算都比较简单:

1
2
3
// 点位序号 = i
const x = (i%amountX)*separationPlane - offsetX;
const z = Math.floor((i/amountX)%amountZ)*separationPlane - offsetZ;

y轴计算是xz轴坐标的结合,其中涉及到一些调幅和三角函数的原理,我不懂就不多bb了

1
const y = (Math.sin(0.5*x) + Math.sin(0.5*z)) * 200
球形

球形之前用的是Vector3.setFromSphericalCoords
这个接口获取到球坐标系下的坐标需要用到3个参数:半径、方位角、极角,
当然也可以手动把直角坐标转化为球坐标:

1
2
3
4
5
6
// 极角 = theta
// 方位角 = phi
// 半径 = radius
const x = radius * Math.cos(theta) * sin(phi)
const y = radius * Math.sin(theta) * sin(phi)
const z = radius * Math.cos(phi)

除了坐标计算的方式不同之外,
这个例子中还有一个不同之处,就是坐标点的存储方式:
由于涉及到延时自动切换形状,
这里将所有坐标都放在同一个数组中,类似于二维数组打平成一维数组取值:

1
2
3
4
// offset = 当前变换形状的首坐标
// current = 当前变换形状的序号
// particlesTotal = 数组总数
const offset = current * particlesTotal * 3

最后在AnimationFrame函数中,添加了一个物体跟随x轴位置,随时间进行动态收缩的动画,
其中用到了performance.now()
用于获取一个高精度的时间帧:

1
2
3
4
5
6
const time = performance.now()
for(let i = 0, l = objects.length; i < l; i++){
const object = objects[i]
const scale = Math.sin(Math.floor(object.position.x) + time) * 0.002 * 0.3 + 1
object.scale.set(scale, scale, scale)
}
衍生样式