function init() { const container = document.getElementById('globe') const canvas = container.getElementsByTagName('canvas')[0] const width = 1000 const height = 800 const globeRadius = 200 const globeSegments = 64 const globeWidth = 4098 / 2 const globeHeight = 1968 / 2 const traceSteps = 10; const groups = { globe: null, globePoints: null, tracePoints: null, traceLines: null, } let data, scene, renderer, globe const camera = { object: null, orbitControls: null, angles: { current: { azimuthal: null, polar: null, }, target: { azimuthal: null, polar: null, }, }, transition: { current: 0, target: 30, }, } function setup() { scene = new THREE.Scene() camera.object = new THREE.PerspectiveCamera(45, width / height, 1, 4000) camera.object.position.z = -400 renderer = new THREE.WebGLRenderer({ canvas: canvas, antialias: true, opacity: 1, }) renderer.setSize(width, height) setupGlobe() setupOrbitControls() render() } setup() function setupGlobe() { const canvasSize = 128 const textureCanvas = document.createElement('canvas') textureCanvas.width = canvasSize textureCanvas.height = canvasSize const canvasContext = textureCanvas.getContext('2d') canvasContext.rect(0, 0, canvasSize, canvasSize) const texture = new THREE.Texture(textureCanvas) const geometry = new THREE.SphereGeometry( globeRadius, globeSegments, globeSegments ) const material = new THREE.MeshBasicMaterial({ map: texture, transparent: true, opacity: 0.5, }) globe = new THREE.Mesh(geometry, material) groups.globe = globe groups.globe.name = 'Globe' scene.add(groups.globe) addPoints() } function addPoints() { const mergedGeometry = new THREE.Geometry() const pingGeometry = new THREE.SphereGeometry(0.5, 5, 5) const material = new THREE.MeshBasicMaterial({ color: '#626177', }) for (let point of pointdata.points) { const pos = convertFlatCoordsToSphereCoords(point.x, point.y) if (pos.x && pos.y && pos.z) { pingGeometry.translate(pos.x, pos.y, pos.z) mergedGeometry.merge(pingGeometry) pingGeometry.translate(-pos.x, -pos.y, -pos.z) } } const total = new THREE.Mesh(mergedGeometry, material) groups.globePoints = total groups.globePoints.name = 'Globe Points' scene.add(groups.globePoints) } function addTracePoints(tracepoints) { console.log(tracepoints); const mergedGeometry = new THREE.Geometry() const pingGeometry = new THREE.SphereGeometry(1.9, 5, 5) const material = new THREE.MeshBasicMaterial({ color: '#FF0000', }) for (let point of tracepoints.points) { const pos = convertLatLngToSphereCoords(point.x, point.y) if (pos.x && pos.y && pos.z) { pingGeometry.translate(pos.x, pos.y, pos.z) mergedGeometry.merge(pingGeometry) pingGeometry.translate(-pos.x, -pos.y, -pos.z) } } const total = new THREE.Mesh(mergedGeometry, material) groups.tracePoints = total groups.tracePoints.name = 'Trace Points' scene.add(groups.tracePoints) groups.tracePoints.rotation.y = groups.globePoints.rotation.y - 0.05 //drawTraceLines(tracepoints); } /* function calculateLine(a, b) { var line = []; if (a < b) { var step = (a - b) / (traceSteps - 1); } else { var step = (b - a) / (traceSteps - 1); } var k; for (k = 0; k < traceSteps ; k++) { line.push(a + (step * k)); } return line; } function drawTraceLines(tracepoints) { const mergedGeometry = new THREE.Geometry() const pingGeometry = new THREE.SphereGeometry(1.9, 5, 5) const material = new THREE.MeshBasicMaterial({ color: '#FF4c4c', }) var i; for (i = 0; i < tracepoints.points.length; i++) { if (typeof tracepoints.points[i+1] === 'undefined') { break; } var x1 = tracepoints.points[i].x; var x2 = tracepoints.points[i+1].x; xarray = calculateLine(x1, x2); var y1 = tracepoints.points[i].y; var y2 = tracepoints.points[i+1].y; yarray = calculateLine(y1, y2); var j; for (j = 0; j < xarray.length; j++) { const pos = convertLatLngToSphereCoords(xarray[j], yarray[j]) if (pos.x && pos.y && pos.z) { pingGeometry.translate(pos.x, pos.y, pos.z) mergedGeometry.merge(pingGeometry) pingGeometry.translate(-pos.x, -pos.y, -pos.z) } } } const total = new THREE.Mesh(mergedGeometry, material) groups.traceLines = total groups.traceLines.name = 'Trace Lines' scene.add(groups.traceLines) groups.traceLines.rotation.y = groups.globePoints.rotation.y - 0.05 } */ init.addTracePoints = addTracePoints; function convertLatLngToSphereCoords(latitude, longitude) { const phi = (latitude * Math.PI) / 180 const theta = ((longitude - 180) * Math.PI) / 180 const x = -(globeRadius + -1) * Math.cos(phi) * Math.cos(theta) const y = (globeRadius + -1) * Math.sin(phi) const z = (globeRadius + -1) * Math.cos(phi) * Math.sin(theta) return new THREE.Vector3(x, y, z) } function convertFlatCoordsToSphereCoords(x, y) { let latitude = ((x - globeWidth) / globeWidth) * -180 let longitude = ((y - globeHeight) / globeHeight) * -90 latitude = (latitude * Math.PI) / 180 //(latitude / 180) * Math.PI longitude = (longitude * Math.PI) / 180 //(longitude / 180) * Math.PI const radius = Math.cos(longitude) * globeRadius const targetX = Math.cos(latitude) * radius const targetY = Math.sin(longitude) * globeRadius const targetZ = Math.sin(latitude) * radius return { x: targetX, y: targetY, z: targetZ, } } function convertLatLngToFlatCoords(latitude, longitude) { const x = Math.round((longitude + 180) * (globeWidth / 360)) * 2 const y = Math.round((-1 * latitude + 90) * (globeHeight / 180)) * 2 return { x, y } } function getProjectedPosition( width, height, position, contentWidth, contentHeight ) { position = position.clone() var projected = position.project(camera.object) return { x: projected.x * width + width - contentWidth / 2, y: -(projected.y * height) + height - contentHeight - 10, // -10 for a small offset } } function returnCameraAngles(x, y) { let targetAzimuthalAngle = ((x - globeWidth) / globeWidth) * Math.PI targetAzimuthalAngle = targetAzimuthalAngle + Math.PI / 2 targetAzimuthalAngle += 0.3 let targetPolarAngle = (y / (globeHeight * 2)) * Math.PI targetPolarAngle += 0.1 // Add a small vertical offset return { azimuthal: targetAzimuthalAngle, polar: targetPolarAngle, } } function convertLatLngToSphereCoords(latitude, longitude) { const phi = (latitude * Math.PI) / 180 const theta = ((longitude - 180) * Math.PI) / 180 const x = -(globeRadius + -1) * Math.cos(phi) * Math.cos(theta) const y = (globeRadius + -1) * Math.sin(phi) const z = (globeRadius + -1) * Math.cos(phi) * Math.sin(theta) return new THREE.Vector3(x, y, z) } function easeInOutCubic(t) { return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1 } function getRandomNumberBetween(min, max) { return Math.floor(Math.random() * (max - min + 1) + min) } function setupOrbitControls() { camera.orbitControls = new THREE.OrbitControls(camera.object, canvas) camera.orbitControls.enableKeys = false camera.orbitControls.enablePan = false camera.orbitControls.enableZoom = false camera.orbitControls.enableDamping = false camera.orbitControls.enableRotate = false camera.object.position.z = -550 camera.orbitControls.update() } function render() { renderer.render(scene, camera.object) requestAnimationFrame(render) //animate() groups.globePoints.rotation.y += 0.01 if (groups.tracePoints !== null) { groups.tracePoints.rotation.y += 0.01 } /* if (groups.traceLines !== null) { groups.traceLines.rotation.y += 0.01 } */ } }