let tableData_global = []; // fetched date let flags; const doFetchCountries = () => { $.ajax({ url: "/items" }).done((data) => { if (data instanceof Array) tableData_global = data; else { tableData_global = []; tableData_global.push(data); } }); }; window.onload = () => { doFetchCountries(); setup(); }; // mappa const options = { lat: 0, lng: 0, zoom: 4, style: 'mapbox://styles/mapbox/traffic-night-v2', pitch: 50, } let WIDTH; let HEIGHT; const key = 'pk.eyJ1IjoicmljYXJkb2xhbmduZXIiLCJhIjoiY2pxano2enh2MG1qazN4bm5lajIzeDl3eiJ9.wK0MtuxLgJxDcGUksKMeKg'; let mappa; let myMap; let canvas; // three let scene; let camera; let renderer; var light; function setup_enables() { flags = [ { id: "birth_rate_per_1000", enabled: true, color: 0xff0000 }, { id: "cell_phones_per_100", enabled: true, color: 0x0ff000 }, { id: "children_per_woman", enabled: true, color: 0x00ff00 }, { id: "electricity_consumption_per_capita", enabled: true, color: 0x000ff0 }, { id: "gdp_per_capita", enabled: true, color: 0x0000ff }, { id: "gdp_per_capita_growth", enabled: true, color: 0xf0000f }, { id: "inflation_annual", enabled: true, color: 0xf000f0 }, { id: "internet_user_per_100", enabled: true, color: 0x00f00f }, { id: "life_expectancy", enabled: true, color: 0xf00f00 }, { id: "military_expenditure_percent_of_gdp", enabled: true, color: 0x0f00f0 }, ]; } function setup() { mappa = new Mappa('MapboxGL', key); myMap = mappa.tileMap(options); canvas = document.getElementById("mapa"); canvas.width = window.innerWidth; canvas.height = window.innerHeight; WIDTH = window.innerWidth; HEIGHT = window.innerHeight; camera = new THREE.PerspectiveCamera(75, WIDTH / HEIGHT, 0.1, 1000); camera.up = new THREE.Vector3(0, 0, 1); //camera.position.z = 300; scene = new THREE.Scene(); renderer = new THREE.WebGLRenderer({ alpha: true, canvas: canvas }); light = new THREE.PointLight(0xffffff, 1, 1000); light.position.set(-50, -50, 100); light.castShadow = true; light.shadow.mapSize.width = 512; light.shadow.mapSize.height = 512; light.shadow.camera.near = 0.5; light.shadow.camera.far = 1000; renderer.setSize(WIDTH, HEIGHT); document.body.appendChild(renderer.domElement); myMap.overlay(canvas); myMap.onChange(update); setup_enables(); update(); } function setup_objects() { scene.remove.apply(scene, scene.children); scene.add(light); for (let i = 0; i < tableData_global.length; i++) { let long = tableData_global[i]["gps_long"]; let lat = tableData_global[i]["gps_lat"]; let enabled = 0; for (let j = 0; j < flags.length; j++) { let flag = flags[j]; if (flag.enabled) { let value = tableData_global[i][flag.id]; // TODO: value let height = value / 10.0; let geometry = new THREE.BoxGeometry(1, 1, height); let material = new THREE.MeshBasicMaterial({ color: flag.color }); let cube = new THREE.Mesh(geometry, material); cube.castShadow = true; cube.receiveShadow = true; const pos = myMap.latLngToPixel(lat, long); const vector = new THREE.Vector3(); vector.set((pos.x / WIDTH) * 2 - 1, -(pos.y / HEIGHT) * 2 + 1, 0.5); vector.unproject(camera); const dir = vector.sub(camera.position).normalize(); const distance = -camera.position.z / dir.z; const newPos = camera.position.clone().add(dir.multiplyScalar(distance)); cube.position.set(newPos.x + enabled, newPos.y, newPos.z + height / 2); scene.add(cube); enabled++; } } } } function draw() { } function update() { setup_objects(); let position = myMap.pixelToLatLng(window.innerWidth / 2, window.innerHeight / 2); let look_at = new THREE.Vector3(position.x, position.y, 0); camera.position.set(look_at.x, look_at.y - 10, look_at.z + 30); camera.lookAt(look_at); renderer.render(scene, camera); }