前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Three.js的入门案例(下)

Three.js的入门案例(下)

作者头像
前端达人
发布2021-03-16 16:11:17
2.7K0
发布2021-03-16 16:11:17
举报
文章被收录于专栏:前端达人

关注初识Threejs与小编一起学习成长

上一篇案例中实现了几何体-球体旋转效果,今天继续丰富这个案例效果,在球体的周围添加光圈及旋转模块(图片+文字组成),均匀的分布在球体周围,围绕着球体逆时针旋转,最终效果如图:

知识点

1、基础线条材料、线条模型;

2、矩形平面模型;

3、射线拾取;

01

绘制光圈

围绕着球体绘制光圈。定义好参数(大小、透明度、颜色等),循环绘制四个大小不一,不同透明度的椭圆,调整好位置,效果如图:

代码如下:

代码语言:javascript
复制
_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;
    }
}

02

绘制球体周围模块

在球体周围绘制可点击模块,我们这里使用默认图片与业务名称合并生成一张新图片,然后通过矩形平面模型、基础网孔材料设置纹理贴图的方式。核心代码:

代码语言:javascript
复制
_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);//将周围旋转模块添加到场景中
}

在周期性渲染场景方法中添加:

代码语言:javascript
复制
moons.rotation.y += Math.PI / 180 / delay * intc;//球体周围模块旋转

方可围绕球体旋转。

03

触发点击事件

通过使用Raycaster对象来实现(射线拾取)点击效果:

代码如下:

代码语言:javascript
复制
_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 {
    }
}

可以通过射线拾取达到与鼠标交互的效果,大家就可以根据自身的业务做出处理,比如弹框等。

04

写在最后

至此这个案例就结束了,在绘制周围模块的方案上不是很友好,要每个模块生成两种状态的图片,大家也可以想想有没有更好的解决方案,期待与您交流学习,快去动手实践吧~

如果你对本文内容有任何建议,欢迎与小编沟通交流,一起学习成长!关注公众号回复three.js,获取完整案例代码。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-03-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 前端达人 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档