Last active
April 24, 2018 15:06
-
-
Save osoken/d4a2b8a53882f0b053d058a25724318a to your computer and use it in GitHub Desktop.
See-Through Globe with Drop Shadow
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<meta charset='utf-8'> | |
<script src='//d3js.org/d3.v4.min.js'></script> | |
<script src='//d3js.org/topojson.v1.min.js'></script> | |
<body> | |
<style> | |
</style> | |
<script> | |
var width = 960, | |
height = 500; | |
var scale = 120; | |
var projection = d3.geoOrthographic() | |
.translate([0, 0]) | |
.scale(scale); | |
var shadowProjection = d3.geoOrthographic() | |
.translate([0, 0]) | |
.scale(-scale); | |
var angle = 12; | |
var hue = 210; | |
var path = d3.geoPath() | |
.projection(projection); | |
var shadowPath = d3.geoPath() | |
.projection(shadowProjection); | |
var velocity = 0.02; | |
var frequency = 0.0006; | |
var graticuleGeom = d3.geoGraticule()(); | |
var sphereGeom = {type: 'Sphere'}; | |
var svg = d3.select('body').append('svg') | |
.attr('width', width) | |
.attr('height', height); | |
var fog = svg.append('defs') | |
.append('linearGradient') | |
.attr('id', 'fog') | |
.attr('gradientTransform', 'rotate(90)'); | |
fog.append('stop') | |
.attr('offset', 0) | |
.attr('stop-color', '#FFF'); | |
fog.append('stop') | |
.attr('offset', 0.55) | |
.attr('stop-color', '#FFF'); | |
fog.append('stop') | |
.attr('offset', 0.65) | |
.attr('stop-color', 'hsl(' + hue + ', 90%, 92%)'); | |
fog.append('stop') | |
.attr('offset', 1.0) | |
.attr('stop-color', 'hsl(' + hue + ', 90%, 92%)'); | |
svg.append('rect') | |
.attr('width', width) | |
.attr('height', height) | |
.attr('x', 0) | |
.attr('y', 0) | |
.attr('fill', 'url(#fog)'); | |
var drawLayer = svg.append('g') | |
.attr( | |
'transform', | |
'translate(' + (0.5 * width) + ', ' + (0.5 * height + 50)+ ')' | |
); | |
d3.json( | |
'/osoken/raw/f141a4f3faed8cedf8a73aaf6344cf0f/ne_110m_land.json', | |
function(error, world) { | |
if (error) throw error; | |
var geom = topojson.feature(world, world.objects.ne_110m_land); | |
var filter = svg.append('filter') | |
.attr('id', 'shadowFilter') | |
.attr('filterUnits', 'userSpaceOnUse') | |
.attr('x', -0.5 * width) | |
.attr('y', -0.5 * height) | |
.attr('width', width).attr('height', height); | |
var blur = filter.append('feGaussianBlur') | |
.attr('in', 'SourceGraphic') | |
.attr('stdDeviation', 0); | |
var shadowLayer = drawLayer.append('g') | |
.datum(geom) | |
.attr('stroke', 'none') | |
.attr( | |
'transform', | |
'translate(0, ' + scale + ') ' + | |
'scale(1.0, ' + (Math.sin(angle * Math.PI / 180)) + ')' | |
).attr('filter', 'url(#shadowFilter)'); | |
shadowProjection.clipAngle(180); | |
var shadowBack = shadowLayer.append('path') | |
.attr('d', shadowPath); | |
shadowProjection.clipAngle(90); | |
var shadowFront = shadowLayer.append('path') | |
.attr('d', shadowPath); | |
var earthLayer = drawLayer.append('g'); | |
projection.clipAngle(180); | |
var landBack = earthLayer.append('path') | |
.datum(geom) | |
.attr('fill', '#BABABA') | |
.attr('stroke', 'none') | |
.attr('d', path); | |
projection.clipAngle(90); | |
var sphere = earthLayer.append('path') | |
.datum(sphereGeom) | |
.attr('stroke', 'none') | |
.attr('fill', 'rgba(255, 255, 255, 0.4)') | |
.attr('d', path); | |
var graticule = earthLayer.append('path') | |
.datum(graticuleGeom) | |
.attr('fill', 'none') | |
.attr('stroke', '#F7F7F7') | |
.attr('stroke-width', 1.0) | |
.attr('d', path); | |
var landFront = earthLayer.append('path') | |
.datum(geom) | |
.attr('fill', '#BABABA') | |
.attr('stroke', 'none') | |
.attr('d', path); | |
d3.timer(function(elapsed) { | |
var r = velocity * elapsed; | |
var y = -Math.sin(frequency * elapsed); | |
blur.attr('stdDeviation', 10 + 6 * y); | |
shadowLayer.attr('fill', 'hsl(' + hue + ', 20%, ' + (70 + 1 * y) + '%)'); | |
shadowProjection.rotate([r, -90]).scale(scale + 30 * (1 + y)) | |
.clipAngle(180); | |
shadowBack.attr('d', shadowPath); | |
shadowProjection.clipAngle(90); | |
shadowFront.attr('d', shadowPath); | |
projection.rotate([r, -angle]).translate([0, -75 * (1 + y)]) | |
.clipAngle(180); | |
landBack.attr('d', path); | |
projection.clipAngle(90); | |
sphere.attr('d', path); | |
graticule.attr('d', path); | |
landFront.attr('d', path); | |
}); | |
} | |
); | |
</script> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment