A clock!
Last active
October 23, 2019 21:40
-
-
Save nitaku/9314561 to your computer and use it in GitHub Desktop.
Clock
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
LAT = 43.62 | |
LONG = 10.63 | |
DAYS = ['Dom','Lun','Mar','Mer','Gio','Ven','Sab'] | |
MONTHS = ['Gen','Feb','Mar','Apr','Mag','Giu','Lug','Ago','Set','Ott','Nov','Dic'] | |
### add a zero in front of numbers < 10 ### | |
pad_time = (i) -> if i<10 then "0#{i}" else i | |
### add methods to Date to check if DST is in effect ### | |
### from http://stackoverflow.com/questions/11887934/check-if-daylight-saving-time-is-in-effect-and-if-it-is-for-how-many-hours ### | |
Date.prototype.stdTimezoneOffset = () -> | |
jan = new Date(this.getFullYear(), 0, 1) | |
jul = new Date(this.getFullYear(), 6, 1) | |
return Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset()) | |
Date.prototype.dst = () -> this.getTimezoneOffset() < this.stdTimezoneOffset() | |
### SEASONS ### | |
get_season = (now) -> | |
seasons = Date.getSeasons now.getFullYear() | |
if now < seasons[1] | |
return 'winter' | |
else if now < seasons[2] | |
return 'spring' | |
else if now < seasons[3] | |
return 'summer' | |
else if now < seasons[4] | |
return 'fall' | |
else | |
return 'winter' | |
### define a scale for SUN and MOON altitude ### | |
altitude = d3.scale.linear() | |
.domain([-1,1]) | |
.range([600,0]) | |
### DAY/NIGHT ### | |
get_day_night = (now) -> | |
times = SunCalc.getTimes(now, LAT, LONG) | |
if now < times.sunriseEnd | |
return 'night' | |
else if now < times.dusk | |
return 'day' | |
else | |
return 'night' | |
### update every 0.5 seconds ### | |
last_seconds = -1 | |
last_sep = false | |
last_day_night = null | |
update_05_secs = () -> | |
### CLOCK ### | |
now = new Date() | |
h = now.getHours() | |
m = now.getMinutes() | |
s = now.getSeconds() | |
h = pad_time(h) | |
m = pad_time(m) | |
s = pad_time(s) | |
if s != last_seconds | |
last_sep = not last_sep | |
last_seconds = s | |
clock_string = h | |
if last_sep | |
clock_string += ':' | |
else | |
clock_string += ' ' | |
clock_string += m | |
d3.select('#clock') | |
.text(clock_string) | |
### DAYLIGHT SAVINGS TIME ### | |
d3.select('#dst') | |
.text(if now.dst() then "LEG" else "SOL") | |
### CALENDAR ### | |
d3.select('#calendar') | |
.text("#{DAYS[now.getDay()]} #{now.getDate()} #{MONTHS[now.getMonth()]} #{now.getFullYear()}") | |
### SEASONS ### | |
d3.select('#season') | |
.text switch get_season(now) | |
when 'winter' then 'inverno' | |
when 'spring' then 'primavera' | |
when 'summer' then 'estate' | |
when 'fall' then 'autunno' | |
### NETWORK status ### | |
d3.select('#router') | |
.classed('ok', navigator.onLine) # FIXME check by ping | |
d3.select('#wifirouter') | |
.classed('ok', true) # FIXME check by ping | |
### SUN and MOON simulation ### | |
sun_alt = Math.sin SunCalc.getPosition(now, LAT, LONG).altitude | |
moon_alt = Math.sin SunCalc.getMoonPosition(now, LAT, LONG).altitude | |
moon_phase = SunCalc.getMoonIllumination(now) | |
d3.select('#sun') | |
.attr('y', altitude(sun_alt)) | |
.attr('fill','#FFF268') | |
d3.select('#moon') | |
.attr('y', altitude(moon_alt)) | |
.attr('fill','#BDDBFD') | |
d3.select('#moon_symbol > path') | |
.attr('d', if moon_phase.angle > 0 then "M0 30 A30 30 0 1 1 0 -30 A#{60*Math.abs(moon_phase.fraction-0.5)} 30 0 1 #{if moon_phase.fraction > 0.5 then 1 else 0} 0 30" else "M0 30 A#{60*Math.abs(moon_phase.fraction-0.5)} 30 0 1 #{if moon_phase.fraction > 0.5 then 1 else 0} 0 -30 A30 30 0 1 1 0 30") | |
### NIGHT and DAY ### | |
day_night = get_day_night(now) | |
if day_night != last_day_night | |
if day_night is 'day' | |
d3.select('body') | |
.transition().duration(3000) | |
.style('background', '#00BCD1') | |
d3.select('#land') | |
.transition().duration(3000) | |
.attr('fill', '#ABEC72') | |
else if day_night is 'night' | |
d3.select('body') | |
.transition().duration(3000) | |
.style('background', '#434367') | |
d3.select('#land') | |
.transition().duration(3000) | |
.attr('fill', '#0A8690') | |
last_day_night = day_night | |
setTimeout((()->update_05_secs()),500) | |
### update every 10 minutes ### | |
update_10_min = () -> | |
### WHEATER from OpenWeatherMap ### | |
d3.json 'http://api.openweathermap.org/data/2.5/weather?q=Ponsacco,it&APPID=eaecf85a68297fd2c57d209840cb81dc&lang=it', (data) -> | |
if not data? | |
return | |
d3.select('#temperature') | |
.text("#{Math.round(data.main.temp - 273.15)}°") # temp is in Kelvin degrees | |
d3.select('#humidity') | |
.text("#{Math.round(data.main.humidity)}%") | |
if data.weather? and data.weather[0]? | |
# console.debug data.weather[0].icon | |
status = +data.weather[0].icon[0...2] | |
### set haze visibility ### | |
if status < 4 | |
d3.select('#haze') | |
.transition().duration(3000) | |
.attr('fill-opacity', 0) | |
else | |
d3.select('#haze') | |
.transition().duration(3000) | |
.attr('fill-opacity', 0.5) | |
### set clouds visibility ### | |
if status < 2 or status is 50 | |
d3.select('#clouds') | |
.transition().duration(3000) | |
.attr('opacity', 0) | |
else | |
d3.select('#clouds') | |
.transition().duration(3000) | |
.attr('opacity', 1) | |
### set more clouds visibility ### | |
if status < 3 or status is 50 | |
d3.select('#more_clouds') | |
.transition().duration(3000) | |
.attr('opacity', 0) | |
else | |
d3.select('#more_clouds') | |
.transition().duration(3000) | |
.attr('opacity', 1) | |
# if data.weather[0].icon[2] is 'd' | |
# day() | |
# else | |
# night() | |
# .attr('xlink:href', "http://openweathermap.org/img/w/#{data.weather[0].icon}.png") | |
# else | |
# d3.select('#weather_icon') | |
# .attr('xlink:href', '') | |
setTimeout((()->update_10_min()),600000) # OpenWeatherMap time limit is 10 minutes | |
update_05_secs() | |
update_10_min() |
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
html, body { | |
padding: 0; | |
margin: 0; | |
overflow: hidden; | |
width: 1024px; | |
height: 748px; | |
background: gray; | |
} | |
@font-face { | |
font-family: "DroidSansMono"; | |
src: url("DroidSansMono.ttf"); | |
} | |
.tile { | |
font-family: "DroidSansMono"; | |
fill: white; | |
} | |
#calendar { | |
font-size: 40px; | |
font-family: "Georgia"; | |
text-anchor: middle; | |
} | |
#season { | |
text-transform: uppercase; | |
font-weight: bold; | |
text-anchor: middle; | |
} | |
#clock { | |
font-size: 120px; | |
text-anchor: middle; | |
} | |
#dst { | |
font-size: 16px; | |
font-weight: bold; | |
text-anchor: end; | |
} | |
#temperature { | |
font-size: 60px; | |
text-anchor: end; | |
} | |
#humidity { | |
font-size: 40px; | |
text-anchor: end; | |
} | |
/* statuses */ | |
.status .icon { | |
fill: red; | |
} | |
.status.ok .icon { | |
fill: white; | |
} |
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> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> | |
<title>Clock</title> | |
<link type="text/css" href="index.css" rel="stylesheet"/> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script src="suncalc.js"></script> | |
<script src="seasons.js"></script> | |
</head> | |
<body> | |
<svg width="1024" height="748"> | |
<defs> | |
<symbol id="sun_symbol" viewBox="0 0 100 100"> | |
<circle cx="50" cy="50" r="33.715"/> | |
<g> | |
<polygon points="50,5 47.275,13.334 52.725,13.334 "/> | |
<polygon points="50,95 47.275,86.667 52.725,86.667 "/> | |
</g> | |
<g> | |
<polygon points="95,50 86.666,47.276 86.666,52.725 "/> | |
<polygon points="5,50 13.333,47.276 13.333,52.725 "/> | |
</g> | |
<g> | |
<polygon points="18.18,18.18 22.146,26 26,22.146 "/> | |
<polygon points="81.82,81.82 74.002,77.854 77.854,74 "/> | |
</g> | |
<g> | |
<polygon points="81.82,18.18 74.002,22.146 77.854,25.999 "/> | |
<polygon points="18.18,81.82 22.146,74 26,77.854 "/> | |
</g> | |
<g> | |
<polygon points="32.961,8.351 33.595,17.095 38.638,15.032 "/> | |
<polygon points="67.039,91.649 61.361,84.968 66.405,82.904 "/> | |
</g> | |
<g> | |
<polygon points="91.649,32.961 82.905,33.595 84.969,38.638 "/> | |
<polygon points="8.351,67.039 15.032,61.362 17.096,66.405 "/> | |
</g> | |
<g> | |
<polygon points="8.501,32.598 15.133,38.333 17.239,33.308 "/> | |
<polygon points="91.499,67.402 82.76,66.691 84.867,61.668 "/> | |
</g> | |
<g> | |
<polygon points="67.402,8.501 61.668,15.133 66.691,17.24 "/> | |
<polygon points="32.598,91.499 33.308,82.761 38.333,84.868 "/> | |
</g> | |
</symbol> | |
<symbol id="moon_symbol" viewBox="-34 -34 68 68"> | |
<circle r="30" style="fill: black; fill-opacity: 0.1;"/> | |
<path d="M0 30 A30 30 0 1 1 0 -30 A30 30 0 1 1 0 30"/> | |
</symbol> | |
<symbol id="cloud_symbol" viewBox="0 0 100 100"> | |
<path d="M642.02-364.11c-0.772,0-1.519,0.114-2.229,0.313c-0.17-6.744-5.679-12.162-12.464-12.162 c-4.368,0-8.201,2.251-10.428,5.65c-1.38-2.61-4.117-4.393-7.275-4.393c-2.621,0-4.95,1.229-6.456,3.139 c-2.865-6.496-9.357-11.031-16.913-11.031c-8.99,0-16.479,6.42-18.138,14.926c-0.937-0.248-1.911-0.393-2.925-0.393 c-6.312,0-11.427,5.116-11.427,11.427c0,0.907,0.117,1.787,0.317,2.634h95.921c0.146-0.609,0.229-1.243,0.229-1.896 C650.233-360.433,646.556-364.11,642.02-364.11z"/> | |
<path d="M90.02,48.188c-0.771,0-1.518,0.113-2.229,0.312c-0.17-6.744-5.678-12.162-12.463-12.162 c-4.369,0-8.201,2.251-10.428,5.65c-1.381-2.61-4.117-4.393-7.275-4.393c-2.621,0-4.951,1.229-6.457,3.139 c-2.865-6.496-9.357-11.031-16.913-11.031c-8.99,0-16.479,6.42-18.138,14.926c-0.937-0.248-1.911-0.393-2.925-0.393 c-6.312,0-11.427,5.116-11.427,11.427c0,0.907,0.117,1.786,0.317,2.634h95.92c0.146-0.609,0.23-1.243,0.23-1.896 C98.234,51.863,94.557,48.188,90.02,48.188z"/> | |
</symbol> | |
</defs> | |
<use id="sun" xlink:href="#sun_symbol" x="750" width="140" height="140"/> | |
<use id="moon" xlink:href="#moon_symbol" x="148" width="100" height="100"/> | |
<rect id="land" x="0" y="300" width="1024" height="448" fill="white"/> | |
<rect id="haze" x="0" y="0" width="1024" height="748" fill="#888" fill-opacity="0"/> | |
<g id="clouds" fill="white" fill-opacity="0.3" opacity="0"> | |
<use xlink:href="#cloud_symbol" x="800" y="0" width="100" height="100"/> | |
<use xlink:href="#cloud_symbol" x="40" y="50" width="200" height="200"/> | |
<use xlink:href="#cloud_symbol" x="360" y="180" width="140" height="140"/> | |
</g> | |
<g id="more_clouds" fill="white" fill-opacity="0.3" opacity="0"> | |
<use xlink:href="#cloud_symbol" x="240" y="-10" width="80" height="80"/> | |
<use xlink:href="#cloud_symbol" x="10" y="84" width="160" height="160"/> | |
<use xlink:href="#cloud_symbol" x="110" y="180" width="90" height="90"/> | |
<use xlink:href="#cloud_symbol" x="710" y="60" width="280" height="280"/> | |
<use xlink:href="#cloud_symbol" x="894" y="118" width="120" height="120"/> | |
<use xlink:href="#cloud_symbol" x="590" y="-184" width="500" height="500"/> | |
</g> | |
<g transform="translate(0,25)"> | |
<line stroke="black" stroke-width="1" x1="0" x2="10" y1="0" y2="0"/> | |
<circle r="3" cx="10"/> | |
</g> | |
<a xlink:href="http://192.168.0.1" xlink:show="new" target="_blank"> | |
<g id="router" class="status" transform="translate(35,25)"> | |
<path class="icon" transform="scale(0.5) translate(-50,-50)" d="M49.249,17.499c-17.782,0-32.25,14.469-32.25,32.25c0,17.784,14.468,32.252,32.25,32.252 c17.78,0,32.251-14.469,32.251-32.252C81.5,31.968,67.029,17.499,49.249,17.499z M74.211,62.84c-0.006,0-0.012-0.006-0.018-0.006 h-6.654c0.986-3.357,1.666-7.1,1.852-11.121h7.979C77.086,55.717,75.992,59.461,74.211,62.84z M51.381,77.855V66.762h10.584 c-2.064,4.939-4.484,8.549-5.855,10.371C54.58,77.52,53.002,77.732,51.381,77.855z M42.543,77.182 c-1.364-1.799-3.809-5.432-5.896-10.42h10.808v11.127C45.774,77.781,44.131,77.57,42.543,77.182z M24.283,62.84 c-1.778-3.379-2.878-7.123-3.161-11.127h8.094c0.186,4.021,0.866,7.764,1.852,11.121h-6.763 C24.296,62.834,24.291,62.84,24.283,62.84z M24.469,36.313c0.019,0.003,0.032,0.012,0.048,0.012h6.681 c-1.24,3.988-1.821,7.815-1.971,11.462h-8.105C21.413,43.644,22.582,39.78,24.469,36.313z M47.456,21.606v10.792H36.892 c1.489-3.33,3.466-6.745,6.065-10.211C44.413,21.853,45.924,21.705,47.456,21.606z M55.686,22.231 c2.584,3.453,4.549,6.851,6.031,10.167H51.381V21.643C52.848,21.751,54.293,21.905,55.686,22.231z M63.246,36.325 c1.357,3.996,2.006,7.828,2.174,11.462H51.381V36.325H63.246z M47.456,36.325v11.462H33.187c0.17-3.634,0.819-7.466,2.18-11.462 H47.456z M33.182,51.713h14.274v11.121H35.202C34.143,59.516,33.381,55.783,33.182,51.713z M51.381,62.834V51.713h14.045 c-0.203,4.07-0.959,7.803-2.02,11.121H51.381z M69.379,47.787c-0.146-3.647-0.729-7.474-1.971-11.462h6.568 c0.014,0,0.031-0.009,0.049-0.012c1.883,3.467,3.055,7.331,3.344,11.474H69.379z M71.465,32.398h-5.52 c-1.045-2.558-2.316-5.154-3.941-7.796C65.711,26.494,68.92,29.147,71.465,32.398z M36.675,24.501 c-1.651,2.678-2.955,5.307-4.012,7.897h-5.635C29.616,29.093,32.892,26.396,36.675,24.501z M26.749,66.762h5.641 c1.202,3.137,2.576,5.816,3.854,8.002C32.514,72.814,29.276,70.098,26.749,66.762z M62.414,74.668 c1.264-2.168,2.619-4.813,3.801-7.906h5.525C69.254,70.049,66.078,72.725,62.414,74.668z"/> | |
<circle r="20" fill="transparent"/> | |
</g> | |
</a> | |
<g transform="translate(0,730)"> | |
<line stroke="black" stroke-width="1" x1="0" x2="10" y1="0" y2="0"/> | |
<circle r="3" cx="10"/> | |
</g> | |
<a xlink:href="http://192.168.0.4" xlink:show="new" target="_blank"> | |
<g id="wifirouter" class="status" transform="translate(33,720)"> | |
<g transform="scale(0.15) translate(-125,-100)"> | |
<path class="icon" d="M137.085,39.439c-48.16,0-91.761,19.869-123.06,51.829l17.67,17.669c26.77-27.434,64.121-44.497,105.39-44.497 c41.268,0,78.618,17.063,105.39,44.497l17.67-17.669C228.846,59.307,185.245,39.439,137.085,39.439z"/> | |
<path class="icon" d="M137.085,79.624c-37.081,0-70.638,15.361-94.658,40.046l17.669,17.669c19.492-20.159,46.801-32.715,76.989-32.715 s57.497,12.556,76.989,32.715l17.668-17.669C207.723,94.985,174.166,79.624,137.085,79.624z"/> | |
<path class="icon" d="M137.085,121.341c-25.58,0-48.71,10.681-65.173,27.813l17.684,17.685c11.932-12.608,28.802-20.498,47.489-20.498 s35.558,7.89,47.488,20.497l17.685-17.684C185.795,132.021,162.664,121.341,137.085,121.341z"/> | |
<circle class="icon" cx="136.754" cy="198.076" r="29.448"/> | |
</g> | |
</g> | |
</a> | |
<text id="calendar" class="tile" x="512" y="10" dy="1em"/> | |
<text id="season" class="tile" x="512" y="60" dy="1em"/> | |
<text id="clock" class="tile" x="512" y="160" dy=".35em"/> | |
<text id="dst" class="tile" x="670" y="240" dy=".35em"/> | |
<text id="temperature" class="tile" x="1014" y="10" dy="1em"/> | |
<text id="humidity" class="tile" x="1004" y="90" dy="1em"/> | |
</svg> | |
</body> | |
<script src="index.js"></script> | |
</html> |
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
(function() { | |
var DAYS, LAT, LONG, MONTHS, altitude, get_day_night, get_season, last_day_night, last_seconds, last_sep, pad_time, update_05_secs, update_10_min; | |
LAT = 43.62; | |
LONG = 10.63; | |
DAYS = ['Dom', 'Lun', 'Mar', 'Mer', 'Gio', 'Ven', 'Sab']; | |
MONTHS = ['Gen', 'Feb', 'Mar', 'Apr', 'Mag', 'Giu', 'Lug', 'Ago', 'Set', 'Ott', 'Nov', 'Dic']; | |
/* add a zero in front of numbers < 10 | |
*/ | |
pad_time = function(i) { | |
if (i < 10) { | |
return "0" + i; | |
} else { | |
return i; | |
} | |
}; | |
/* add methods to Date to check if DST is in effect | |
*/ | |
/* from http://stackoverflow.com/questions/11887934/check-if-daylight-saving-time-is-in-effect-and-if-it-is-for-how-many-hours | |
*/ | |
Date.prototype.stdTimezoneOffset = function() { | |
var jan, jul; | |
jan = new Date(this.getFullYear(), 0, 1); | |
jul = new Date(this.getFullYear(), 6, 1); | |
return Math.max(jan.getTimezoneOffset(), jul.getTimezoneOffset()); | |
}; | |
Date.prototype.dst = function() { | |
return this.getTimezoneOffset() < this.stdTimezoneOffset(); | |
}; | |
/* SEASONS | |
*/ | |
get_season = function(now) { | |
var seasons; | |
seasons = Date.getSeasons(now.getFullYear()); | |
if (now < seasons[1]) { | |
return 'winter'; | |
} else if (now < seasons[2]) { | |
return 'spring'; | |
} else if (now < seasons[3]) { | |
return 'summer'; | |
} else if (now < seasons[4]) { | |
return 'fall'; | |
} else { | |
return 'winter'; | |
} | |
}; | |
/* define a scale for SUN and MOON altitude | |
*/ | |
altitude = d3.scale.linear().domain([-1, 1]).range([600, 0]); | |
/* DAY/NIGHT | |
*/ | |
get_day_night = function(now) { | |
var times; | |
times = SunCalc.getTimes(now, LAT, LONG); | |
if (now < times.sunriseEnd) { | |
return 'night'; | |
} else if (now < times.dusk) { | |
return 'day'; | |
} else { | |
return 'night'; | |
} | |
}; | |
/* update every 0.5 seconds | |
*/ | |
last_seconds = -1; | |
last_sep = false; | |
last_day_night = null; | |
update_05_secs = function() { | |
/* CLOCK | |
*/ | |
var clock_string, day_night, h, m, moon_alt, moon_phase, now, s, sun_alt; | |
now = new Date(); | |
h = now.getHours(); | |
m = now.getMinutes(); | |
s = now.getSeconds(); | |
h = pad_time(h); | |
m = pad_time(m); | |
s = pad_time(s); | |
if (s !== last_seconds) { | |
last_sep = !last_sep; | |
last_seconds = s; | |
} | |
clock_string = h; | |
if (last_sep) { | |
clock_string += ':'; | |
} else { | |
clock_string += ' '; | |
} | |
clock_string += m; | |
d3.select('#clock').text(clock_string); | |
/* DAYLIGHT SAVINGS TIME | |
*/ | |
d3.select('#dst').text(now.dst() ? "LEG" : "SOL"); | |
/* CALENDAR | |
*/ | |
d3.select('#calendar').text("" + DAYS[now.getDay()] + " " + (now.getDate()) + " " + MONTHS[now.getMonth()] + " " + (now.getFullYear())); | |
/* SEASONS | |
*/ | |
d3.select('#season').text((function() { | |
switch (get_season(now)) { | |
case 'winter': | |
return 'inverno'; | |
case 'spring': | |
return 'primavera'; | |
case 'summer': | |
return 'estate'; | |
case 'fall': | |
return 'autunno'; | |
} | |
})()); | |
/* NETWORK status | |
*/ | |
d3.select('#router').classed('ok', navigator.onLine); | |
d3.select('#wifirouter').classed('ok', true); | |
/* SUN and MOON simulation | |
*/ | |
sun_alt = Math.sin(SunCalc.getPosition(now, LAT, LONG).altitude); | |
moon_alt = Math.sin(SunCalc.getMoonPosition(now, LAT, LONG).altitude); | |
moon_phase = SunCalc.getMoonIllumination(now); | |
d3.select('#sun').attr('y', altitude(sun_alt)).attr('fill', '#FFF268'); | |
d3.select('#moon').attr('y', altitude(moon_alt)).attr('fill', '#BDDBFD'); | |
d3.select('#moon_symbol > path').attr('d', moon_phase.angle > 0 ? "M0 30 A30 30 0 1 1 0 -30 A" + (60 * Math.abs(moon_phase.fraction - 0.5)) + " 30 0 1 " + (moon_phase.fraction > 0.5 ? 1 : 0) + " 0 30" : "M0 30 A" + (60 * Math.abs(moon_phase.fraction - 0.5)) + " 30 0 1 " + (moon_phase.fraction > 0.5 ? 1 : 0) + " 0 -30 A30 30 0 1 1 0 30"); | |
/* NIGHT and DAY | |
*/ | |
day_night = get_day_night(now); | |
if (day_night !== last_day_night) { | |
if (day_night === 'day') { | |
d3.select('body').transition().duration(3000).style('background', '#00BCD1'); | |
d3.select('#land').transition().duration(3000).attr('fill', '#ABEC72'); | |
} else if (day_night === 'night') { | |
d3.select('body').transition().duration(3000).style('background', '#434367'); | |
d3.select('#land').transition().duration(3000).attr('fill', '#0A8690'); | |
} | |
last_day_night = day_night; | |
} | |
return setTimeout((function() { | |
return update_05_secs(); | |
}), 500); | |
}; | |
/* update every 10 minutes | |
*/ | |
update_10_min = function() { | |
/* WHEATER from OpenWeatherMap | |
*/ d3.json('http://api.openweathermap.org/data/2.5/weather?q=Ponsacco,it&APPID=eaecf85a68297fd2c57d209840cb81dc&lang=it', function(data) { | |
var status; | |
if (!(data != null)) return; | |
d3.select('#temperature').text("" + (Math.round(data.main.temp - 273.15)) + "°"); | |
d3.select('#humidity').text("" + (Math.round(data.main.humidity)) + "%"); | |
if ((data.weather != null) && (data.weather[0] != null)) { | |
status = +data.weather[0].icon.slice(0, 2); | |
/* set haze visibility | |
*/ | |
if (status < 4) { | |
d3.select('#haze').transition().duration(3000).attr('fill-opacity', 0); | |
} else { | |
d3.select('#haze').transition().duration(3000).attr('fill-opacity', 0.5); | |
} | |
/* set clouds visibility | |
*/ | |
if (status < 2 || status === 50) { | |
d3.select('#clouds').transition().duration(3000).attr('opacity', 0); | |
} else { | |
d3.select('#clouds').transition().duration(3000).attr('opacity', 1); | |
} | |
/* set more clouds visibility | |
*/ | |
if (status < 3 || status === 50) { | |
return d3.select('#more_clouds').transition().duration(3000).attr('opacity', 0); | |
} else { | |
return d3.select('#more_clouds').transition().duration(3000).attr('opacity', 1); | |
} | |
} | |
}); | |
return setTimeout((function() { | |
return update_10_min(); | |
}), 600000); | |
}; | |
update_05_secs(); | |
update_10_min(); | |
}).call(this); |
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
Date.fromJulian= function(j){ | |
j= (+j)+(30.0/(24*60*60)); | |
var A= Date.julianArray(j, true); | |
return new Date(Date.UTC.apply(Date, A)); | |
} | |
Date.julianArray= function(j, n){ | |
var F= Math.floor; | |
var j2, JA, a, b, c, d, e, f, g, h, z; | |
j+= .5; | |
j2= (j-F(j))*86400.0; | |
z= F(j); | |
f= j-z; | |
if(z< 2299161) a= z; | |
else{ | |
g= F((z-1867216.25)/36524.25); | |
a= z+1+g-F(g/4); | |
} | |
b= a+1524; | |
c= F((b-122.1)/365.25); | |
d= F(365.25*c); | |
e= F((b-d)/30.6001); | |
h= F((e< 14)? (e-1): (e-13)); | |
var JA= [F((h> 2)? (c-4716): (c-4715)), | |
h-1, F(b-d-F(30.6001*e)+f)]; | |
var JB= [F(j2/3600), F((j2/60)%60), Math.round(j2%60)]; | |
JA= JA.concat(JB); | |
if(typeof n== 'number') return JA.slice(0, n); | |
return JA; | |
} | |
Date.getSeasons= function(y, wch){ | |
y= y || new Date().getFullYear(); | |
if(y<1000 || y> 3000) throw y+' is out of range'; | |
var Y1= (y-2000)/1000, Y2= Y1*Y1, Y3= Y2*Y1, Y4= Y3*Y1; | |
var jd, t, w, d, est= 0, i= 0, Cos= Math.degCos, A= [y], | |
e1= [485, 203, 199, 182, 156, 136, 77, 74, 70, 58, 52, 50, 45, 44, 29, 18, 17, 16, 14, 12, 12, 12, 9, 8], | |
e2= [324.96, 337.23, 342.08, 27.85, 73.14, 171.52, 222.54, 296.72, 243.58, 119.81, 297.17, 21.02, | |
247.54, 325.15, 60.93, 155.12, 288.79, 198.04, 199.76, 95.39, 287.11, 320.81, 227.73, 15.45], | |
e3= [1934.136, 32964.467, 20.186, 445267.112, 45036.886, 22518.443, | |
65928.934, 3034.906, 9037.513, 33718.147, 150.678, 2281.226, | |
29929.562, 31555.956, 4443.417, 67555.328, 4562.452, 62894.029, | |
31436.921, 14577.848, 31931.756, 34777.259, 1222.114, 16859.074]; | |
while(i< 4){ | |
switch(i){ | |
case 0: jd= 2451623.80984 + 365242.37404*Y1 + 0.05169*Y2 - 0.00411*Y3 - 0.00057*Y4; | |
break; | |
case 1: jd= 2451716.56767 + 365241.62603*Y1 + 0.00325*Y2+ 0.00888*Y3 - 0.00030*Y4; | |
break; | |
case 2: jd= 2451810.21715 + 365242.01767*Y1 - 0.11575*Y2 + 0.00337*Y3 + 0.00078*Y4; | |
break; | |
case 3: jd= 2451900.05952 + 365242.74049*Y1 - 0.06223*Y2 - 0.00823*Y3 + 0.00032*Y4; | |
break; | |
} | |
var t= (jd- 2451545.0)/36525, | |
w= 35999.373*t - 2.47, | |
d= 1 + 0.0334*Cos(w)+ 0.0007*Cos(2*w); | |
est= 0; | |
for(var n= 0; n<24; n++){ | |
est += e1[n]*Cos(e2[n]+(e3[n]*t)); | |
} | |
jd+= (0.00001*est)/d; | |
A[++i]= Date.fromJulian(jd); | |
} | |
return wch && A[wch]? A[wch]: A; | |
} | |
Math.degRad= function(d){ | |
return (d*Math.PI)/180.0 | |
} | |
Math.degSin= function(d){ | |
return Math.sin(Math.degRad(d)) | |
} | |
Math.degCos= function(d){ | |
return Math.cos(Math.degRad(d)) | |
} |
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
/* | |
(c) 2011-2014, Vladimir Agafonkin | |
SunCalc is a JavaScript library for calculating sun/mooon position and light phases. | |
https://github.com/mourner/suncalc | |
*/ | |
(function () { "use strict"; | |
// shortcuts for easier to read formulas | |
var PI = Math.PI, | |
sin = Math.sin, | |
cos = Math.cos, | |
tan = Math.tan, | |
asin = Math.asin, | |
atan = Math.atan2, | |
acos = Math.acos, | |
rad = PI / 180; | |
// sun calculations are based on http://aa.quae.nl/en/reken/zonpositie.html formulas | |
// date/time constants and conversions | |
var dayMs = 1000 * 60 * 60 * 24, | |
J1970 = 2440588, | |
J2000 = 2451545; | |
function toJulian(date) { | |
return date.valueOf() / dayMs - 0.5 + J1970; | |
} | |
function fromJulian(j) { | |
return new Date((j + 0.5 - J1970) * dayMs); | |
} | |
function toDays(date) { | |
return toJulian(date) - J2000; | |
} | |
// general calculations for position | |
var e = rad * 23.4397; // obliquity of the Earth | |
function getRightAscension(l, b) { | |
return atan(sin(l) * cos(e) - tan(b) * sin(e), cos(l)); | |
} | |
function getDeclination(l, b) { | |
return asin(sin(b) * cos(e) + cos(b) * sin(e) * sin(l)); | |
} | |
function getAzimuth(H, phi, dec) { | |
return atan(sin(H), cos(H) * sin(phi) - tan(dec) * cos(phi)); | |
} | |
function getAltitude(H, phi, dec) { | |
return asin(sin(phi) * sin(dec) + cos(phi) * cos(dec) * cos(H)); | |
} | |
function getSiderealTime(d, lw) { | |
return rad * (280.16 + 360.9856235 * d) - lw; | |
} | |
// general sun calculations | |
function getSolarMeanAnomaly(d) { | |
return rad * (357.5291 + 0.98560028 * d); | |
} | |
function getEquationOfCenter(M) { | |
return rad * (1.9148 * sin(M) + 0.02 * sin(2 * M) + 0.0003 * sin(3 * M)); | |
} | |
function getEclipticLongitude(M, C) { | |
var P = rad * 102.9372; // perihelion of the Earth | |
return M + C + P + PI; | |
} | |
function getSunCoords(d) { | |
var M = getSolarMeanAnomaly(d), | |
C = getEquationOfCenter(M), | |
L = getEclipticLongitude(M, C); | |
return { | |
dec: getDeclination(L, 0), | |
ra: getRightAscension(L, 0) | |
}; | |
} | |
var SunCalc = {}; | |
// calculates sun position for a given date and latitude/longitude | |
SunCalc.getPosition = function (date, lat, lng) { | |
var lw = rad * -lng, | |
phi = rad * lat, | |
d = toDays(date), | |
c = getSunCoords(d), | |
H = getSiderealTime(d, lw) - c.ra; | |
return { | |
azimuth: getAzimuth(H, phi, c.dec), | |
altitude: getAltitude(H, phi, c.dec) | |
}; | |
}; | |
// sun times configuration (angle, morning name, evening name) | |
var times = [ | |
[-0.83, 'sunrise', 'sunset' ], | |
[ -0.3, 'sunriseEnd', 'sunsetStart' ], | |
[ -6, 'dawn', 'dusk' ], | |
[ -12, 'nauticalDawn', 'nauticalDusk'], | |
[ -18, 'nightEnd', 'night' ], | |
[ 6, 'goldenHourEnd', 'goldenHour' ] | |
]; | |
// adds a custom time to the times config | |
SunCalc.addTime = function (angle, riseName, setName) { | |
times.push([angle, riseName, setName]); | |
}; | |
// calculations for sun times | |
var J0 = 0.0009; | |
function getJulianCycle(d, lw) { | |
return Math.round(d - J0 - lw / (2 * PI)); | |
} | |
function getApproxTransit(Ht, lw, n) { | |
return J0 + (Ht + lw) / (2 * PI) + n; | |
} | |
function getSolarTransitJ(ds, M, L) { | |
return J2000 + ds + 0.0053 * sin(M) - 0.0069 * sin(2 * L); | |
} | |
function getHourAngle(h, phi, d) { | |
return acos((sin(h) - sin(phi) * sin(d)) / (cos(phi) * cos(d))); | |
} | |
// calculates sun times for a given date and latitude/longitude | |
SunCalc.getTimes = function (date, lat, lng) { | |
var lw = rad * -lng, | |
phi = rad * lat, | |
d = toDays(date), | |
n = getJulianCycle(d, lw), | |
ds = getApproxTransit(0, lw, n), | |
M = getSolarMeanAnomaly(ds), | |
C = getEquationOfCenter(M), | |
L = getEclipticLongitude(M, C), | |
dec = getDeclination(L, 0), | |
Jnoon = getSolarTransitJ(ds, M, L); | |
// returns set time for the given sun altitude | |
function getSetJ(h) { | |
var w = getHourAngle(h, phi, dec), | |
a = getApproxTransit(w, lw, n); | |
return getSolarTransitJ(a, M, L); | |
} | |
var result = { | |
solarNoon: fromJulian(Jnoon), | |
nadir: fromJulian(Jnoon - 0.5) | |
}; | |
var i, len, time, angle, morningName, eveningName, Jset, Jrise; | |
for (i = 0, len = times.length; i < len; i += 1) { | |
time = times[i]; | |
Jset = getSetJ(time[0] * rad); | |
Jrise = Jnoon - (Jset - Jnoon); | |
result[time[1]] = fromJulian(Jrise); | |
result[time[2]] = fromJulian(Jset); | |
} | |
return result; | |
}; | |
// moon calculations, based on http://aa.quae.nl/en/reken/hemelpositie.html formulas | |
function getMoonCoords(d) { // geocentric ecliptic coordinates of the moon | |
var L = rad * (218.316 + 13.176396 * d), // ecliptic longitude | |
M = rad * (134.963 + 13.064993 * d), // mean anomaly | |
F = rad * (93.272 + 13.229350 * d), // mean distance | |
l = L + rad * 6.289 * sin(M), // longitude | |
b = rad * 5.128 * sin(F), // latitude | |
dt = 385001 - 20905 * cos(M); // distance to the moon in km | |
return { | |
ra: getRightAscension(l, b), | |
dec: getDeclination(l, b), | |
dist: dt | |
}; | |
} | |
SunCalc.getMoonPosition = function (date, lat, lng) { | |
var lw = rad * -lng, | |
phi = rad * lat, | |
d = toDays(date), | |
c = getMoonCoords(d), | |
H = getSiderealTime(d, lw) - c.ra, | |
h = getAltitude(H, phi, c.dec); | |
// altitude correction for refraction | |
h = h + rad * 0.017 / tan(h + rad * 10.26 / (h + rad * 5.10)); | |
return { | |
azimuth: getAzimuth(H, phi, c.dec), | |
altitude: h, | |
distance: c.dist | |
}; | |
}; | |
// calculations for illumination parameters of the moon, | |
// based on http://idlastro.gsfc.nasa.gov/ftp/pro/astro/mphase.pro formulas and | |
// Chapter 48 of "Astronomical Algorithms" 2nd edition by Jean Meeus | |
// (Willmann-Bell, Richmond) 1998. | |
SunCalc.getMoonIllumination = function (date) { | |
var d = toDays(date), | |
s = getSunCoords(d), | |
m = getMoonCoords(d), | |
sdist = 149598000, // distance from Earth to Sun in km | |
phi = acos(sin(s.dec) * sin(m.dec) + cos(s.dec) * cos(m.dec) * cos(s.ra - m.ra)), | |
inc = atan(sdist * sin(phi), m.dist - sdist * cos(phi)); | |
return { | |
fraction: (1 + cos(inc)) / 2, | |
angle: atan(cos(s.dec) * sin(s.ra - m.ra), sin(s.dec) * cos(m.dec) | |
- cos(s.dec) * sin(m.dec) * cos(s.ra - m.ra)) | |
}; | |
}; | |
// export as AMD module / Node module / browser variable | |
if (typeof define === 'function' && define.amd) { | |
define(SunCalc); | |
} else if (typeof module !== 'undefined') { | |
module.exports = SunCalc; | |
} else { | |
window.SunCalc = SunCalc; | |
} | |
}()); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment