Threejs 3D implements goods switching dynamic effect

Without further ado, let’s look at the presentation

Before I start writing the code, LET me explain a few concepts to make it easier for you to understand

Concept to explain

Scenario (Sence)

All elements are in the scene, and all drawn elements are added to the scene

cosnt scene = new Three.Scene();
Copy the code

Camera

A camera is like a human eye. Only with a camera can you see all objects and light sources in the scene. Camera has orthogonal projection camera and perspective projection camera two kinds. Perspective projection and human eyes see the world is the same, near large and far small; The orthogonal projection is the same size from far to far, so any line that is parallel in three dimensions must be parallel in two dimensions. Perspective cameras are good for most scenes because they look just like the real world; Orthogonal projection camera is suitable for mapping, modeling and other scenes, which is convenient to observe the size proportion between models.

Orthogonal projection camera

OrthographicCamera is a rectangular body determined by six parameters: THREE.OrthographicCamera(left, right, Top, bottom, near, far). These six parameters specify the position of the left, right, top, bottom, front and rear sides of the camera’s display body.

Perspective projection camera

Perspective cameras are the most common type of camera that simulate the vision of the human eye, large near and small (perspective). Fov stands for perspective, and the bigger the Fov, the bigger your eyes open, and the farther away you are, the more you see. PerspectiveCamera(FOV, aspect, near, far) is used for simulating reality.

Light

The main sources of light are as follows: 1. Ambient light, which has the same brightness from all angles, is usually used to specify a base brightness for the whole scene without specifying the position of the light source. 2. Point light source, a light source from a point, the brightness of different object surfaces decreases linearly; 3, parallel light, brightness has nothing to do with the distance between the light source and the object, only with the Angle of parallel light and the object in the plane; The spotlight casts a conical light.

Spot light (Figure 1), parallel light (Figure 2), point light source (Figure 3)

Material

Much of an object’s physical properties depend on its materials, which also determine the appearance of its geometry. Threejs provides several representative materials, commonly used basic materials, specular highlight materials, in addition to Threejs provides the material can also introduce external images, stick to the surface of the object, called texture map.

Renderer

Threejs draws things that eventually need to be displayed on a rectangular canvas on the screen. At this point, we need to render with the WebGLRenderer

const renderer = new Three.WebGLRenderer();
Copy the code

The code

The JS framework uses the Vue UI framework as element-UI

Initialize the DOM node

<div id="app">
    <div id="content" style="height: 500px"></div>
    <div class="selct">
        <div class="title">Part of the selection</div>
        <ul class="list">
           <li v-for="(item, index) in meshList" @click="selectMesh(index)" :class="activeIndex == index ? 'active' : ''">{{item.name}}</li>
        </ul>
        <div class="title">Color choices</div>
        <el-color-picker v-model="color" color-format="rgb" @change="setSelectColor"></el-color-picker>
    </div>
</div>
Copy the code
initEL() {
    this.root = document.getElementById('content');
    this.canvas = document.createElement('canvas');
    this.width = this.root.offsetWidth;
    this.height = this.root.offsetHeight;
    console.log(this.width, this.height);
}
Copy the code

Initialize the scene value

initSence() {
    this.scene = new THREE.Scene();
}
Copy the code

Initialize the light source

initLight() {
    / / the ambient light
    const ambient = new THREE.AmbientLight(0xffffff.0.9);
    / / the point light source
    const point = new THREE.PointLight(0xcccccc.0.1.100);
    / / parallel light
    const directional = new THREE.DirectionalLight(0xffffff.0.5);
    this.scene.add(ambient);
    this.scene.add(point);
    this.scene.add(directional);
}
Copy the code

Initializing the camera

initCamera() {
    const aspect = this.width / this.height;
    this.camera = new THREE.PerspectiveCamera(45, aspect, 1.1000);
    this.camera.position.z = 15;
    this.camera.aspect = aspect;
    this.camera.updateProjectionMatrix();
}
Copy the code

Initialize the renderer

initRenderer() {
    this.renderer = new THREE.WebGLRenderer({ antialias: true });
    this.renderer.setSize(this.width, this.height);
    this.renderer.setClearColor(0xeeeeee.1);
    this.canvas = this.renderer.domElement;
}
Copy the code

Initializing the Controller

initControls() {
    this.controls = new THREE.OrbitControls(this.camera, this.canvas);
    this.controls.minPolarAngle = (Math.PI * 1) / 6;
    this.controls.maxPolarAngle = (Math.PI * 3) / 4;
    this.controls.smooth = true;
    this.controls.smoothspeed = 0.95;
    this.controls.autoRotateSpeed = 2;
    this.controls.maxDistance = 20;
    this.controls.minDistance = 12;
    this.controls.update();
}
Copy the code

Render the canvas

render() {
    this.camera.lookAt(this.scene.position);
    this.renderer.render(this.scene, this.camera);
}
Copy the code

Load model

loadModel() {
    this.loader = new THREE.GLTFLoader();
    this.loader.load('./model/scene.gltf'.(model) = > {
        let index = 1;
        model.scene.traverse((child) = > {
            if (child instanceof THREE.Mesh) {
                // Reset the material
                child.material.map = null;
                child.name = 'modules' + index;
                index++;
                this.meshList.push(child);
                this.meshColorList.push('rgb(0, 0, 0)');
            }
            this.activeMesh = this.meshList[0];
        });
        this.scene.add(model.scene);
        this.renderer.render(this.scene, this.camera);
    });
}
Copy the code

Select module/color

selectMesh(index) {
    let mesh = this.meshList[index];
    this.activeMesh = mesh;
    this.activeIndex = index;
    this.color = this.meshColorList[index];
    this.setSelectColor(this.color);
},
// Set the color
setSelectColor(value) {
    let rgb = value.replace(/[rgb]|[(]|[)]|\s/g.' ').split(', ');
    let text = this.setTexture(rgb);
    this.activeMesh.material = text;
    this.activeMesh.material.map.needsUpdate = true;
    this.activeMesh.material.needsUpdate = true;
    this.meshColorList[this.activeIndex] = value;
},
// Set the material
setTexture(rgb) {
    var size = 200 * 200;
    var data = new Uint8Array(3 * size);
    for (var i = 0; i < size; i++) {
        var stride = i * 3;
        data[stride] = Number(rgb[0]);
        data[stride + 1] = Number(rgb[1]);
        data[stride + 2] = Number(rgb[2]);
    }
    var texture = new THREE.DataTexture(data, 100.100, THREE.RGBFormat);
    texture.needsUpdate = true;
    return new THREE.MeshPhongMaterial({ map: texture });
}
Copy the code

Update renderer

update() {
    requestAnimationFrame(() = > this.update());
    this.controls.update();
    this.render();
}
Copy the code

The relevant code

Github.com/liyanan666/…