|
<!doctype html> |
|
<html> |
|
<head> |
|
<meta charset='utf-8'> |
|
<script src='https://d3js.org/d3.v4.min.js'></script> |
|
<script src='https://cdnjs.cloudflare.com/ajax/libs/three.js/r83/three.min.js'></script> |
|
<style> |
|
#map-layer { |
|
position: absolute; |
|
left: 0; |
|
top: 0; |
|
z-index: 2; |
|
} |
|
#shade-layer { |
|
position: absolute; |
|
left: 0; |
|
top: 0; |
|
z-index: 1; |
|
} |
|
</style> |
|
</head> |
|
<body> |
|
<script> |
|
// Set parameters. |
|
const WIDTH = 512, HEIGHT = 512 |
|
const RADIUS = 120 |
|
const INITIAL_ROTATE = [0, 0] |
|
const SCALE = RADIUS |
|
const BACKGROUND_COLOR = 'white' |
|
const TO_RADIAN = Math.PI / 180 |
|
const TO_DEGREE = 180 / Math.PI |
|
const ROTATION_SCALE = 0.25 |
|
|
|
// create projection object. |
|
var projection = d3.geoOrthographic() |
|
.translate([WIDTH / 2, HEIGHT / 2]) |
|
.scale(SCALE) |
|
.clipAngle(90) |
|
.rotate(INITIAL_ROTATE) |
|
|
|
// Create map layers at multiple resolutions. |
|
var mapLayer = d3.select('body').append('canvas').attr('id', 'map-layer') |
|
.attr('width', WIDTH).attr('height', HEIGHT) |
|
var mapContext = mapLayer.node().getContext('2d') |
|
mapContext.strokeStyle = 'black' |
|
var mapPath = d3.geoPath().projection(projection).context(mapContext) |
|
var mapMarks = { |
|
type: 'FeatureCollection', |
|
features: [{ |
|
type: 'Feature', |
|
geometry: { |
|
type: 'LineString', |
|
coordinates: [ |
|
[-5, 0], |
|
[ 5, 0] |
|
] |
|
} |
|
}, { |
|
type: 'Feature', |
|
geometry: { |
|
type: 'LineString', |
|
coordinates: [ |
|
[0, -5], |
|
[0, 5] |
|
] |
|
} |
|
}] |
|
} |
|
function drawMapLayer() { |
|
mapContext.setTransform(1, 0, 0, 1, 0, 0) |
|
mapContext.clearRect(0, 0, WIDTH, HEIGHT) |
|
mapContext.beginPath() |
|
mapPath(mapMarks) |
|
mapContext.lineWidth = 2 |
|
mapContext.stroke() |
|
} |
|
drawMapLayer() |
|
|
|
// Handle drag event. |
|
var drag = d3.drag().on('drag', function() { |
|
// Skip spurious drag event. |
|
if (d3.event.dx === 0 && d3.event.dy === 0) return |
|
var r = projection.rotate() |
|
var dr = [d3.event.dx * ROTATION_SCALE, - d3.event.dy * ROTATION_SCALE] |
|
projection.rotate([r[0] + dr[0], r[1] + dr[1]]) |
|
drawMapLayer() |
|
|
|
// Rotate Three.js objects. |
|
sphereObject.rotation.x = - projection.rotate()[1] * TO_RADIAN |
|
sphereObject.rotation.y = projection.rotate()[0] * TO_RADIAN |
|
sphereObject.rotation.z = projection.rotate()[2] * TO_RADIAN |
|
drawShadeLayer() |
|
}) |
|
mapLayer.call(drag) |
|
|
|
// Create 3D scene and camera objects. |
|
var scene = new THREE.Scene() |
|
var camera = new THREE.OrthographicCamera(-WIDTH / 2, WIDTH / 2, HEIGHT / 2, -HEIGHT / 2, 0.1, 10000) |
|
camera.position.z = 500 |
|
// Create renderer object. |
|
var renderer = new THREE.WebGLRenderer({ |
|
antialias: true |
|
}) |
|
renderer.domElement.id = 'shade-layer' |
|
renderer.setClearColor(BACKGROUND_COLOR, 1) |
|
renderer.setSize(WIDTH, HEIGHT) |
|
document.body.appendChild(renderer.domElement) |
|
// Add light to scene. |
|
var light = new THREE.HemisphereLight('#fff', '#666', 1.5) |
|
light.position.set(0, 500, 0) |
|
scene.add(light) |
|
// Create sphere. |
|
var sphere = new THREE.SphereGeometry(120, 100, 100) |
|
var sphereMaterial = new THREE.MeshNormalMaterial({ |
|
wireframe: false |
|
}) |
|
var sphereMesh = new THREE.Mesh(sphere, sphereMaterial) |
|
// For debug ... |
|
var dot1 = new THREE.SphereGeometry(5, 10, 10) |
|
dot1.translate(0, 0, 120) |
|
var dot1Material = new THREE.MeshBasicMaterial({ |
|
color: 'blue' |
|
}) |
|
var dot1Mesh = new THREE.Mesh(dot1, dot1Material) |
|
var dot2 = new THREE.SphereGeometry(5, 10, 10) |
|
dot2.translate(120, 0, 0) |
|
var dot2Material = new THREE.MeshBasicMaterial({ |
|
color: 'red' |
|
}) |
|
var dot2Mesh = new THREE.Mesh(dot2, dot2Material) |
|
var dot3 = new THREE.SphereGeometry(5, 10, 10) |
|
dot3.translate(0, -120, 0) |
|
var dot3Material = new THREE.MeshBasicMaterial({ |
|
color: 'green' |
|
}) |
|
var dot3Mesh = new THREE.Mesh(dot3, dot3Material) |
|
var sphereObject = new THREE.Object3D() |
|
sphereObject.add(sphereMesh, dot1Mesh, dot2Mesh, dot3Mesh) |
|
|
|
scene.add(sphereObject) |
|
function drawShadeLayer() { |
|
renderer.render(scene, camera) |
|
} |
|
drawShadeLayer() |
|
</script> |
|
</body> |
|
</html> |
|
|