After seeing the canvas work of Xiaoqian, I learned to make a 3D earth, which can be regarded as WebGL pit. I used the native Canvas to draw 2D graphics before, but this time I used the 3D framework of three. js and stats.js. After all, this is the first time you’ve been exposed to WebGL

Talk is cheap show the code!

Github project source address: github.com/FightingHao… Project presentation address: fightinghao. Making. IO/codingDream…

There are many deficiencies in the code, please review..

What are the Three. Js

With the rapid development of front-end in recent years, webpage performance is becoming more and more powerful. Browsers provide WebGL (Web Graphics Processing library) interface, which can be used to draw 3D graphics by calling corresponding API. Three.js is another layer of encapsulation on top of this basic interface. Three. Js is the most popular WEBPAGE 3D rendering JS engine.

How to use three.js

Preparation stage

  1. Add canvas element to page
<! Output 3D graphics as a three.js renderer --> <canvas id="webglcanvas"></canvas>
Copy the code
  1. Introduce the three.js library file
  • Local introduction
<! -- three.js library --> <script SRC ="./libs/three.min.js"></script>
Copy the code
  • CDN remote import
  <script src='http://cdnjs.cloudflare.com/ajax/libs/three.js/r70/three.min.js'></script>
Copy the code
  1. Variables used in the project
letCanvas, // Canvas tags stats, // performance detector camera, // camera scene, // renderer group, // Object group mouseX = 0, // mouse horizontal position mouseY = 0, // windowHalfX = window.innerWidth / 2, // windowHalfY = window.innerheight / 2; // Half the size of the viewportCopy the code

Creating scene materials

In order for three.js to display, you need three things: the scene, the camera, and the renderer

  1. The scene can be understood as the stage. Because to draw the 3D effect, you have to have a stage to demonstrate the effect

    Create scene API:THREE.Scene()
Scene = new three.scene () // Create sceneCopy the code
  1. Now that we have the scene, we need the camera to capture the material, so the second step is to create a camera.

    Create camera API:THREE.PerspectiveCamera(fov, aspect, near, far)
    • Fov viewing Angle, which can be understood as the field of vision, is the range of the scene seen on the display, in degrees.
    • Aspect is width/height, usually set to the aspect ratio of the Canvas element.
    • The distance is near
    • Far Indicates the remote distance
    • Only when the distance from the camera is greater than near value, less than FAR value, and within the camera’s viewing Angle, can it be projected by the camera.
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 2000) camera.position.z = 500 // Camera distanceCopy the code
  1. The scene and camera are available, that is, the material can be shot, but the material needs to go through some photoshop, beauty and so on to become beautiful. That’s where the renderer comes in.

    Create renderer API:THREE.WebGLRenderer({})
renderer = new THREE.WebGLRenderer({
    canvas: canvas,
    antialias: true, / /true/falseIf anti-aliasing is enabled, /* alpha:false, / /true/falseSpecifies whether background color transparency can be set. Precision:'highp', // highp/mediump/lowp indicates the precision selection, premultipliedAlpha:false, / /true/falseMaxLights: 3, // Maximum number of lights, stencil:false             // false/trueIndicates whether to use template fonts or patterns */})Copy the code

Renderer. setSize(window.innerWidth, window.innerheight) parameters are width and height, respectively

Creating 3D graphics

We have used the camera to shoot the material in the scene, but these elements are only 2D after all, now we want to change the material from 2D to 3D, at this time, we need to use a 3D graph as the carrier of 2D material. To put it in a foodie’s sense, it’s the chicken roll, the chicken roll, the chicken roll, the chicken roll, the chicken roll, the chicken roll, the chicken roll, the chicken roll becomes a 3D chicken roll, right? emmm… Awkward explanation. API:

  • The graphical shapesTHREE.SphereGeometry(radius, widthSegments, heightSegments, phiStart, phiLength, thetaStart, thetaLength)
    • Radius: indicates the radius of a sphere
    • WidthSegments, heightSegments: Number of horizontal and vertical segments. WidthSegments has a minimum value of 3 and a default value of 8. The minimum value of heightSegments is 2 and the default value is 6.
    • PhiStart: the starting Angle in the horizontal direction. The default is 0
    • PhiLenght: The degree of arc covered by the surface of a sphere horizontally, math.pi * 2 by default
    • ThetaStart: The starting Angle in the vertical direction. Default: 0
    • ThetaLength: The vertical direction is the radian covered by the surface of the sphere. The default is math.pi
  • Graphic materialTHREE.MeshBasicMaterial({})

    There are many kinds of graphic materials, online checked the information, think this summary is good, we can have a lookBlog.csdn.net/qq_30100043…
  • Graphical formTHREE.Mesh(geometry, material)
    • Geometry Of objects
    • Material Object material
