Three.js的入门案例(下)

关注初识Threejs与小编一起学习成长
在上一篇案例中实现了几何体-球体旋转效果,今天继续丰富这个案例效果,在球体的周围添加光圈及旋转模块(图片+文字组成),均匀的分布在球体周围,围绕着球体逆时针旋转,最终效果如图:
   知识点
1、基础线条材料、线条模型;
2、矩形平面模型;
3、射线拾取;
绘制光圈
围绕着球体绘制光圈。定义好参数(大小、透明度、颜色等),循环绘制四个大小不一,不同透明度的椭圆,调整好位置,效果如图:
       代码如下:
_this.drawCircle=function(){//光圈参数(大小、透明度)var param = [{ size: 7, opacity: '.3' },{ size: 8, opacity: '.5' },{ size: 9.5, opacity: '1' },{ size: 11, opacity: '.2' }];var line;for (var j = 0; j < param.length; j++) {//基础线条材料var lineMaterial = new THREE.LineBasicMaterial({transparent: true, // 开启透明opacity: param[j].opacity,// 透明度color: 'rgb(129,146,255)'//线段颜色});//椭圆曲线var ellipse = new THREE.EllipseCurve(0,0, //椭圆的中心的x、y坐标param[j].size,param[j].size, //椭圆在x,y轴的半径0,//以弧度来表示,从正X轴算起曲线开始的角度2* Math.PI, //以弧度来表示,从正X轴算起曲线终止的角度false,//椭圆是否按照顺时针方向来绘制0//以弧度表示,椭圆从X轴正方向逆时针的旋转角度(可选));var ellipsePath = new THREE.CurvePath();//曲线路径ellipsePath.add(ellipse);var ellipseGeometry = ellipsePath.createPointsGeometry(100);//返回几何体对象//线条模型对象line = new THREE.Line(ellipseGeometry, lineMaterial);scene.add(line);//将光圈添加到场景中line.rotation.x = Math.PI / 2;line.position.y = -1;}}
绘制球体周围模块
在球体周围绘制可点击模块,我们这里使用默认图片与业务名称合并生成一张新图片,然后通过矩形平面模型、基础网孔材料设置纹理贴图的方式。核心代码:
_this.drawModel=function(){var that=this;//创建一个月亮模型分组var moons = window.moons = new THREE.Mesh();/*添加xyz坐标轴*/// var axesHelper = new THREE.AxesHelper(30);// moons.add(axesHelper);//矩形平面模型(x轴宽度、y轴高度、x方向的分段数、y方向的分段数)//要与map贴图比例成正比,否则图片会变形var bufferGeometry = new THREE.PlaneBufferGeometry(4, 2, 2, 2);//基础网孔材料var basicMaterial = new THREE.MeshBasicMaterial({// map: textureLoader.load(modelBg),//设置纹理贴图depthWrite: false,transparent: true,alphaTest: 0,side: 2});var planeMesh = new THREE.Mesh(bufferGeometry, basicMaterial);planeMesh.position.z = 9.5;//球体周围物体的z轴var moonsBox = new THREE.Mesh();moonsBox.add(planeMesh);//循环球体周围的数据for (var i = 0; i < roundData.length; i++) {//解决异步循环(function (i) {//生成带文字的图片that.cenerateImages(i,function (d) {var newMoonBox = moonsBox.clone();//克隆一个网格模型newMoonBox.children[0].material = newMoonBox.children[0].material.clone();// console.log(JSON.stringify(roundData[i].imgh));//更新带文字的图片,保存模块数据(id、索引等)newMoonBox.children[0].material.map = textureLoader.load(roundData[i].img);newMoonBox.children[0].roundData = roundData[i].id;newMoonBox.children[0].roundData_index = i;//旋转位置,均匀分布球体周围newMoonBox.rotation.y = Math.PI * 2 / roundData.length * i;//渲染之后直接执行newMoonBox.onBeforeRender = function (renderer, scene, camera, geometry, material) {this.children[0].lookAt(this.children[0].getWorldPosition(new THREE.Vector3()).add(camera.position));}moons.add(newMoonBox);});})(i)}scene.add(moons);//将周围旋转模块添加到场景中}
在周期性渲染场景方法中添加:
moons.rotation.y += Math.PI / 180 / delay * intc;//球体周围模块旋转
       方可围绕球体旋转。
触发点击事件
通过使用Raycaster对象来实现(射线拾取)点击效果:
       代码如下:
_this.onDocumentClick=function(event) {var raycaster = new THREE.Raycaster();var mouseVector = new THREE.Vector3();event.preventDefault();//防止冒泡mouseVector.x = (event.offsetX / canvasWidth) * 2 - 1;mouseVector.y = -(event.offsetY / canvasHeight) * 2 + 1;raycaster.setFromCamera(mouseVector, camera); // 设置射线拾取的参数selectObject = raycaster.intersectObjects(moons.children, true)[0];if (selectObject&&selectObject.object) {//初始化选中的样式var clickThat = selectObject.object.parent.children;if (clickThat.length > 0) {//清空之前选中样式for (var i = 0; i < moons.children.length; i++) {var tempobj=moons.children[i].children[0];tempobj.material.map = textureLoader.load(roundData[tempobj.roundData_index].img);}var idcont = selectObject.object.roundData;//当前选中的值var idcontIndex = idcont - 1 < 0 ? 0 : idcont - 1;selectObject.object.material.map = textureLoader.load(roundData[idcontIndex].imgh);//更新当前选中模块样式}else {}}else {}}
可以通过射线拾取达到与鼠标交互的效果,大家就可以根据自身的业务做出处理,比如弹框等。
写在最后
至此这个案例就结束了,在绘制周围模块的方案上不是很友好,要每个模块生成两种状态的图片,大家也可以想想有没有更好的解决方案,期待与您交流学习,快去动手实践吧~
      你“在看”我吗?
  评论
