初学three 添加sprite

354 阅读1分钟

image.png 在three场景中,我们会添加很多建筑模型,增加了模型,意味着需要标识这些属于何种身份,道路,信号灯,银行、大厦等,这里我们一般通过添加图片的方式,进行标识

1、模拟批量创建建筑

// 创建若干个建筑物

const buildCount = 50;

const group = new THREE.Group();

for (let i=0; i<buildCount; i++) {

    const x = randWidth(20);

    const y = randWidth(100);

    const z = randWidth(10);

    const boxGeometry = new THREE.BoxBufferGeometry(x, y ,z);

    const positionX = 300 - randWidth(600);

    const positionZ = 300 - randWidth(600);

    boxGeometry.translate(positionX,  y / 2 ,positionZ);

    const material = new THREE.MeshBasicMaterial( { color: 0x5588aa } );
    
    const mesh = new THREE.Mesh(boxGeometry, material);

    mesh.isBuild = true;

    group.add(mesh);

}

scene.add(group);

在前面文章中,我创建了若干个随机建筑物,现在就需要给每个建筑物添加图标展示

// 创建精灵函数,传入父对象

function createLableSprite_jcy(group, x, y, z) {

var spriteMaterial = new THREE.SpriteMaterial({

map: new THREE.TextureLoader().load("./textures/icon-build.png"), //设置精灵纹理贴图

transparent: true, //开启透明(纹理图片png有透明信息)

});

// 创建精灵模型对象,不需要几何体geometry参数

var sprite = new THREE.Sprite(spriteMaterial);

sprite.scale.set(10, 10, 10); //精灵大小

    sprite.position.set(x, y, z)

// 把精灵模型插入到模型对象的父对象下面

group.add(sprite);

// 父对象group位置变化,网格模型及其对象的标签同样发生变化

group.position.set(group.position.x, group.position.y, group.position.z);

// 表示标签信息的精灵模型对象相对父对象设置一定的偏移

sprite.translateY(y+10);

return group;

}

上面代码是添加雪碧图后,添加到模型的父对象中,使用到group的方法

2、添加图标sprite

代码示例

const geometry = new THREE.BoxGeometry( 1, 1, 1 );

const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );

const cubeA = new THREE.Mesh( geometry, material );

cubeA.position.set( 100, 100, 0 );

const cubeB = new THREE.Mesh( geometry, material );

cubeB.position.set( -100, -100, 0 );

//create a group and add the two cubes

//These cubes can now be rotated / scaled etc as a group

const group = new THREE.Group();

group.add( cubeA );

group.add( cubeB );

scene.add( group );

从官网的代码示例中,可以看到group类似html中的div,当我们需要对一部分标签包裹的时候,就会外套一个div 命名为wrap;

所以我们最后只需要将createLableSprite_jcy在for循环中调用,传入建筑以及建筑的坐标即可,

createLableSprite_jcy(mesh, positionX,  y / 2 ,positionZ);

以上的group是将50个柱形建筑整体打包成一体,所以后续针对小车添加图标,我们需要另外声明一个group

3、移动的图标

小车需要图标,但是小车是运动的,坐标是实时变化的,所以我们需要将小车和 图标绑定在一起,包裹

const carGroup = new THREE.Group();

之前对小车mesh旋转调整的,现在需要针对carGroup 

carGroup.rotation.y = - Math.PI / 2;

把雪碧图和小车模型都添加到group

let spriteMaterial = new THREE.SpriteMaterial({

// 设置精灵纹理贴图

  map: new THREE.TextureLoader().load("./textures/icon-car.png"),  

transparent: true, //开启透明(纹理图片png有透明信息)

});

    carGroup.add(carModel);

// 创建精灵模型对象,不需要几何体geometry参数

const sprite = new THREE.Sprite(spriteMaterial);

sprite.scale.set(10, 10, 10); //精灵大小

// sprite.position.set(-1.6721884850946012, -1.368973127897772e-13, 360.53068686806284)

// 把精灵模型插入到模型对象的父对象下面

carGroup.add(sprite);

carGroup.position.set(-1.6721884850946012, -1.368973127897772e-13, 360.53068686806284);

sprite.translateY(carGroup.position.y + 20);

scene.add( carGroup );

因为雪碧图和小车同时运动,所以最后运动的是carGroup ,

let progress = 0;

function moveCamera() {

    if (progress <= 1 - 0.00004 * 20){

        const point = curve.getPointAt(progress) //获取样条曲线指定点坐标,作为相机的位置

        const pointBox = curve.getPointAt(progress + 0.00004 * 20) //获取样条曲线指定点坐标

        if (carGroup) {

            carGroup.position.set(pointBox.x, pointBox.y, pointBox.z);

            carGroup.lookAt(point.x, point.y, point.z);

        }

        progress += 0.00004

    } else {

        progress = 0

    }

}

参考链接:

Threejs使用精灵Sprite作为标签,鼠标悬浮精灵上时鼠变小手blog.csdn.net/baidu_29701…

我正在参加「创意开发 投稿大赛」详情请看:掘金创意开发大赛来了!