在2020年春节来临之际,我们WeGame推出春节促销活动。随着 CINEMA 4D 越来越被设计师普及,3D逐渐成为了当前的一种设计趋势,相比于平面页面,3D能给用户带来更真实的交互场景从而获得更好的体验。最近我们也有了一定的3D技术储备,因此将Web 3D技术应用到了在此次春节活动中。
项目展示
Web 3D相比传统2D展示氛围及带入感更强。我们使用的是threeJS库,完成threejs 3D微场景搭建的同时丰富页面中的交互,增强场景春节氛围感。
项目体验地址(PC端):
https://test.mwegame.qq.com/ui/act/wegame/act-pc/wegame-20191224-newyear/server/
在进入场景时我们需要控制摄像机的轨迹来达到环视3D模型的效果,这一效果需要通过弧度算取欧拉角旋转来实现的。(如下图摄像机运动轨迹的曲线绘制方法,坐标v0为3D模型)1、如何通过两点计算出运动轨迹
计算三维向量中心点坐标:
代码:
getVectorCenter: function(v1, v2){ * [add] [divideScalar] 均为Vector3自带方法函数 return v1c.add(v2c).divideScalar(2);其中Vector3中提供基础方法
根据圆心和中心点坐标,得到一个点的射线:
代码:
// 通过Ray,得到射线段
var rayLine = new THREE.Ray(new THREE.Vector3(0,0,0), vectorCenter)
// 在射线段先随意定义一个射线顶点
// at可以设置射线的距离,并且返回Vector3坐标
// rayLine.at(1) == vectorCenter, 将向量中心点距离圆心长度 * n
var vtop = rayLine.at(10)
根据射线顶点 + 起始点与终点坐标,可以随意选取线段内的控制点坐标:
根据起始点+终点+控制点坐标,可以绘制贝塞尔曲线,仍然存在几个优化点:
当起点与终点象限重合时,仍然会被绘制曲线
即使通过两点获得出一条曲线后,会发现相机在位置1时,移动的路径可能不会出现问题,但是相机在位置2的时候,此时相机2距离视点位置较近,不需要作曲线。获得相机位置点到视点的直线距离,再减去半径获得差值,当差值小于0时,代表相机位置距离视点小于半径则直接做直线运动,再用差值除以直径就获得出比例。var len = starPos.distanceTo(endPos) - three3D.radius <= 0 ? 0 : starPos.distanceTo(endPos) - three3D.radius;var ratio = len / ( three3D.radius * 2 ) <= 1 ? len / ( three3D.radius * 2 ) : 1;2、雪花效果
春节活动在冬天,因此我们需要雪花来衬托冬天的氛围。制作3D下雪场景需要如下几个步骤:
var texture = new THREE.TextureLoader().load("./images/snow0.png");//样式化粒子的THREE.PointCloudMaterial材质 var material = new THREE.PointsMaterial({ transparent: transparent, vertexColors: vertexColors, sizeAttenuation: sizeAttenuation, depthTest: false //设置解决透明度有问题的情况 var geom = new THREE.Geometry(); //存放粒子数据的网格 var range = 2400; //生成雪花的坐标范围 for (var i = 0; i < 700; i++) { //生成700个雪花var particle = new THREE.Vector3(Math.random() * range - range / 2, Math.random() * range - range / 2, Math.random() * range - range / 2); particle.velocityY = (0.1 + Math.random() / 5) * 20; particle.velocityX = ((Math.random() - 0.5) / 3) * 10; particle.velocityZ = ((Math.random() - 0.5) * 3) * 10; geom.vertices.push(particle); var color = new THREE.Color(0xffffff); cloud = new THREE.Points(geom, material); cloud.verticesNeedUpdate = true;Snow.prototype.snowRender = function () { var vertices = cloud.geometry.vertices; vertices.forEach(function (v, index) { v.y = v.y - (v.velocityY) * .3; v.x = v.x - (v.velocityX) * .05; v.z = v.z - (v.velocityZ) * .05; if (v.y <= -1200) v.y = 1200; if (v.x <= -400 || v.x >= 400) v.velocityX = v.velocityX * -0.1; if (v.z <= -400 || v.z >= 400) v.velocityZ = v.velocityZ * -0.1; cloud.geometry.verticesNeedUpdate = true;3、音乐动画
通过用欢快的音乐衬托出春节喜气洋洋的节日氛围。
代码:
// 音符从小变大
var scaleSize,
endScale = 0.015;
if (obj.position.y > endCoord.y) {
scaleSize = 0;
} else if (obj.position.y < endCoord.y) {
scaleSize = ((obj.position.y - startCoord.y) / (endCoord.y - startCoord.y)) * endScale;
}
// 控制透明度
var opacityVal;
if (obj.position.y < startCoord.y + 3 || obj.position.y > endCoord.y) {
opacityVal = 0;
} else if (((startCoord.y + 3) <= obj.position.y) && (obj.position.y < (startCoord.y + 25))) {
opacityVal = 1;
}
else {
opacityVal = 1 - ((obj.position.y - (startCoord.y + 25)) / (endCoord.y - startCoord.y - 25));
}
opacityVal = opacityVal > 0 ? opacityVal : 0
// 如果音符飘到顶,则重置回到初始值
if (obj.position.y > endCoord.y) {
obj.position.y = startCoord.y;
obj.position.z = startCoord.z;
obj.material.opacity = 0
}
4、全屏幕适配
设计稿为标准的1920px*1080px尺寸,但在小屏幕或笔记本下会出现内容显示不全的问题,给用户带来了不友好的体验。
以宽度1920px,高度1080px为参考基准,我们进行了全设备的兼容,步骤如下:
4.1、分析屏幕尺寸,以参考基础为标准,一共有五种情况:
A情况:“宽等于1920px,高等于1080px”,B情况:“宽大于1920px,高大于1080px”C情况:“宽小于1920px,高小于1080px”D情况:“宽大于1920px,高小于1080px”E情况:“宽小于1920px,高大于1080px”我们获取到此时浏览器实际宽高后,需要分辨出此时浏览器尺寸是“扁的”还是“高的”。
扁的情况⬆️
高的情况⬆️
设置一个基准比例:
BaseRate = 1920/1080 = 1.777;
设置一个实时比例:
Rate = PageWidth/PageHeight;
所以,“扁的”情况为Rate > BaseRate,“高的”情况为 Rate < BaseRate。
核心点:获取出当前浏览器是“扁的”还是“高的”情况,并计算缩放比例系数。
4.3、通过比例系数进行缩放和内容重新定位。
当宽高都大于1920px*1080px时:不进行放大缩放,但要对内容进行垂直和水平居中定位。
当宽高都小于1920px*1080px时:
若为“扁的”情况:则需要对高度进行缩放,并且垂直居中。
若为“高的”情况:则需要对宽度进行缩放,并且水平居中。
同理,在各种情况下,我们需要对其缩放系数进行计算后进行缩放,同时还需要对内容进行垂直或水平方向的重新定位。
同时我们还需要使用window.onresize函数进行实时监听,保证用户在手动缩放浏览器大小的时候也能进行适配。
核心点:缩放后内容的重新定位,window.onresize函数的实时监听。
这样我们在各种屏幕大小下,都能满足非常好的用户阅读体验,保证用户在浏览页面的过程中全部信息的获取。 后期性能测试
测试目的:了解实际项目在Web3D中的性能影响,将数据提供给开发进行兼容处理。根据测试提供的wegame用户机型配置数据来对比,此次测试主要分为三种机型配置 4G显存(中高配)、2G显存(中配)、1G显存(中低配)。测试方向:1、页面首次载入数据。2、页面3D交互数据。1、低配机器测试过程中GPU使用率在95%+,但是页面浏览流畅,并无明显卡顿感,FPS总体维持在35以上。在中配机器测试过程中GPU使用率平均在32%左右,页面流畅无卡顿,FPS维持在55左右。2、通过3D场景的体验中发现,低配机器CPU平均占用在25%左右,在页面首次载入的时候,CPU占用会有2-3秒左右飙升到40%。中低配机器CPU平均占用在16%左右,首次载入时会有2-3秒飙升到37%。
测试总结:项目在测试过程中发现,在非客户端内嵌的情况下,基本都可以流畅的体验web3d,因此我们也放弃2d兼容方案。
项目优化
项目后期因增加了设计师提供的模型,使得项目资源大小增加了10M,因此采用Draco 压缩方案进行优化3d模型的资源大小。Draco是一个用于压缩、解压缩 3D 几何网格和点云的开源库,为改善 3D 图形存储和传输而设计。使用draco可以对 glTF 格式进一步的压缩,原本10M的GLTF文件被压缩到1M。
以往使用视频方式做kv,通常会准备一个入场资格,循环视频,大小往往超过5m,此次春节活动仅仅只需要加载1M的模型即可。同时视频仅仅只能展示,而web3D方案交互性更加丰富。 项目总结
Web 3D主要攻克技能点
1、根据rgb主站场景进行点击曲线路径控制
2、3D雪花氛围效果
3、模型效果测试反馈
4、根据实际3D场景效果进行交互优化
5、物体的圆形运动轨迹
6、模型贴图与模型动画控制
7、将雪花效果改成漂浮动画z
8、云动画 + 简单漂浮动画
后期功能完善
1、模型还原、交互还原
2、入场动画
3、场景增加文字信息
4、模型加载与引导动画
5、性能测试准备
参考文档
https://segmentfault.com/a/1190000019449497https://threejs.org/examples/?q=light#webgl_lights_spotlightshttps://threejs.org/docs/index.html#examples/zh/loaders/DRACOLoader https://segmentfault.com/a/1190000019449497 http://www.yanhuangxueyuan.com/doc/Three.js/MeshStandardMaterial.htmlhttps://threejs.org/docs/index.html#api/zh/materials/MeshStandardMaterial https://threejs.org/examples/#webgl_points_sprites——扫码关注P&P Design,看更多设计分享——