|
|
@ -0,0 +1,230 @@ |
|
|
|
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 groups = { |
|
|
|
globe: null, |
|
|
|
globePoints: null, |
|
|
|
tracePoints: 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) { |
|
|
|
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) |
|
|
|
// Reset ping item position.
|
|
|
|
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 |
|
|
|
} |
|
|
|
|
|
|
|
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) { |
|
|
|
// Convert latitude and longitude on the 90/180 degree axis.
|
|
|
|
let latitude = ((x - globeWidth) / globeWidth) * -180 |
|
|
|
let longitude = ((y - globeHeight) / globeHeight) * -90 |
|
|
|
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, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
function returnCameraAngles(x, y) { |
|
|
|
let targetAzimuthalAngle = ((x - globeWidth) / globeWidth) * Math.PI |
|
|
|
targetAzimuthalAngle = targetAzimuthalAngle + Math.PI / 2 |
|
|
|
let targetPolarAngle = (y / (globeHeight * 2)) * Math.PI |
|
|
|
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) |
|
|
|
groups.globePoints.rotation.y += 0.01 |
|
|
|
if (groups.tracePoints !== null) { |
|
|
|
groups.tracePoints.rotation.y += 0.01 |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|