Wuyue Ant Financial Service · Data Experience technology team

Our journey is the sea of stars – the declaration of the Ari people

How to build Ali’s Star Sea with code? First of all, let’s imagine a scene happening at present. The stars are twinkling all over the sky, meteors are streaking across the sky from time to time, the earth is rotating on its own, and countless people are trading in different places thanks to the convenient services provided by Ali.

The effect is as follows:

embed: sky.mov

Structure decomposition

How to construct the above scenario is decomposed into the following structure:

The starry sky

First you have to have a piece of sky, a rectangle, with a black background.

We temporarily set width, height, and depth for the three-dimensional space. Corresponding to a piece of twinkling stars, first of all to generate a bunch of stars in the space, and then let the stars keep flashing, temporarily according to the linear difference change, there are bigger (three-dimensional space is brighter) there are smaller (strain dark) part of the key code is as follows:

var starts = [];
for (let i = 0; i < 10000; i++) {
  starts.push({
    x: Math.random() * width,
    y: Math.random() * height,
    z: Math.random() * depth,
    // Current progress 0-1, current size (1-t) * minSize + t * maxSize
    t: Math.random(),
    // Change direction
    direction: Math.random(), 
    // The change step is temporarily fixed as a constant, and each star can be different as needed
    step: 0.01./ / minimum
    minSize: 10./ / the biggest
    maxSize: 20 
  });
}
animate();
function animate () {
  requestAnimationFrame(animate);
  starts.forEach((item) = > {
    let { t, minSize, maxSize } = item;
    // Calculate the current size
    item.size = (1 - t) * minSize + t * maxSize;
    // Change the schedule
    if (t > 1) {
      // If it has already reached the maximum, it starts to decrease
      item.direction = - 1; 
    } else if (t < 0) {
      // Start to get bigger
      item.direction = 1; 
    }
    // Modify the schedule
    item.t += item.step * item.direction;
  });
  // Render according to the values above
  render();
}
Copy the code

So we’re done with the stars. But all over the sky, the stars twinkle, is to have a meteor, so it is beautiful. A meteor is a star with a quick line across the sky. So it can be as follows:

// Meteor processing logic
var falls = [];
for (let i = 0; i < 10; i++) {
  falls.push({
    // The starting point of the meteor
    start: {
      x: Math.random() * width,
      y: Math.random() * height,
      z: Math.random() * depth
    },
    // The end of the meteor
    end: {
      x: Math.random() * width,
      y: Math.random() * height,
      z: Math.random() * depth
    },
    // The current progress is 0-1 and the current position is calculated according to the quadratic Bezier curve
    t: Math.random(),
    step: 0.01
  });
}

function animate () {
  requestAnimationFrame(animate);
  starts.forEach((item) = > {
    let { t, start as p0, end as p2} = item;
    // Set a control point arbitrarily
    let p1 = {
      x: p0.x,
      y: (p0.y + p2.y) / 2.z: p2.z 
    };
    // Calculate the current position according to the quadratic Bezier curve
    //(1 - t) * (1 - t) * p0 + 2 * t * (1 - t ) * p1 + t * t * p2
    
    let tmp = {
      x: (1 - t) * (1 - t) * p0.x + 2 * t * (1 - t ) * p1.x + t * t * p2.x,
      y: (1 - t) * (1 - t) * p0.y + 2 * t * (1 - t ) * p1.y + t * t * p2.y,
      z: (1 - t) * (1 - t) * p0.z + 2 * t * (1 - t ) * p1.z + t * t * p2.z
    };
    item.t += item.step;
    item.tmp = tmp;
    // Change the schedule
    if (t > 1) {
      // If the maximum value is already 0
      item.t = 0; 
      // Reset the starting point
      item.start = {
        x: Math.random() * width,
        y: Math.random() * height,
        z: Math.random() * depth
      };
      item.end = {
        x: Math.random() * width,
        y: Math.random() * height,
        z: Math.random() * depth }; }});// Render according to the values above
  render();
}
Copy the code

Of course, the above is just for the sake of explanation, separate the effect of flicker and meteor, in fact, there is a coincidence of the two parts of the logic, add a flag bit in the star state is flicker or meteor, and then the two logic can be combined, see github code implementation section here is no longer verbose.

The earth

