A 2017 moon calendar. Click to show today.
Uses the "Simple" moon plase calculation from Moon Phase Calculators. Built with blockbuilder.org. Forked from curran's block: Moon
license: mit | |
border: no | |
height: 380 |
A 2017 moon calendar. Click to show today.
Uses the "Simple" moon plase calculation from Moon Phase Calculators. Built with blockbuilder.org. Forked from curran's block: Moon
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<style> | |
body { | |
margin: 0;position: fixed;top: 0;right: 0;bottom: 0;left: 0; | |
} | |
text { | |
font-size: 1rem; | |
} | |
.axis .domain, .axis line { | |
display: none; | |
} | |
</style> | |
</head> | |
<body> | |
<svg width="960" height="380"></svg> | |
<script> | |
var svg = d3.select("svg"), | |
width = svg.attr("width"), | |
height = svg.attr("height"), | |
margin = { left: 100, right: 15, top: 35, bottom: 35 }, | |
moonSize = 12, | |
moonStroke = 0.5, | |
axisPadding = moonSize - 2, | |
startDate = new Date(2017, 0, 1), | |
endDate = new Date(2017, 11, 31); | |
var g = svg.append("g") | |
.attr("transform", "translate(" + [margin.left, margin.top] + ")"), | |
innerWidth = width - margin.right - margin.left, | |
innerHeight = height - margin.bottom - margin.top, | |
formatMonth = d3.timeFormat("%B"), | |
formatDay = d3.timeFormat("%d"), | |
newMoon = (new Date(1970, 0, 7, 20, 35, 0)).getTime(), | |
lunarPeriod = 2551443000, | |
data = d3.timeDays(startDate, endDate).map(type); | |
function type (date){ | |
return { | |
month: formatMonth(date), | |
day: formatDay(date), | |
phase: -((date.getTime() - newMoon)) / lunarPeriod * 360 + 180 | |
}; | |
} | |
var xScale = d3.scaleLinear() | |
.domain(d3.extent(data, function (d){ return d.day; })) | |
.range([0, innerWidth]), | |
yScale = d3.scalePoint() | |
.domain(data.map(function (d){ return d.month; })) | |
.range([0, innerHeight]); | |
var circle = d3.geoCircle(), | |
projection = d3.geoOrthographic() | |
.scale(moonSize) | |
.translate([0, 0]), | |
path = d3.geoPath() | |
.projection(projection); | |
g.append("g") | |
.attr("class", "y axis") | |
.attr("transform", "translate(-" + axisPadding + ")") | |
.call(d3.axisLeft().scale(yScale)); | |
g.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0,-" + axisPadding + ")") | |
.call(d3.axisTop().scale(xScale).ticks(30)); | |
g.append("g") | |
.attr("class", "x axis") | |
.attr("transform", "translate(0," + (innerHeight + axisPadding) + ")") | |
.call(d3.axisBottom().scale(xScale).ticks(30)); | |
var moons = g.selectAll(".moon").data(data) | |
.enter().append("g") | |
.attr("class", "moon") | |
.attr("transform", function (d){ | |
return "translate(" + [xScale(d.day), yScale(d.month)] + ")"; | |
}); | |
moons.append("circle") | |
.attr("fill", "#2b281b") | |
.attr("r", moonSize + moonStroke); | |
moons.append("path") | |
.attr("fill", "#f7f6f2") | |
.attr("d", function (d){ | |
return path(circle.center([d.phase, 0])()); | |
}); | |
svg.on("click", function (){ | |
var d = type(new Date()); | |
g.append("circle") | |
.attr("cx", function (){ return xScale(d.day); }) | |
.attr("cy", function (){ return yScale(d.month); }) | |
.attr("stroke", "red") | |
.attr("stroke-width", "50px") | |
.attr("stroke-opacity", 0) | |
.attr("fill", "none") | |
.attr("r", 500) | |
.transition().duration(1000) | |
.attr("stroke-width", "3px") | |
.attr("stroke-opacity", 1) | |
.attr("r", moonSize + 5); | |
}); | |
</script> | |
</body> |