Declan's Blog

Hi, nice to meet you.

  1. 1. CSS3d
    1. 1.1. transform 相关属性介绍:
    2. 1.2. 实现 CSS3D 全景
    3. 1.3. 设置视角
    4. 1.4. 对于全景图素材的要求

CSS3d

项目涉及的技术主要是 CSS3d,3D 全景是其应用场景之一

  • 优势:因为是基于 div+css3 实现,相对 canvas webgl 拥有更好的平台兼容性。
  • 劣势:渲染性能相比 canvas webgl 要弱,只适合创建较小的三维面片场景。

渲染性能这点在项目完成后得到了证实 🤣,由于使用了大量 CSS3 Transform 相关的属性(一个页面内上百个元素),包括 平移(translate)、旋转(rotate)、缩放(scale),导致在性能较差的移动设备上出现了卡顿和发热的情况。

transform 相关属性介绍:

  • transform:修改 CSS 可视化模型的坐标空间,包括 平移(translate)、旋转(rotate)、缩放(scale) 和 扭曲(skew)
  • perspective: 指定了观察者与 z=0 平面的距离,使具有三维变换的元素产生透视效果
  • transform-style:为子元素提供 2D 还是 3D 的场景。另外,该属性是非继承的
  • transform-origin:允许被转换元素位置

实现 CSS3D 全景

什么是全景?

当你站在一个点,身体旋转 360°,这个过程看到的画面就是以你为中心的全景图了,焦距不变时等同于站在一个圆柱体的中心。

那么当我们有了全景图的素材后,将其切割为若干份,通过 transform 的平移和旋转将其拼为一个多棱柱,并通过 perspective 将视角置于棱柱中心(计算机世界是离散的,不能实现完美的圆柱,只能用近似圆柱的棱柱来代替),就实现了全景效果。

未来城活动页是将全景图分割成 60 等份,相邻的元素构成夹角 6°(360/60,相邻两侧面相对于棱柱中心所构成的夹角)。需要注意的是:我们要确保每个元素的正面是指向棱柱中心的。所以要计算好每等份的旋转角度值后,再将元素向外(即 Z 轴方向)平移 r px。对于立方体的 r 就是 边长/2。

举个栗子:对于正九棱柱,每个元素的宽为 210px,对应的角度为 40°。

由此可得到一个公用函数,只需传入含有元素的宽度和元素数量的对象,即可得到 r 值:

1
2
3
4
5
6
7
function calTranslateZ(opts) {
return Math.round(opts.width / (2 * Math.tan(Math.PI / opts.number)));
}
calTranlateZ({
width: 210,
number: 9
}); // 288

设置视角

正棱柱构建完成后,需要将我们的视角设置在正棱柱内,超过视角外的元素不会被浏览器渲染(translateZ > perspective),并且保证棱柱的正面都是指向正棱柱中心,就可以形成 360° 的环绕效果了。

1
2
3
4
#view(perspective:1000px)
#stage(transform-style:preserve-3d)
#cube(transform-style:preserve-3d)
.div(width:600px;height:600px;) /*组成棱柱的元素*/

只要保证.div 元素自身 Z 坐标和祖先元素 Z 坐标相加大于 #view 元素的 perspective 值即可。

对于全景图素材的要求

  1. 水平方向上需要首尾相连
  2. 因为效果图最终需要切成 N 等份,所以尽可能让 设计图的宽度能被 N 整除
  3. 图片尺寸不仅要考虑正视图的大小,还要考虑元素在上下旋转时依然能覆盖视野

参考资料

  • 前端的 3D(css3 版本)–淘宝造物节 3D 创景的制作
  • CSS 3D Panorama - 淘宝造物节技术剖析
  • 另外项目中使用了一个小巧实用的辅助支持库,对相关元素及方法进行了封装:css3d-engine
This article was last updated on days ago, and the information described in the article may have changed.