letGeometry = new THREE.SphereGeometry(200, 20, 20) // ShapeletMaterial = new THREE.MeshBasicMaterial({map: texture}) // textureletMesh = new THREE.Mesh(Geometry, materialCopy the code
  • Loading graphicsnew THREE.TextureLoader().load(img, callback)

    Load the above graphics
loader.load('./img/land_ocean_ice_cloud_2048.jpg'.function (texture) {
    letGeometry = new THREE.SphereGeometry(200, 20, 20) // ShapeletMaterial = new THREE.MeshBasicMaterial({map: texture}) // textureletMesh = new THREE. (geometry, material)})Copy the code

Create a portfolio

Now that we have 3D graphics, the next step is to combine these graphics together into various 3D interfaces to create composition API: three.Group ()

// Create a group group = new three.group () scene.add(group) // Add the group to the scene renderCopy the code

Add the created 3D graphics to the composition

API: group. The add (mesh)

  • Mesh 3 d objects

movement

The 3D graphics have been rendered in the scene, now it’s time to get them moving!

function animateRequestAnimationFrame (animate) render()function render() {// Update the performance monitor stats.update(); X += (mousex-camera.position. x) * 0.05 camera.position.y += (mousex-camera.position. y) * 0.05 // The Angle of the shot, Camera. LookAt (scene.position) // Earth rotation speed group.rotation. Y -= 0.005Copy the code

We’re almost done with the 3D rotation of the Earth

What is the stats. Js

Having said three. js, let’s talk about stats.js. Stats. js is an auxiliary library developed by three. js to test the performance of WebGL code by detecting the number of frames when an animation is running

Stats. Use js

Preparation stage

Similar to three.js, stats.js requires the introduction of a framework library and a div to render the performance test interface

<! -- Used to display and count graph performance --> <div id="stats-output"></div> <! Stats.js library --> <script SRC ="./libs/stats.min.js"></script>
Copy the code

Begin to use

First, you need to initialize stats

// initialize stats = initStats();function initStats() { stats = new Stats(); // Set stats. SetMode (0); / / 0: FPS, 1: ms / / statistics show that in the upper left corner stats. The domElement accordingly. Style. The position ='absolute';
  stats.domElement.style.left = '10px';
  stats.domElement.style.top = '10px'; // Add the statistics object to the corresponding <div> element document.getelementById ("stats-output").appendChild(stats.domElement);
  return stats;
}
Copy the code

The stats detector API needs to be updated in real time when the scene changes, i.e. 3D motion: stats.update(); Used to dynamically update the detection situation when the earth rotates

// Earth rotation logic functionfunction render() {// Update the performance monitor stats.update(); X += (mousex-camera.position. x) * 0.05 camera.position.y += (mousex-camera.position. y) * 0.05 // The Angle of the shot, Camera. LookAt (scene.position) // Earth rotation speed group.rotation. Y -= 0.005 // Renderer.render (scene, camera)}Copy the code

Stats.setmode (0); // 0: FPS, 1: ms parameter 0 displays FPS


The final optimization

1. The earth Angle can be controlled through the mouse

/ / bind mouse event document. AddEventListener ('mousemove', onDocumentMouseMove, false) // Monitor the direction of mouse movement to determine the northern and southern hemispheres of the earthfunction onDocumentMouseMove(ev) {
  ev = ev || event
  mouseX = ev.clientX - windowHalfX
  mouseY = ev.clientY - windowHalfY
}
Copy the code

2. The response type

Can automatically change the size of rendered graphics according to the window size

// 窗口大小改变监听
window.addEventListener('resize', onWindowResize, false) // Monitor the window size to change the size of the earth according to the window size, similar to responsivenessfunction onWindowResize() {
  windowHalfX = window.innerWidth / 2
  windowHalfY = window.innerHeight / 2
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()
  renderer.setSize(window.innerWidth, window.innerHeight)
}
Copy the code

Ok, now 3D Earth is almost complete ~ complete code

<! DOCTYPE html> <html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge"> < span style> < span style> overflow: hidden; } </style> </head> <body> <! -- Used to display and count graph performance --> <div id="stats-output"></div> <! Output 3D graphics as a three.js renderer --> <canvas id="webglcanvas"></canvas> <! -- webGL library --> <script SRC ="./libs/three.min.js"></script>
  <script src="./libs/stats.min.js"></script>
  <script>
    letCanvas, // Canvas tag drawing API stats, // performance detector camera, // camera scene, // renderer group, // Object group mouseX = 0, // windowHalfX = window.innerWidth / 2, // windowHalfY = window.innerheight / 2; // windowHalfY = window.innerheight / 2; Init () // Builds earth animate() // makes the earth rotatefunction initCanvas = document.getelementById () {canvas = document.getelementById ()'webglcanvas'// stats initializes stats = initStats(); PerspectiveCamera(50, window. InnerWidth/window. InnerHeight, 1, PerspectiveCamera(50, window. 2000) camera.position.z = 500 // Camera far // scene = new three.scene () // Create a group group = new three.group () Scene.add (group) // Add the combination to the scene render // Earth math shape maplet loader = new THREE.TextureLoader()
      loader.load('./img/land_ocean_ice_cloud_2048.jpg'.function (texture) {
        // console.log(texture)
        letGeometry = new THREE.SphereGeometry(200, 20, 20) // ShapeletMaterial = new THREE.MeshBasicMaterial({map: texture}) // textureletRenderer = new THREE.WebGLRenderer({canvas: canvas, antialias:true, / /true/falseIf anti-aliasing is enabled, /* alpha:false, / /true/falseSpecifies whether background color transparency can be set. Precision:'highp', // highp/mediump/lowp indicates the precision selection, premultipliedAlpha:false, / /true/falseMaxLights: 3, // Maximum number of lights, stencil:false             // false/trueRenderer.setsize (window.innerWidth, Window. The innerHeight) / / bind mouse event document. AddEventListener ('mousemove', onDocumentMouseMove, false// Monitor window.adDeventListener ()'resize', onWindowResize, false} // Monitor the direction of mouse movement to determine the north and south hemispheres of the earthfunctiononDocumentMouseMove(ev) { ev = ev || event mouseX = ev.clientX - windowHalfX mouseY = ev.clientY - windowHalfY } // Monitor the window size, so as to change the size of the earth according to the window size, similar to responsivenessfunction onWindowResize() {
      windowHalfX = window.innerWidth / 2
      windowHalfY = window.innerHeight / 2
      camera.aspect = window.innerWidth / window.innerHeight
      camera.updateProjectionMatrix()
      renderer.setSize(window.innerWidth, window.innerHeight)
    }

    function animateRequestAnimationFrame (animate) render()function render() {// Update the performance monitor stats.update(); X += (mousex-camera.position. x) * 0.05 camera.position.y += (mousex-camera.position. y) * 0.05 // The Angle of the shot, Camera. LookAt (scene.position) // Earth rotation speed group.rotation. Y -= 0.005 // Renderer.render (scene, camera)}function initStats() { stats = new Stats(); // Set stats. SetMode (0); / / 0: FPS, 1: ms / / statistics show that in the upper left corner stats. The domElement accordingly. Style. The position ='absolute';
      stats.domElement.style.left = '10px';
      stats.domElement.style.top = '10px'; // Add the statistics object to the corresponding <div> element document.getelementById ("stats-output").appendChild(stats.domElement);
      returnstats; } // Ecchat data visualization // Flat world is wrong, CSS Perspective :1000px transform-style:perserve-3d // Camera Scene render Light -> canvas </script> </body> </html>Copy the code

Image materials and JS library can be downloaded on github: github.com/FightingHao…

This is my first post on the Nuggets. I hope you can give me a thumbs up