Created
July 3, 2016 05:55
-
-
Save erik-sn/c854a7e5d86b347f969b57e2e0004aef to your computer and use it in GitHub Desktop.
Local Weather
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
<div id="loader" >Loading...</div> | |
<div id="page-container"> | |
<div id="temp-toggle">Toggle °C/°F</div> | |
<div id="sky-container"> | |
<div id="cloud-container"></div> | |
<div id="precipitation-container"></div> | |
<div id="sun-moon-container"> | |
</div> | |
<div id="warning"></div> | |
<div id="main-container"> | |
<div id="location" ></div> | |
<div id="main-icon-container"></div> | |
<div id="weather"></div> | |
<div id="tempF"></div> | |
<div id="tempC"></div> | |
<div id="humidity"></div> | |
</div> | |
</div> | |
<svg id="landscape-curve" viewBox="0 0 700 150" preserveAspectRatio="xMinYMin meet" style="background-color: green"> | |
<defs> | |
<filter id="filter1" x="0" y="0"> | |
<feOffset result="offOut" in="SourceGraphic" dx="-5" dy="0" /> | |
<feGaussianBlur result="blurOut" in="offOut" stdDeviation="5" /> | |
<feBlend in="SourceGraphic" in2="blurOut" mode="normal" /> | |
</filter> | |
</defs> | |
<path filter="url(#filter1)" d="M0, 50 C150,200 0,0 700,100 L700,00 L0,0 Z" style="stroke: none;"></path> | |
</svg> | |
<div id="landscape-container"> | |
<div class="container-fluid" id="hourly-container"> | |
<div id="hourly-label">Hourly Forecast</div> | |
<div class="row row-centered"> | |
<div class="col-xs-1 col-centered hour-container"></div> | |
<div class="col-xs-1 col-centered hour-container"></div> | |
<div class="col-xs-1 col-centered hour-container"></div> | |
<div class="col-xs-1 col-centered hour-container"></div> | |
<div class="col-xs-1 col-centered hour-container"></div> | |
<div class="col-xs-1 col-centered hour-container"></div> | |
<div class="col-xs-1 col-centered hour-container"></div> | |
<div class="col-xs-1 col-centered hour-container"></div> | |
<div class="col-xs-1 col-centered hour-container"></div> | |
<div class="col-xs-1 col-centered hour-container"></div> | |
</div> | |
</div> | |
</div> | |
</div> |
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
var weatherState; | |
var tempState = 'F'; | |
$('document').ready(function() { | |
showLoader(); | |
$('#temp-toggle').click(function() { | |
if (tempState === 'F') { | |
tempState = 'C'; | |
$('.farenheit').hide(); | |
$('.celsius').show(); | |
} else { | |
tempState = 'F'; | |
$('.celsius').hide(); | |
$('.farenheit').show(); | |
} | |
}); | |
$(window).resize(function() { | |
var width = $(window).width(); | |
if (width > 600) { | |
// $('#sun-moon-container').fadeIn(1000); | |
$('.cloud').fadeIn(1000); | |
addPrecipitation(weatherState); | |
console.log(weatherState) | |
setWeather(weatherState); | |
} else { | |
$('#sun-moon-container').fadeOut(500); | |
$('.cloud').fadeOut(500); | |
$('.drop').fadeOut(500); | |
} | |
if (width < 600 && width > 450) { | |
$('#sky-container').height(200 + (600 - width) / 2 ); | |
$('#landscape-container').css('margin-top', (500 - width) /2 ); | |
} | |
}); | |
if (navigator.geolocation) { | |
navigator.geolocation.getCurrentPosition(function(position) { | |
var weatherUrl = generateWeatherUrl(position); | |
var locationUrl = generateLocationUrl(position); | |
getData(weatherUrl, 'jsonp', function(weatherData) { | |
getData(locationUrl, 'json', function(locationData) { | |
if (weatherData && locationData) { | |
hideLoader(); | |
$('#main-icon-container').html('<i class="wi ' + getWeatherIcon(weatherData.currently.icon) + ' main-icon"></i>'); | |
$('#location').html(retrieveLocation(locationData.results)); | |
$('#weather').html(weatherData.currently.summary); | |
var temperature = weatherData.currently.temperature; | |
$('#tempC').html('<div class="celsius">Temp: ' + fToC(temperature) + '°C</div>'); | |
$('#tempF').html('<div class="farenheit">Temp: ' + Math.round(temperature) + '°F</div>'); | |
$('#humidity').html('Humidity: ' + Math.round(weatherData.currently.humidity * 100) + '%'); | |
setHourlyData(weatherData.hourly.data); | |
setWeather(weatherData.currently.icon); | |
} else { | |
$('#page-container').hide(); | |
$('#warning').html('Could not load data, please try to refresh the page.'); | |
} | |
}); | |
}); | |
}, function(error) { | |
$('#page-container').hide(); | |
$('#warning').html('Geolocation only works over HTTPS, please make sure you are using it!'); | |
}); | |
} | |
}); | |
function showLoader() { | |
$('#page-container').hide(); | |
$('#loader').show(); | |
} | |
function hideLoader() { | |
$('#loader').hide(); | |
$('#page-container').show(); | |
} | |
function generateWeatherUrl(position) { | |
var weatherUrl = 'https://api.forecast.io/forecast/5a271ab011ef2106cf601442dc3a7694/' | |
return weatherUrl + position.coords.latitude + ',' + position.coords.longitude + '/'; | |
} | |
function generateLocationUrl(position) { | |
var base = 'https://maps.googleapis.com/maps/api/geocode/json?latlng=' | |
return base + position.coords.latitude + ',' + position.coords.longitude; | |
} | |
function getData(url, dataType, returnData) { | |
$.ajax({ | |
url: url, | |
type: 'GET', | |
dataType: dataType, | |
success: function(data) { | |
returnData(data) | |
}, | |
error: function() { | |
returnData(undefined); | |
} | |
}); | |
} | |
/** | |
Sift through geolocation data, find only locations that have a single | |
'political' address and return the formatted address. | |
**/ | |
function retrieveLocation(data) { | |
if (data.length === 0) { | |
return ''; | |
} | |
var matches = data.filter(function(result) { | |
if (result.types.length === 1 && result.types[0] === 'political') { | |
return true; | |
} | |
}); | |
return matches[0].formatted_address; | |
} | |
function setHourlyData(hourly) { | |
var hours = hourly.slice(0, 10); | |
for (var i = 0; i < hours.length; i++) { | |
var time = '<div class="hourly-time">' + unixToTimestamp(hours[i].time) + '</div>'; | |
weatherState = hours[i].icon; | |
var icon = '<i class="hourly-icon wi ' + getWeatherIcon(hours[i].icon) + '" />'; | |
var summary = '<div>' + hours[i].summary + '</div>'; | |
var tempF = '<div class="farenheit">' + Math.round(hours[i].temperature) + '°F</div>'; | |
var tempC = '<div class="celsius">' + fToC(hours[i].temperature) + '°C</div>'; | |
var humidity = '<div>' + Math.round(100 * hours[i].humidity) + '%</div>'; | |
$('.hour-container:nth-child(' + (i + 1) + ')').html(time + icon + summary + tempF + tempC + humidity); | |
} | |
} | |
function unixToTimestamp(unix) { | |
var date = new Date(unix * 1000); | |
var hours = date.getHours(); | |
var minutes = "0" + date.getMinutes(); | |
return hours + ':' + minutes.substr(-2); | |
} | |
function fToC(temp) { | |
return Math.round((temp - 32) * (5 / 9)); | |
} | |
function setWeather(icon) { | |
var hour = new Date().getHours(); | |
if (hour < 7 || hour > 19) { | |
showNight(); | |
} else { | |
showDay(); | |
} | |
weatherState = icon; | |
addPrecipitation(icon); | |
switch(icon) { | |
case 'clear-day': | |
$('#sun-moon-container').fadeIn(500); | |
break; | |
case 'clear-night': | |
$('#sun-moon-container').fadeIn(500); | |
break; | |
case 'rain': | |
addClouds(10, 9); | |
setCloudColor('#999') | |
$('#sun-moon-container').hide(); | |
break; | |
case 'snow': | |
addClouds(10, 9); | |
setCloudColor('#999') | |
$('#sun-moon-container').hide(); | |
break; | |
case 'sleet': | |
addClouds(10, 9); | |
setCloudColor('#999') | |
$('#sun-moon-container').hide(); | |
break; | |
case 'cloudy': | |
addClouds(10, 9); | |
setCloudColor('#FFF'); | |
break; | |
case 'partly-cloudy-day': | |
addClouds(3, 30); | |
setCloudColor('#FFF'); | |
$('#sun-moon-container').fadeIn(500); | |
break; | |
case 'partly-cloudy-night': | |
addClouds(3, 30); | |
setCloudColor('#555') | |
$('#sun-moon-container').hide(); | |
break; | |
default: | |
$('#sun-moon-container').hide(); | |
break; | |
} | |
} | |
function getWeatherIcon(icon) { | |
switch(icon) { | |
case 'clear-day': | |
return 'wi-day-sunny'; | |
case 'clear-night': | |
return 'wi-night-clear'; | |
case 'rain': | |
return 'wi-rain'; | |
case 'snow': | |
return 'wi-snow'; | |
case 'sleet': | |
return 'wi-sleet'; | |
case 'wind': | |
return 'wi-windy'; | |
case 'cloudy': | |
return 'wi-cloudy'; | |
case 'fog': | |
return 'wi-fog'; | |
case 'partly-cloudy-day': | |
return 'wi-day-cloudy'; | |
case 'partly-cloudy-night': | |
return 'wi-night-alt-cloudy'; | |
default: | |
return ''; | |
} | |
} | |
function showDay() { | |
$('body').css('color', '#333') | |
$('body').css('background-color', 'green') | |
$('#sun-moon-container').html('<img src="https://res.cloudinary.com/dvr87tqip/image/upload/v1466806859/sun.svg" height=300px />') | |
$('#sun-moon-container').css('right', '-100px') | |
$('#sun-moon-container').css('top', '-100px') | |
$('#sky-container').css('background', '#c9dbe9') | |
$('#sky-container').css('background', '-webkit-linear-gradient(top, #c9dbe9 20%, #fff 100%)') | |
$('#sky-container').css('background', '-linear-gradient(top, #c9dbe9 20%, #fff 100%)') | |
$('#sky-container').css('background', '-moz-linear-gradient(top, #c9dbe9 20%, #fff 100%)') | |
$('#landscape-curve > path').css('fill', '#fff') | |
$('#page-container').css('background-color', 'green') | |
$('#landscape-container').css('background-color', 'green') | |
$('#landscape-curve').css('background-color', 'green') | |
} | |
function showNight() { | |
$('.cloud').css('color', '#888'); | |
$('body').css('color', '#FEFEFA') | |
$('body').css('background-color', '#2F4F4F') | |
$('#sun-moon-container').html('<img src="https://res.cloudinary.com/dvr87tqip/image/upload/v1466773790/moon_ck199s.svg" height=300px />'); | |
$('#sun-moon-container').css('right', '-100px'); | |
$('#sun-moon-container').css('top', '-100px') ; | |
$('#sky-container').css('background-color', '#0D0D2A'); | |
$('#landscape-curve > path').css('fill', '#0D0D2A'); | |
$('#page-container').css('background-color', '#2F4F4F'); | |
$('#landscape-container').css('background-color', '#2F4F4F'); | |
$('#landscape-curve').css('background-color', '#2F4F4F'); | |
} | |
function addPrecipitation(icon) { | |
switch(icon) { | |
case 'rain': | |
createRain(200); | |
break; | |
case 'snow': | |
createRain(100); | |
break; | |
case 'sleet': | |
createRain(100); | |
break; | |
default: | |
$('.drop').remove(); | |
break; | |
} | |
} | |
function addClouds(count, spacing) { | |
$('.cloud').remove(); | |
for (var i = 0; i < count; i++) { | |
var id = 'cloud-' + i; | |
var cloud = '<div id="' + id + '" class="cloud" ></div>' | |
$('#cloud-container').append(cloud); | |
var num = Math.floor(Math.random() * 10) + 1; | |
num *= Math.floor(Math.random() * 2) == 1 ? 1 : -1; | |
$('#' + id).css('right', i * spacing + (num / 5) + '%'); | |
$('#' + id).css('top', 2 * num); | |
test = 5; | |
} | |
} | |
function setCloudColor(color) { | |
$('.cloud').css('background', color); | |
$('.cloud').append('<style>.cloud:after{background: ' + color + ';}</style>'); | |
$('.cloud').append('<style>.cloud:before{background: ' + color + ';}</style>'); | |
} | |
// function to generate a random number range. | |
function randRange( minNum, maxNum) { | |
return (Math.floor(Math.random() * (maxNum - minNum + 1)) + minNum); | |
} | |
// function to generate drops | |
// rain inspired by https://codepen.io/alemesre/pen/hAxGg | |
function createRain(drops) { | |
$('.drop').remove(); | |
var width = $('body').width(); | |
var height = $('#sky-container').height() + 100; | |
for( i = 1; i <= drops; i++) { | |
var dropLeft = randRange(0, width); | |
var dropTop = randRange(0, height); | |
$('#precipitation-container').append('<div class="drop" id="drop'+i+'"></div>'); | |
$('#drop'+i).css('left',dropLeft); | |
$('#drop'+i).css('top',dropTop); | |
} | |
} |
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
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.2.2/jquery.min.js"></script> |
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
#page-container { | |
display: none; | |
} | |
#location { | |
font-size: 25px; | |
text-align: center; | |
} | |
#loader { | |
width: 100%; | |
text-align: center; | |
margin-top: 20%; | |
font-size: 40px; | |
} | |
#warning { | |
color: red; | |
font-size: 28px; | |
text-align: center; | |
} | |
#main-container { | |
z-index: 2; | |
position: absolute; | |
width: 100%; | |
font-size: 24px; | |
text-align: center; | |
} | |
.main-icon { | |
margin-top: 5px; | |
height: 25px; | |
zoom: 2.5; | |
-moz-transform: scale(2.5); | |
-webkit-transition: -webkit-transform .8s ease-in-out; | |
transition: transform .8s ease-in-out; | |
} | |
.main-icon:hover { | |
-webkit-transform: rotate(30deg); | |
transform: rotate(30deg); | |
} | |
#temp-toggle { | |
z-index: 3; | |
-webkit-touch-callout: none; /* iOS Safari */ | |
-webkit-user-select: none; /* Chrome/Safari/Opera */ | |
-khtml-user-select: none; /* Konqueror */ | |
-moz-user-select: none; /* Firefox */ | |
-ms-user-select: none; /* Internet Explorer/Edge */ | |
user-select: none; | |
-webkit-box-shadow: 0px 0px 5px 0px rgba(50, 50, 50, 0.75); | |
-moz-box-shadow: 0px 0px 5px 0px rgba(50, 50, 50, 0.75); | |
box-shadow: 0px 0px 5px 0px rgba(50, 50, 50, 0.75); | |
padding-top: 2px; | |
color: #333333; | |
text-align: center; | |
font-size: 20px; | |
font-weight: bold; | |
border: 4px solid #333333; | |
position: absolute; | |
margin: 10px 0px 0px 10px; | |
height: 40px; | |
width: 135px; | |
border-radius: 2px; | |
transition: background-color 1.5s; | |
transition: color 1s; | |
} | |
#temp-toggle:hover { | |
background-color: #333333; | |
color: white; | |
transition: background-color 1s; | |
transition: color 0.75s; | |
} | |
.celsius { | |
display: none; | |
} | |
#hourly-label { | |
font-size: 24px; | |
width: 100%; | |
text-align: center; | |
margin-bottom: 5px; | |
} | |
.hour-container { | |
text-align: center; | |
width: 150px; | |
} | |
.hourly-time { | |
margin-top: 4px; | |
font-weight: bold; | |
font-size: 18px; | |
} | |
.hourly-icon { | |
margin: 5px 0px 5px 0px; | |
zoom: 2.5; | |
-moz-transform: scale(2.5); | |
-webkit-transition: -webkit-transform .8s ease-in-out; | |
transition: transform .8s ease-in-out; | |
} | |
.hourly-icon:hover { | |
-webkit-transform: rotate(30deg); | |
transform: rotate(30deg); | |
} | |
.row-centered { | |
text-align:center; | |
} | |
.col-centered { | |
display:inline-block; | |
float:none; | |
margin-right:-4px; | |
} | |
/** Weather Visualization **/ | |
body { | |
height: 100vh; | |
} | |
#sun-moon-container { | |
z-index: 0; | |
position: fixed; | |
} | |
#preciptiation-container { | |
z-index: 1; | |
position: absolute; | |
height: 400px; | |
width: 100%; | |
} | |
/** | |
Rain inspired by https://codepen.io/alemesre/pen/hAxGg | |
*/ | |
.drop { | |
background: -webkit-gradient(linear,0% 0%,0% 100%, from(rgba(13,52,58,1) ), to(rgba(255,255,255,0.6)) ); | |
background: -moz-linear-gradient(top, rgba(13,52,58,1) 0%, rgba(255,255,255,.6) 100%); | |
width:1px; | |
height:20px; | |
position: absolute; | |
bottom:200px; | |
-webkit-animation: fall .85s ease-out infinite; | |
-moz-animation: fall .85s ease-out infinite; | |
} | |
#cloud-container { | |
z-index: 1; | |
position: fixed; | |
} | |
.cloud { | |
width: 200px; | |
height: 60px; | |
background: #fff; | |
border-radius: 200px; | |
-moz-border-radius: 200px; | |
-webkit-border-radius: 200px; | |
position: fixed; | |
} | |
.cloud:before, .cloud:after { | |
content: ''; | |
position: absolute; | |
background: #fff; | |
width: 100px; height: 80px; | |
position: absolute; top: -15px; left: 10px; | |
border-radius: 100px; | |
-moz-border-radius: 100px; | |
-webkit-border-radius: 100px; | |
-webkit-transform: rotate(30deg); | |
transform: rotate(30deg); | |
-moz-transform: rotate(30deg); | |
} | |
.cloud:after { | |
width: 120px; height: 120px; | |
top: -55px; left: auto; right: 15px; | |
} | |
#sky-container { | |
min-height: 185px; | |
padding-top: 50px; | |
} | |
#landscape-container { | |
margin-top: -50px; | |
} |
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
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" /> | |
<link href="https://cdnjs.cloudflare.com/ajax/libs/weather-icons/2.0.9/css/weather-icons-wind.min.css" rel="stylesheet" /> | |
<link href="https://cdnjs.cloudflare.com/ajax/libs/weather-icons/2.0.9/css/weather-icons.min.css" rel="stylesheet" /> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment