Skip to content

Instantly share code, notes, and snippets.

@erohinaelena
Last active February 15, 2017 22:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erohinaelena/261c58f2c283eae3a72d to your computer and use it in GitHub Desktop.
Save erohinaelena/261c58f2c283eae3a72d to your computer and use it in GitHub Desktop.
Draggable night sky map
<html>
<head>
<meta charset="utf-8">
<link href="stars.css" rel="stylesheet">
</head>
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script src="stars.js"></script>
</body>
</html>
body {
background: #113;
}
var width = 960,
height = 500;
var projection = d3.geo.stereographic()
.scale(600)
var fixedProjection = d3.geo.stereographic()
.scale(600)
.rotate([0, 0])
var canvas = d3.select("body").append("canvas")
.attr("width", width)
.attr("height", height)
var c = canvas.node().getContext("2d")
function getRetinaRatio() {
var devicePixelRatio = window.devicePixelRatio || 1
var backingStoreRatio = c.webkitBackingStorePixelRatio ||
c.mozBackingStorePixelRatio ||
c.msBackingStorePixelRatio ||
c.oBackingStorePixelRatio ||
c.backingStorePixelRatio || 1
return devicePixelRatio / backingStoreRatio
}
var ratio = getRetinaRatio()
var scaledWidth = width * ratio
var scaledHeight = height * ratio
canvas.node().width = scaledWidth
canvas.node().height = scaledHeight
canvas
.style("width", width + 'px')
.style("height", height + 'px')
c.scale(ratio, ratio)
var path = d3.geo.path()
.projection(projection)
.context(c)
var graticule = d3.geo.graticule()
.step([15, 15])
var bgRGB = d3.rgb('#113')
d3.json("/erohinaelena/raw/ec635d68e8bf55586d40/starData.json", function(error, data) {
var geoConstellations = []
var starsMag = []
data = data.map(function(constellation) {
constellation.stars = constellation.stars.filter(function(star) {
if (star.mag < 6) starsMag.push(star.mag)
return star.mag < 6
})
return constellation
})
var minMaxMag = d3.extent(starsMag)
var opacityScale = d3.scale.linear()
.domain(minMaxMag)
.range([1, 0.4])
var magScale = d3.scale.linear()
.domain(minMaxMag)
.range([2.7, 1.7])
data.forEach(function (constellation) {
var geometries = []
constellation.stars.map(function (star) {
var rgb = d3.rgb(star.color)
var rgba = 'rgba(' + rgb.r + ',' + rgb.g + ',' + rgb.b + ',' + opacityScale(star.mag) + ')'
geometries.push({
type: 'Point',
coordinates: [-star.ra, star.dec],
properties: {
color: rgba,
mag: magScale(star.mag)
}
})
})
var lines = constellation.lines.map(function (line) {
var p1 = [-line.ra1, line.dec1]
var p2 = [-line.ra2, line.dec2]
return [p1, p2]
})
geometries.push({
type: "MultiLineString",
coordinates: lines
})
if (constellation.name == 'Serpens'){
var bound1 = constellation.boundary[0].map(function (coords) {
return [-coords[0], coords[1]]
})
var bound2 = constellation.boundary[1].map(function (coords) {
return [-coords[0], coords[1]]
})
geometries.push({
type: "LineString",
coordinates: bound1
})
geometries.push({
type: "LineString",
coordinates: bound2
})
} else {
var boundLines = constellation.boundary.map(function (coords) {
return [-coords[0], coords[1]]
})
geometries.push({
type: "LineString",
coordinates: boundLines
})
}
geometries = {
type: 'GeometryCollection',
geometries: geometries
}
var geoConstellation = {
type: 'Feature',
geometry: geometries,
properties: {
name: constellation.name,
zodiac: constellation.zodiac,
center: d3.geo.centroid(geometries)
}
}
geoConstellations.push(geoConstellation)
})
draw(geoConstellations, [30, -70])
var raStart, decStart
function getStart() {
raStart = projection.invert(d3.mouse(this))[0]
decStart = fixedProjection.invert(d3.mouse(this))[1]
}
function move() {
var raFinish = projection.invert(d3.mouse(this))[0]
var decFinish = fixedProjection.invert(d3.mouse(this))[1]
var raRotate = raFinish - raStart
var decRotate = decFinish - decStart
var rotate = projection.rotate()
var newCenter = [rotate[0] + raRotate, rotate[1] + decRotate]
draw(geoConstellations, newCenter)
decStart = fixedProjection.invert(d3.mouse(this))[1]
}
var drag = d3.behavior.drag()
.on("dragstart", getStart)
.on("drag", move)
canvas.call(drag)
})
function makeRadialGradient(x, y, r, color) {
var radialgradient = c.createRadialGradient(x, y, 0, x, y, r)
radialgradient.addColorStop(0.2, color)
radialgradient.addColorStop(0.5,'rgba(' + bgRGB.r + ',' + bgRGB.g + ',' + bgRGB.b + ',0)')
radialgradient.addColorStop(0.5,'rgba(' + bgRGB.r + ',' + bgRGB.g + ',' + bgRGB.b + ',1)')
radialgradient.addColorStop(1,'rgba(' + bgRGB.r + ',' + bgRGB.g + ',' + bgRGB.b + ',0)')
c.fillStyle = radialgradient
}
function distance(p) {
var center = [width / 2, height / 2]
var xRotate = center[0] - p[0]
var yRotate = center[1] - p[1]
return Math.sqrt(Math.pow(xRotate, 2) + Math.pow(yRotate, 2))
}
function draw(constellations, center) {
var min = 0,
minDistance = distance(projection(constellations[0].properties.center))
if (center) projection.rotate(center)
c.clearRect(0, 0, width, height)
c.strokeStyle = "#fff"
c.lineWidth = .1
c.beginPath(), path(graticule()), c.stroke()
c.lineWidth = .4
c.beginPath(), path({type: "LineString", coordinates: [[-180, 0], [-90, 0], [0, 0], [90, 0], [180, 0]]}), c.stroke()
c.strokeStyle = "#f2f237"
c.beginPath(), path({type: "LineString", coordinates: [[-180, 0], [-90, 23.26], [0, 0], [90, -23.26], [180, 0]]}), c.stroke()
constellations.forEach(function(constellation, i) {
var currentDistance = distance(projection(constellations[i].properties.center))
if (currentDistance < minDistance) {
min = i
minDistance = currentDistance
}
constellation.geometry.geometries.forEach(function(geo) {
if (geo.type == 'Point') {
makeRadialGradient(
projection(geo.coordinates)[0],
projection(geo.coordinates)[1],
geo.properties.mag,
geo.properties.color)
path.pointRadius([geo.properties.mag])
c.beginPath(), path(geo), c.fill();
} else if (geo.type == 'LineString') {
c.strokeStyle = '#000'
c.beginPath(), path(geo),c.stroke()
} else if (geo.type == 'MultiLineString') {
c.strokeStyle = (constellation.properties.zodiac)? '#f2f237':"#999"
c.beginPath(), path(geo), c.stroke();
}
})
})
c.strokeStyle = "#f00"
c.lineWidth = 1.2
constellations[min].geometry.geometries.forEach(function(geo) {
if (geo.type == 'LineString') {
c.beginPath(), path(geo), c.stroke()
}
})
c.fillStyle = '#fff'
c.textAlign = "center"
c.font = "18px sans-serif"
c.fillText(constellations[min].properties.name, width / 2, 280)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment