Preface:

Hello everyone, I am yan Director of XX media.

The main technologies used in this article: vue3, three.js

Let’s take a look at the finished product:

High definition large image preview (a bit slow) :

Landline preview:

Let’s cut to the chase

The basics of three.js

What do you need in a virtual 3D world? Above all, should have a stereo space, it is to have illuminant next, the most important is to want to have a pair of eyes. Let’s see how to create a 3D world in three.js.

  1. Create a scene
  2. Set the light source
  3. Create the camera, set the camera position and the camera lens orientation
  4. Create a 3D renderer and use it to render the scene

At this point, you have created a visual 3D page using three.js.

On the scene

You can add background colors to the scene, or create a box model (sphere, cube), paste images inside the box model, and place the camera inside the box model to simulate the scene. Box models are often used for 360-degree panoramas, such as house VR displays

[Landing page] Example of creating a scene:

const scene = new THREE.Scene()
// Add the Fog effect to the scene. The Fog parameter represents' the color of the Fog ', 'the distance at which the Fog starts', and the distance at which the Fog just disappears'.
scene.fog = new THREE.Fog(0x000000.0.10000)
// Depth of the box model
const depth = 1400
// Add a spherical box model to the scene
// create a cube
const geometry = new THREE.BoxGeometry(1000.800, depth)
// 2. Load the texture
const texture = new THREE.TextureLoader().load('bg.png')
// 3. Create mesh material (raw material)
const material = new THREE.MeshBasicMaterial({map: texture, side: THREE.BackSide})
// 4. Generate a grid
const mesh = new THREE.Mesh(geometry, material)
// 5. Put the grid into the scene
scene.add(mesh)
Copy the code

About the light source

Set the color and intensity of the light source for the scene. You can also set the type of light source (ambient light, point light, parallel light, etc.) and the position of the light source

Example of creating light source:

// 1. Create ambient light
const ambientLight = new THREE.AmbientLight(0xffffff.1)
// 2. Create a point light source at the bottom right corner of the scene
const light_rightBottom = new THREE.PointLight(0x0655fd.5.0)
light_rightBottom.position.set(0.100, -200)
// 3. Place the light source in the scene
scene.add(light_rightBottom)
scene.add(ambientLight)
Copy the code

About the camera (Important)

A very important step. The camera is your eye. We will also highlight some of the problems we may encounter when using perspective cameras. The most commonly used cameras are orthogonal cameras and perspective cameras.

Orthogonal camera: The size of the object in the final rendering remains the same regardless of whether the object is close or far from the camera. This is useful for rendering 2D scenes or UI elements. As shown in figure:

Figure comments:

  1. The red triangular cone is the size of the field of view
  2. The first surface attached to the red cone is the closest the camera can see
  3. The surface extending from it through the white guides is the farthest the camera can see

Perspective camera: Used to simulate what the human eye would see. It is the most common projection mode used in 3D scene rendering. As shown in figure:

When we use perspective cameras, we may encounter this situation: the object at the edge will have a certain degree of deformation, the reason is: perspective cameras are fisheye effect, the larger the field of view, the larger the deformation of the edge. To avoid edge distortion, the FOV Angle can be set smaller and the distance wider

PerspectiveCamera: New THREE.PerspectiveCamera(FOv, width/height, near, far)

  • Fov (Field of View) – The vertical field of view of the camera cone
  • Aspect (width/height) – The aspect ratio of the camera’s viewing cone
  • Near – The near end of the camera’s visual cone
  • Far – Distal end of camera cone
/** * To avoid edge distortion, set the foV Angle smaller and the distance wider. * Fix the view Angle to find the distance required for the full view screen * 15 degrees equals (math.pi / 12) */
const container = document.getElementById('login-three-container')
const width = container.clientWidth
const height = container.clientHeight
const fov = 15
const distance = width / 2 / Math.tan(Math.PI / 12)
const zAxisNumber = Math.floor(distance - depth / 2)
const camera = new THREE.PerspectiveCamera(fov, width / height, 1.30000)
camera.position.set(0.0, zAxisNumber)
const cameraTarget = new THREE.Vector3(0.0.0)
camera.lookAt(cameraTarget)
Copy the code

About renderers

Render your carefully crafted scenes with WebGL. It creates a canvas for rendering

Example of creating renderer:

// Get the container DOM
const container = document.getElementById('login-three-container')
// Create a WebGL renderer instance
const renderer = new THREE.WebGLRenderer({ antialias: true.alpha: true })
// Sets the size of the renderer canvas
renderer.setSize(width, height)
// Put the canvas instance into the container
container.appendChild(renderer.domElement)
// Renderer renders the scene
renderer.render(scene, camera)
Copy the code

It is important to note that the scene created in this way has no animation effect because only one frame is rendered. To animate objects in the scene, we need to use requestAnimationFrame, so we can write a loop function

// Animation refresh
const loopAnimate = () = > {
    requestAnimationFrame(loopAnimate)
    scene.rotateY(0.001)
    renderer.render(scene, camera)
}
loopAnimate()
Copy the code

Perfect effect

Create a top left earth

// Load the texture
const texture = THREE.TextureLoader().load('earth_bg.png')
// Create a mesh material
const material = new THREE.MeshPhongMaterial({map: texture, blendDstAlpha: 1})
// Create a geometric sphere
const sphereGeometry = new THREE.SphereGeometry(50.64.32)
// Generate a grid
const sphere = new THREE.Mesh(sphereGeometry, material)
// To manipulate the motion effect of the spheres individually, we put the spheres into a group
const Sphere_Group = new THREE.Group()
const Sphere_Group.add(sphere)
// Sets the group's position in space coordinates
const Sphere_Group.position.x = -400
const Sphere_Group.position.y = 200
const Sphere_Group.position.z = -200
// Add scene
scene.add(Sphere_Group)
// To enable the ball to rotate, need to be added in loopAnimate
Sphere_Group.rotateY(0.001)
Copy the code

Make the Earth spin

Render the rotation of the planet
const renderSphereRotate = () = > {
    if (sphere) {
      Sphere_Group.rotateY(0.001)}}// To enable the ball to rotate, need to be added in loopAnimate
const loopAnimate = () = > {
    requestAnimationFrame(loopAnimate)
    renderSphereRotate()
    renderer.render(scene, camera)
}
Copy the code

Create the stars

// Initialize the star
const initSceneStar = (initZposition: number): any= > {
    const geometry = new THREE.BufferGeometry()
    const vertices: number[] = []
    const pointsGeometry: any[] = []
    const textureLoader = new THREE.TextureLoader()
    const sprite1 = textureLoader.load('starflake1.png')
    const sprite2 = textureLoader.load('starflake2.png')
    parameters = [
      [[0.6.100.0.75], sprite1, 50],
      [[0.0.1], sprite2, 20]]// Initialize 500 nodes
    for (let i = 0; i < 500; i++) {
      /** * const x: Number = Math. The random () * 2 * width - the width * equivalent * THREE MathUtils. RandFloatSpread (width) * _ in the random use lodash generated random number * / in the library
      const x: number = THREE.MathUtils.randFloatSpread(width)
      const y: number = _.random(0, height / 2)
      const z: number = _.random(-depth / 2, zAxisNumber)
      vertices.push(x, y, z)
    }

    geometry.setAttribute('position'.new THREE.Float32BufferAttribute(vertices, 3))

    // Create nodes of 2 different materials (500 * 2)
    for (let i = 0; i < parameters.length; i++) {
      const color = parameters[i][0]
      const sprite = parameters[i][1]
      const size = parameters[i][2]

      materials[i] = new THREE.PointsMaterial({
        size,
        map: sprite,
        blending: THREE.AdditiveBlending,
        depthTest: true.transparent: true
      })
      materials[i].color.setHSL(color[0], color[1], color[2])
      const particles = new THREE.Points(geometry, materials[i])
      particles.rotation.x = Math.random() * 0.2 - 0.15
      particles.rotation.z = Math.random() * 0.2 - 0.15
      particles.rotation.y = Math.random() * 0.2 - 0.15
      particles.position.setZ(initZposition)
      pointsGeometry.push(particles)
      scene.add(particles)
    }
    return pointsGeometry
}
const particles_init_position = -zAxisNumber - depth / 2
let zprogress = particles_init_position
let zprogress_second = particles_init_position * 2
const particles_first = initSceneStar(particles_init_position)
const particles_second = initSceneStar(zprogress_second)
Copy the code

Make the stars move

// Render the motion of the stars
const renderStarMove = () = > {
    const time = Date.now() * 0.00005
    zprogress += 1
    zprogress_second += 1

    if (zprogress >= zAxisNumber + depth / 2) {
      zprogress = particles_init_position
    } else {
      particles_first.forEach((item) = > {
        item.position.setZ(zprogress)
      })
    }
    if (zprogress_second >= zAxisNumber + depth / 2) {
      zprogress_second = particles_init_position
    } else {
      particles_second.forEach((item) = > {
        item.position.setZ(zprogress_second)
      })
    }

    for (let i = 0; i < materials.length; i++) {
      const color = parameters[i][0]

      const h = ((360 * (color[0] + time)) % 360) / 360
      materials[i].color.setHSL(color[0], color[1].parseFloat(h.toFixed(2)))}}Copy the code

The effect of the star’s motion is actually to move from far away towards the camera’s position along the Z axis, until you move out of the camera’s position and return to the starting point, and repeat. Using god’s perspective, from the left of the X-axis, it looks like this:

Create clouds and motion tracks

// Create a curve path
const route = [
    new THREE.Vector3(-width / 10.0, -depth / 2),
    new THREE.Vector3(-width / 4, height / 8.0),
    new THREE.Vector3(-width / 4.0, zAxisNumber)
]
const curve = new THREE.CatmullRomCurve3(route, false)
const tubeGeometry = new THREE.TubeGeometry(curve, 100.2.50.false)
const tubeMaterial = new THREE.MeshBasicMaterial({
  opacity: 0.transparent: true
})
const tube = new THREE.Mesh(tubeGeometry, tubeMaterial)
// Add the created path to the scene
scene.add(tube)
// Create plane geometry
const clondGeometry = new THREE.PlaneGeometry(500.200)
const textureLoader = new THREE.TextureLoader()
const cloudTexture = textureLoader.load('cloud.png')
const clondMaterial = new THREE.MeshBasicMaterial({
  map: cloudTexture,
  blending: THREE.AdditiveBlending,
  depthTest: false.transparent: true
})
const cloud = new THREE.Mesh(clondGeometry, clondMaterial)
// Add the cloud to the scene
scene.add(cloud)
Copy the code

Now that we have a cloud and a curvilinear path, we need to combine the two and make the cloud follow the path

The cloud movement

let cloudProgress = 0
let scaleSpeed = 0.0006
let maxScale = 1
let startScale = 0
// Initializes the cloud motion function
const cloudMove = () = > {
  if (startScale < maxScale) {
    startScale += scaleSpeed
    cloud.scale.setScalar(startScale)
  }
  if (cloudProgress > 1) {
    cloudProgress = 0
    startScale = 0
  } else {
    cloudProgress += speed
    if (cloudParameter.curve) {
      const point = curve.getPoint(cloudProgress)
      if (point && point.x) {
        cloud.position.set(point.x, point.y, point.z)
      }
    }
  }

}
Copy the code

Complete the effect of three.js

Finally, you can move the cloud by putting the cloudMove function into the loopAnimate function. At this point, all parts of the log-in page related to three.js are covered. The rest of the lunar surface, the landing box, and the astronauts are all done through positioning and hierarchy Settings and CSS3 animations, which won’t be discussed in depth here.

The code for each section above is inconsistent and slightly different from the complete code for the landing page. The above is more about how each part is implemented. Complete code, I put on Github, almost every line of comment on the type, hope to give you into the pit three. Js bring some help, address: github.com/Yanzengyong…

conclusion

Before, I wrote a 3D visualization knowledge graph using React +three.js. If this article is helpful and well received, I will write a follow-up article on how to create a 3D knowledge graph using three.js.

In the end, I think the essence of 3D visualization is actually design. Having good materials and good modeling can make your page look n-fold better in an instant

Three. Js’s official website