Hey. I am a student at Maastricht University, and for my Digital Entrepreneurship course, I wanted to build an interactive globe in JS. On www.stripe.com, I found this outstanding globe, and there was even a blog post by Nick Jones on how to make it happen ( https://stripe.com/blog/globe). However, my JS skills are very decent, so I hope you can help me out a bit. Here you see the code which is not complete from the blog post by Nick Jones.
const DOT_COUNT= 60000;
const dotGeometry = new THREE.CircleGeometry(2,5);
const positions = [];
const rndId = [];
const countryIds = [];
const vector = new THREE.Vector3();
for (let i = DOT_COUNT; i >= 0; i--) {
const phi = Math.acos(-1 + (2*i)/DOT_COUNT);
const theta = Math.sqrt(DOT_COUNT * Math.PI)*phi;
vector.setFromSphericalCoords(600,phi,theta);
dotGeometry.lookAt(vector);
dotGeometry.translate(vector.x,vector.y,vector.z);
}
const COUNTRY_MAPPING = [
[0,'#99cc99','at'],
[1,'#993333','au'],
[2,'#cccc00','be'],
];
new ImageLoader().load('map.png', (mapImage) => {
const imageData = getImageData(mapImage);
});
dotGeometry.computeBoundingSphere();
const uv = pointToUV(dotGeometry.boundingSphere.center, this.position);
const sample = sampleImage(uv, imageData);
if(!sample[3]) return;
for (let i=0; i < dot dotGeometry.faces.length;i++) {
const face = dotGeomtry.faces[i];
positions.push(
dotGeomtry.vertices[face.a].x,
dotGemotry.vertices[face.a].y,
dotGeometry.vertcies[face.a].z,
dotGeomtry.vertices[face.b].x,
dotGemotry.vertices[face.b].y,
dotGeometry.vertcies[face.b].z,
dotGeomtry.vertices[face.c].x,
dotGemotry.vertices[face.c].y,
dotGeometry.vertcies[face.c].z,
);
const [countryId] = getCountryId(sample);
countzryIds.push(countryId, countryId, countryId);
}
function getCountryId([r, g, b, ]) {
const hex = [r, g, b]
.map((color) => color.toString(16).padStart(2, '0'))
.join('');
const countryId = COUNTRY_MAPPING.find(([, id]) => id === hex);
return countryId;
}
constructor(start, end, radius) {
super();
// Convert latitude/longitude to XYZ on the globe
const start = toXYZ(start[0], start[1], radius);
const endXYZ = toXYZ(end[0], end[1], radius);
// D3 interpolates along the great arc that passes
// through both the start and end point
const d3Interpolate = geoInterpolate(
[start[1], start[0]],
[end[1], end[0]],
);
const control1 = d3Interpolate(0.25);
const control2 = d3Interpolate(0.75);
// Set the arc height to half the distance between points
const arcHeight = start.distanceTo(end) * 0.5 + radius;
const controlXYZ1 = toXYZ(control1[1], control1[0], arcHeight);
const controlXYZ2 = toXYZ(control2[1], control2[0], arcHeight);
// CubicBezier allows for curves which travel halfway
// around the globe without penetrating the sphere
const curve = new CubicBezierCurve3(start, controlXYZ1, controlXYZ2, end);
// Arcs are curved tubes with 0.5px radius and 8 sides
// Each curve is broken into 44 segments
this.geometry = new THREE.TubeBufferGeometry(curve, 44, 0.5, 8);
this.material = new THREE.ShaderMaterial({
// A custom fragment shader animates arc colors
});
this.mesh = new THREE.Mesh(this.geometry, this.material);
this.add(this.mesh);
// Set the draw range to show only the first vertex
this.geometry.setDrawRange(0, 1);
this.drawAnimatedLine();
}
drawAnimatedLine = () => {
let drawRangeCount = this.geometry.drawRange.count;
const timeElapsed = performance.now() - this.startTime;
// Animate the curve for 2.5 seconds
const progress = timeElapsed / 2500;
// Arcs are made up of roughly 3000 vertices
drawRangeCount = progress * 3000;
if (progress < 0.999) {
// Update the draw range to reveal the curve
this.geometry.setDrawRange(0, drawRangeCount);
requestAnimationFrame(this.drawAnimatedLine);
}
}
this.renderer = new WebGLRenderer({ antialias: false, alpha: true });
…
// Rotating the globe on scroll
import throttle from 'lodash/throttle';
const SCROLL_EPSILON = 0.0016;
const GLOBE_TRIGGER_TOP = window.innerHeight;
…
document.addEventListener('scroll', this.universalScrollHandler);
…
// Event handler: rotate the globe based on the current browser scroll position
universalScrollHandler = throttle(this.scrollHandler.bind(this), 16);
scrollHandler() {
// Turns off all other animation
this.isScrolling = true;
this.oldScrollTop = this.scrollTop;
this.scrollTop =
document.scrollingElement.scrollTop || document.body.scrollTop;
this.scrollDelta = this.oldScrollTop - this.scrollTop;
const rotationDelta = this.scrollDelta * SCROLL_EPSILON;
this.globeContainer.rotation.y += rotationDelta;
// Once the browser scrolls past the globe on the page
// stop all animations and move the globe off-screen
if (GLOBE_TRIGGER_TOP < this.scrollTop) {
this.globeOff = true;
this.globeEl.style.transform = 'translateX(100vw)';
} else {
this.globeOff = false;
this.globeEl.style.transform = 'translateX(0)';
}
}
you also use pastebin on the post. I haven't idea about your problem! i just noticed that code above