Now that we have the stars, we’re going to build the Earth. The earth is roughly divided into two parts, first create a sphere at the origin of three-dimensional space, then give the earth a layer of texture skin, is a plane map from -90 to 90, -180-180 plane map as follows:

Then comes the key point, the trading points on earth need to be highlighted, so give some highlighting to the corresponding latitude and longitude. The specific location code is as follows:

  // Change latitude and longitude to x,y plane coordinates
  lnglatToXY ({lng, lat}, width, height) {
    let x = (lng - (- 180.)) / 360 * width;
    let y = Math.abs((lat - 90) / 180) * height;
    return {
      x,y
    };
  }
Copy the code

The next step is to create textures, large background images, and a hot canvas to paint by position.

    // Render textures
    async function render () {
      // Global background image
      let worldBg = await util.loadImg(worldSrc);
      // Hot background image
      let hotBg = await util.loadImg(hotSrc);
      // Draw a big background
      ctx.drawImage(worldBg, 0.0, width, height);
      // Draw hot spots by latitude and longitude
      data.forEach((item) = > {
        let lng = item.lnglat[0];
        let lat = item.lnglat[1];
        let {x, y} = util.lnglatToXY({lng, lat}, width, height);
        ctx.drawImage(hotBg, x - size / 2, y - size / 2, size, size);
      });
      // Create a texture and map it directly onto the ball
      let texture = new THREE.Texture(canvas);
      texture.needsUpdate = true;
      return texture;
    }

Copy the code

Ok, so here we have the earth. I’m just going to rotate the earth around the Y-axis every frame

animate();
function animate () {
  requestAnimationFrame(animate);
  earth.rotation.y += 0.01;
  render();
}
Copy the code

Trade line

Ok rotation of the earth is also available, the following is to plot the earth’s trading lines. Again, there’s a transition from latitude and longitude to space coordinates. The specific principle is shown below.

  // R is the radius of the sphere
  lnglatToXYZ ({lng, lat}, r) {
    var phi = (90 - lat) * Math.PI / 180;
    var theta = - 1 * lng * Math.PI / 180;
    return {
      x: r * Math.sin(phi) * Math.cos(theta),
      y: r * Math.cos(phi),
      z: r * Math.sin(phi) * Math.sin(theta)
    };
  }

Copy the code

So it’s pretty clear that lines perpendicular to the earth are the same latitude and longitude, different radii. So you can use this formula to figure out p1, and p2 gives you a line. And then you add control points and directional variables just like the twinkling stars and you get a lot of line segments fluctuating. The key codes are as follows:

// Raw data
letlines = [ {lng, lat }, {lng, lat }, .... ] ;// Generate some control parameters
lines.forEach((item) = > {
  // Control point 0-1 is used to calculate the end point t * length of the line
  item.t = Math.random(); 
  // Change direction
  item.direction = Math.random() > 0.5 ? 1 : - 1;
  // The speed of change is temporarily the same
  item.step = 0.01;
  // The length of the line segment can be mapped to the actual data such as value
  item.length =  Math.random() * r;
});

animate();
function animate () {
  requestAnimationFrame(animate);
  lines.forEach((item) = > {
    let p1 = lnglatToXYZ(item.lng, item.lat, r);
    // The current endpoint is t
    let p2 = lnglatToXYZ(item.lng, item.lat, r + item.length * t);
    // draw a line according to p1 and p2
    if (item.t > 1) {
      item.direction = - 1; 
    } else if (item.t < 0) {
      item.direction = 1; 
    }
    item.t += item.direction * item.step;
  });
  render();
}
Copy the code

Ok above is twinkle star, the meteor that the horizon delimits, rotate earth, the trade line that breathes presses corresponding position combination is together, it is star sea. Of course you might look at this and say, “Well, the stars are there.” But where is the ocean? There is actually water on the surface of the earth.

Finally, the source code is attached for your reference. Specific effect is seen here at http://yiqihaiqilai.com, https://github.com/liuwuyue/earth, http://yiqihaiqilai.com?line (personal server, may convulsions, such as can’t see, Please download the source code to run, do not come to me)

Last but not least, there are many such scenes in our group. Welcome to join us. If you are interested, you can follow the column or send your resume to ‘Wuyue. lwy####alibaba-inc.com’. Replace (‘####’, ‘@’). ~

Original address: github.com/ProtoTeam/b…