three.js realizes the simulated migration of sphere City

The overview is as follows:
1. Sphere Geometry realizes the Earth's rotation.
2. THREE.ImageUtils.loadTexture loads map mapping materials;
3. THREE.Math.degToRad, Math.sin, Math.cos realize the transformation between the longitude and latitude of the map and the three coordinates x, y, z;
4, track marks are implemented according to the number of segments and the corresponding gdp values.

The results are as follows:

Preview address: three.js realizes the simulated migration of sphere City

Initialize scene, camera and renderer, set camera position, initialize light source, use Hemisphere Light as light source, set light source position as the center of scene, and add light source to scene.

// Initialization scenario
var scene = new THREE.Scene();
// Initialize the camera. The first parameter is the vertical visual field angle of the camera's visual cone, and the second parameter is the aspect ratio of the camera's visual cone.
// The third parameter is the near end of the camera visual cone, and the fourth parameter is the far end of the camera visual cone.
var camera = new THREE.PerspectiveCamera(20, dom.clientWidth / dom.clientHeight, 1, 100000);
// Set the camera position, and the corresponding parameters are expressed separately. x,y,z position
camera.position.set(0, 0, 200);
var renderer = new THREE.WebGLRenderer({
      alpha: true,
      antialias: true
});
// Set light
scene.add(new THREE.HemisphereLight('#ffffff', '#ffffff', 1));

Set the scene window size and initialize the controller. The window size is the same as the browser window size by default. Finally, the renderer is loaded into the dom.

// Set the window size. The first parameter is width and the second parameter is height.
renderer.setSize(dom.clientWidth, dom.clientHeight);
// Initialization Controller
var orbitcontrols = new THREE.OrbitControls(camera,renderer.domElement);
// Load the renderer to dom in
dom.appendChild(renderer.domElement);

Define the Earth and its material. The Earth is implemented by Sphere Geometry and imported by Image Utils.

// Define the Earth's Material
var earthTexture = THREE.ImageUtils.loadTexture(earthImg, {}, function () {
    renderer.render(scene, camera);
});
// Create the earth
earthBall = new THREE.Mesh(new THREE.SphereGeometry(earthBallSize, 50, 50), new THREE.MeshBasicMaterial({
    map: earthTexture
}));
scene.add(earthBall);

Conversion method between longitude and latitude coordinates of marking sites and three-dimensional x, y, z coordinates.

// Latitude and longitude conversion function, longitude Represents longitude. latitude Expressing soleness, radius Represents the radius of a sphere
var getPosition = function (longitude, latitude, radius) {
    // Convert longitude and latitude to rad coordinate
    var lg = THREE.Math.degToRad(longitude);
    var lt = THREE.Math.degToRad(latitude);
    var temp = radius * Math.cos(lt);
    // Obtain x,y,z coordinate
    var x = temp * Math.sin(lg);
    var y = radius * Math.sin(lt);
    var z = temp * Math.cos(lg);
    return {
        x: x,
        y: y,
        z: z
    }
}

Add a way to track between two cities.

// Adding Trajectory Function
var addLine = function (v0, v3) {
    var angle = (v0.angleTo(v3) * 180) / Math.PI;
    var aLen = angle * 0.5 * (1 - angle / (Math.PI * earthBallSize * parseInt(earthBallSize / 10)));
    var hLen = angle * angle * 1.2 * (1 - angle / (Math.PI * earthBallSize * parseInt(earthBallSize / 10)));
    var p0 = new THREE.Vector3(0, 0, 0);
    // normal vector
    var rayLine = new THREE.Ray(p0, getVCenter(v0.clone(), v3.clone()));
    // Vertex coordinates
    var vtop = rayLine.at(hLen / rayLine.at(1).distanceTo(p0));
    // Control point coordinates
    var v1 = getLenVcetor(v0.clone(), vtop, aLen);
    var v2 = getLenVcetor(v3.clone(), vtop, aLen);
    // Drawing Bessel curve
    var curve = new THREE.CubicBezierCurve3(v0, v1, v2, v3);
    var geometry = new THREE.Geometry();
    geometry.vertices = curve.getPoints(100);
    var line = new MeshLine();
    line.setGeometry(geometry);
    var material = new MeshLineMaterial({
        color: metapLineColor,
        lineWidth: 0.1,
        transparent: true,
        opacity: 1
    })
    return {
        curve: curve,
        lineMesh: new THREE.Mesh(line.geometry, material)
    }
}

The method of realizing the moving ball on the trajectory.

var animateDots = [];
// Line object set
var groupLines = new THREE.Group();
// line
marking.children.forEach(function (item) {
    var line = addLine(marking.children[0].position, item.position);
    groupLines.add(line.lineMesh);
    animateDots.push(line.curve.getPoints(metapNum));
})
scene.add(groupLines);
// A gliding ball on the line
var aGroup = new THREE.Group();
for (var i = 0; i < animateDots.length; i ++) {
    for (var j = 0; j < markingNum; j ++) {
        var aGeo = new THREE.SphereGeometry(slideBallSize, 10, 10);
        var aMaterial = new THREE.MeshBasicMaterial({
            color: slideBallColor,
            transparent: true,
            opacity: 1 - j * 0.02
        })
        var aMesh = new THREE.Mesh(aGeo, aMaterial);
        aGroup.add(aMesh);
    }
}
var vIndex = 0;
var firstBool = true;
function animationLine () {
    aGroup.children.forEach(function (elem, index) {
        var _index = parseInt(index / markingNum);
        var index2 = index - markingNum * _index;
        var _vIndex = 0;
        if (firstBool) {
            _vIndex = vIndex - index2 % markingNum >= 0 ? vIndex - index2 % markingNum : 0;
        } else {
            _vIndex = vIndex - index2 % markingNum >= 0 ? vIndex - index2 % markingNum : metapNum + vIndex - index2;
        }
        var v = animateDots[_index][_vIndex];
        elem.position.set(v.x, v.y, v.z);
    })
    vIndex ++;
    if (vIndex > metapNum) {
        vIndex = 0;
    }
    if (vIndex == metapNum && firstBool) {
        firstBool = false;
    }
    requestAnimationFrame(animationLine);
}
scene.add(aGroup);

The tag location is confirmed by the position value, and the animation is implemented by the request Animation Frame.

// Execution function
var render = function () {
    scene.rotation.y -= 0.01;
    renderer.render(scene, camera);
    orbitcontrols.update();
    requestAnimationFrame(render);
}

Tags: Javascript

Posted on Sun, 06 Oct 2019 05:38:04 -0700 by mcl