旅行(travel)
程序员文章站
2022-04-03 22:48:11
...
示例
HTML
#container
CSS
html
background: black
height: 100%
overflow: hidden
body
height: 100%
margin: 0
padding: 0
position: relative
z-index: 10
canvas
animation: in 2s cubic-bezier(0.23, 1, 0.32, 1) 0.25s backwards
background: transparent
position: absolute
@keyframes in
from
opacity: 0
JS
'use strict';
var Earth = function(el, data) {
let camera, scene, renderer, composer, w, h;
let lines = [],
mouse = {
x: 0,
y: 0
},
mouseOnDown = {
x: 0,
y: 0
},
points = [],
rotation = {
x: Math.PI * 1.9,
y: Math.PI / 6
},
target = {
x: Math.PI * 1.9,
y: Math.PI / 6
},
targetOnDown = {
x: 0,
y: 0
};
const center = new THREE.Vector3(0, 0, 0),
clock = new THREE.Clock(),
distance = 350,
PI_HALF = Math.PI / 2,
pointRadius = 152,
radius = 150;
// Shaders
// https://github.com/dataarts/webgl-globe
const shaders = {
'atmosphere': {
uniforms: {},
vertexShader: [
'varying vec3 vNormal;',
'void main() {',
'vNormal = normalize( normalMatrix * normal );',
'gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );',
'}'
].join('\n'),
fragmentShader: [
'varying vec3 vNormal;',
'void main() {',
'float intensity = pow( 0.8 - dot( vNormal, vec3( 0, 0, 1.0 ) ), 3.0 );',
'gl_FragColor = vec4( 0.3, 0.4, 0.6, 0.05 ) * intensity;',
'}'
].join('\n')
}
};
// -------------------------------------
// Init
// -------------------------------------
function init() {
w = window.innerWidth;
h = window.innerHeight;
camera = new THREE.PerspectiveCamera(distance / 5, w / h, 1, distance * 2);
scene = new THREE.Scene();
scene.add(camera);
// Stars
// http://gielberkers.com/evenly-distribute-particles-shape-sphere-threejs/
let starGeometry = new THREE.Geometry();
for (let i = 0; i < 1000; i++) {
let x = -1 + Math.random() * 2;
let y = -1 + Math.random() * 2;
let z = -1 + Math.random() * 2;
const d = 1 / Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2));
x *= d;
y *= d;
z *= d;
const vertex = new THREE.Vector3(
x * distance,
y * distance,
z * distance
);
starGeometry.vertices.push(vertex);
}
const stars = new THREE.Points(starGeometry, new THREE.PointsMaterial({
color: '#333333',
size: 3
}));
scene.add(stars);
// Light
let light = new THREE.PointLight('#ffffff', 0.5);
camera.add(light);
light.position.set(distance / 2, distance / 2, 0);
light.target = camera;
// Earth
THREE.ImageUtils.crossOrigin = ''
var earthLights = THREE.ImageUtils.loadTexture('//s3-us-west-2.amazonaws.com/s.cdpn.io/68727/earth-lights.jpg');
var earthBump = THREE.ImageUtils.loadTexture('//s3-us-west-2.amazonaws.com/s.cdpn.io/68727/earth-bump.jpg');
earthLights.minFilter = THREE.LinearFilter;
earthBump.minFilter = THREE.LinearFilter;
var earthGeometry = new THREE.SphereGeometry(radius, 50, 30);
var earthMaterial = new THREE.MeshPhongMaterial({
bumpMap: earthBump,
bumpScale: 4,
emissiveMap: earthLights,
emissive: '#333333',
map: earthLights,
specular: '#010101'
});
const earth = new THREE.Mesh(earthGeometry, earthMaterial);
scene.add(earth);
// Atmosphere
const atmosphereMaterial = new THREE.ShaderMaterial({
vertexShader: shaders['atmosphere'].vertexShader,
fragmentShader: shaders['atmosphere'].fragmentShader,
side: THREE.BackSide,
blending: THREE.AdditiveBlending,
transparent: true
});
const atmosphere = new THREE.Mesh(earthGeometry, atmosphereMaterial);
atmosphere.scale.set(1.3, 1.3, 1.3);
scene.add(atmosphere);
// Points
for (let i = 0; i < data.length; i++) {
points.push(new point(data[i].lat, data[i].long, data[i].r, i));
let newLine = drawCurve(points[0].position, points[i].position);
new TWEEN.Tween(newLine)
.to({
currentPoint: 200
}, 2000)
.delay(i * 350 + 1500)
.easing(TWEEN.Easing.Cubic.Out)
.onUpdate(function() {
newLine.geometry.setDrawRange(0, newLine.currentPoint);
})
.start();
}
// Renderer
renderer = new THREE.WebGLRenderer({
alpha: true,
antialias: true
});
renderer.autoClear = false;
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(w, h);
// Composer
composer = new THREE.EffectComposer(renderer);
composer.addPass(new THREE.RenderPass(scene, camera));
const effectBloom = new THREE.BloomPass(1.75);
const effectFilm = new THREE.FilmPass(0.25, 0.5, 2048, 0);
const effectShift = new THREE.ShaderPass(THREE.RGBShiftShader);
effectShift.uniforms['amount'].value = 0.001;
effectShift.renderToScreen = true;
composer.addPass(effectBloom);
composer.addPass(effectFilm);
composer.addPass(effectShift);
// Events
el.addEventListener('mousedown', onMouseDown, false);
window.addEventListener('resize', onWindowResize, false);
// DOM
el.appendChild(renderer.domElement);
}
// -------------------------------------
// Lat + Long to Vector
// -------------------------------------
function latLongToVector3(lat, lon, r) {
// http://www.smartjava.org/content/render-open-data-3d-world-globe-threejs
const phi = lat * Math.PI / 180;
const theta = (lon - 180) * Math.PI / 180;
const x = -r * Math.cos(phi) * Math.cos(theta);
const y = r * Math.sin(phi);
const z = r * Math.cos(phi) * Math.sin(theta);
return new THREE.Vector3(x, y, z);
}
// -------------------------------------
// Interactivity
// -------------------------------------
function onMouseDown(event) {
event.preventDefault();
el.addEventListener('mouseup', onMouseUp, false);
el.addEventListener('mousemove', onMouseMove, false);
el.addEventListener('mouseout', onMouseOut, false);
mouseOnDown.x = -event.clientX;
mouseOnDown.y = event.clientY;
targetOnDown.x = target.x;
targetOnDown.y = target.y;
el.style.cursor = 'move';
}
function onMouseMove(event) {
mouse.x = -event.clientX;
mouse.y = event.clientY;
target.x = targetOnDown.x + (mouse.x - mouseOnDown.x) * 0.005;
target.y = targetOnDown.y + (mouse.y - mouseOnDown.y) * 0.005;
target.y = target.y > PI_HALF ? PI_HALF : target.y;
target.y = target.y < -PI_HALF ? -PI_HALF : target.y;
}
function onMouseUp(event) {
el.removeEventListener('mousemove', onMouseMove, false);
el.removeEventListener('mouseup', onMouseUp, false);
el.removeEventListener('mouseout', onMouseOut, false);
el.style.cursor = 'auto';
}
function onMouseOut(event) {
el.removeEventListener('mouseup', onMouseUp, false);
el.removeEventListener('mouseout', onMouseOut, false);
}
function onWindowResize(event) {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
// -------------------------------------
// Animate
// -------------------------------------
function animate(time) {
render();
TWEEN.update(time);
requestAnimationFrame(animate);
}
// -------------------------------------
// Render
// -------------------------------------
function render() {
if (el.style.cursor != 'move') target.x += 0.00075;
rotation.x += (target.x - rotation.x) * 0.1;
rotation.y += (target.y - rotation.y) * 0.1;
camera.position.x = distance * Math.sin(rotation.x) * Math.cos(rotation.y);
camera.position.y = distance * Math.sin(rotation.y);
camera.position.z = distance * Math.cos(rotation.x) * Math.cos(rotation.y);
camera.lookAt(center);
renderer.render(scene, camera);
composer.render();
}
// -------------------------------------
// Point
// -------------------------------------
function point(lat, lng, r, i) {
const position = latLongToVector3(lat, lng, radius);
const pointGeometry = new THREE.SphereGeometry(r, 32, 32);
const pointMaterial = new THREE.MeshBasicMaterial({
color: '#ff3600',
opacity: 0.6,
side: THREE.DoubleSide,
transparent: true
});
let point = new THREE.Mesh(pointGeometry, pointMaterial);
point.position.set(position.x, position.y, position.z);
point.scale.set(0.01, 0.01, 0.01);
point.lookAt(center);
scene.add(point);
new TWEEN.Tween(point.scale)
.to({
x: 1,
y: 1,
z: 1
}, 1000)
.delay(i * 350 + 1500)
.easing(TWEEN.Easing.Cubic.Out)
.start();
const pointRingGeometry = new THREE.RingGeometry(r + 0.5, r + 1.5, 32);
const pointRingMaterial = new THREE.MeshBasicMaterial({
color: '#ff3600',
opacity: 0.2,
side: THREE.DoubleSide,
transparent: true
});
let pointRing = new THREE.Mesh(pointRingGeometry, pointRingMaterial);
pointRing.position.set(position.x, position.y, position.z);
pointRing.scale.set(0.01, 0.01, 0.01);
pointRing.lookAt(center);
scene.add(pointRing);
new TWEEN.Tween(pointRing.scale)
.to({
x: 1,
y: 1,
z: 1
}, 1500)
.delay(i * 350 + 1500)
.easing(TWEEN.Easing.Cubic.Out)
.start();
return point;
}
// http://armsglobe.chromeexperiments.com/js/visualize_lines.js
function drawCurve(a, b, i) {
const distance = a.clone().sub(b).length();
let mid = a.clone().lerp(b, 0.5);
const midLength = mid.length();
mid.normalize();
mid.multiplyScalar(midLength + distance * 0.25);
let normal = (new THREE.Vector3()).subVectors(a, b);
normal.normalize();
const midStart = mid.clone().add(normal.clone().multiplyScalar(distance * 0.25));
const midEnd = mid.clone().add(normal.clone().multiplyScalar(distance * -0.25));
let splineCurveA = new THREE.CubicBezierCurve3(a, a, midStart, mid);
let splineCurveB = new THREE.CubicBezierCurve3(mid, midEnd, b, b);
let points = splineCurveA.getPoints(100);
points = points.splice(0, points.length - 1);
points = points.concat(splineCurveB.getPoints(100));
points.push(center);
let lineGeometry = new THREE.BufferGeometry();
let positions = new Float32Array(points.length * 3);
for (let ii = 0; ii < points.length; ii++) {
positions[ii * 3 + 0] = points[ii].x;
positions[ii * 3 + 1] = points[ii].y;
positions[ii * 3 + 2] = points[ii].z;
}
lineGeometry.addAttribute('position', new THREE.BufferAttribute(positions, 3));
lineGeometry.setDrawRange(0, 0);
var lineMaterial = new THREE.LineBasicMaterial({
color: new THREE.Color(0xffffff),
linewidth: 3,
opacity: 0.25,
transparent: true
});
let line = new THREE.Line(lineGeometry, lineMaterial);
line.currentPoint = 0;
scene.add(line);
return line;
}
// -------------------------------------
// Start
// -------------------------------------
init();
animate();
this.animate = animate;
return this;
};
var data = [{
long: -81.173,
lat: 28.4,
r: 8
}, {
long: -81.1,
lat: 32.084,
r: 3
}, {
long: -74.006,
lat: 40.713,
r: 5
}, {
long: -0.128,
lat: 51.507,
r: 2
}, {
long: -87.63,
lat: 41.878,
r: 2
}, {
long: -122.419,
lat: 37.775,
r: 2
}, {
long: -90.199,
lat: 38.627,
r: 3
}, {
long: -77.042,
lat: -12.046,
r: 2
}, {
long: -77.345,
lat: 25.06,
r: 5
}, {
long: -117.783,
lat: 33.542,
r: 2
}, {
long: -149.9,
lat: 61.218,
r: 2
}, {
long: -123.121,
lat: 49.283,
r: 2
}, {
long: 25.462,
lat: 36.393,
r: 2
}, {
long: -122.676,
lat: 45.523,
r: 3
}, {
long: -95.401,
lat: 29.817,
r: 2
}]
var container = document.getElementById('container');
var planet = new Earth(container, data);
更多有趣示例 尽在 小红砖社区https://xhz.bos.xyz
上一篇: whatsApp指纹解锁
下一篇: 飞溅加载器(splash loader)