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 | function calTranslateZ(opts) { |
设置视角
正棱柱构建完成后,需要将我们的视角设置在正棱柱内,超过视角外的元素不会被浏览器渲染(translateZ > perspective),并且保证棱柱的正面都是指向正棱柱中心,就可以形成 360° 的环绕效果了。
1 | #view(perspective:1000px) |
只要保证.div 元素自身 Z 坐标和祖先元素 Z 坐标相加大于 #view 元素的 perspective 值即可。
对于全景图素材的要求
- 水平方向上需要首尾相连
- 因为效果图最终需要切成 N 等份,所以尽可能让 设计图的宽度能被 N 整除
- 图片尺寸不仅要考虑正视图的大小,还要考虑元素在上下旋转时依然能覆盖视野
参考资料
- 前端的 3D(css3 版本)–淘宝造物节 3D 创景的制作
- CSS 3D Panorama - 淘宝造物节技术剖析
- 另外项目中使用了一个小巧实用的辅助支持库,对相关元素及方法进行了封装:css3d-engine