mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-18 19:21:34 +08:00
Weather demo
This commit is contained in:
35
ionic/components/app/test/weather/flickr.js
Normal file
35
ionic/components/app/test/weather/flickr.js
Normal file
@ -0,0 +1,35 @@
|
||||
import {Http} from 'ionic/net/http';
|
||||
|
||||
let FLICKR_API_KEY = '504fd7414f6275eb5b657ddbfba80a2c';
|
||||
|
||||
let baseUrl = 'https://api.flickr.com/services/rest/';
|
||||
|
||||
export class Flickr {
|
||||
constructor() {
|
||||
|
||||
/*
|
||||
var flickrSearch = $resource(baseUrl, {
|
||||
method: 'flickr.groups.pools.getPhotos',
|
||||
group_id: '1463451@N25',
|
||||
safe_search: 1,
|
||||
jsoncallback: 'JSON_CALLBACK',
|
||||
api_key: FLICKR_API_KEY,
|
||||
format: 'json'
|
||||
}, {
|
||||
get: {
|
||||
method: 'JSONP'
|
||||
}
|
||||
});
|
||||
*/
|
||||
}
|
||||
|
||||
static search(tags, lat, lng) {
|
||||
return new Promise((resolve, reject) => {
|
||||
Http.get(baseUrl + '?method=flickr.groups.pools.getPhotos&group_id=1463451@N25&safe_search=1&api_key=' + FLICKR_API_KEY + '&format=json&tags=' + tags + '&lat=' + lat + '&lng=' + lng).then((val) => {
|
||||
resolve(val);
|
||||
}, (err) => {
|
||||
reject(httpResponse);
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
56
ionic/components/app/test/weather/geo.js
Normal file
56
ionic/components/app/test/weather/geo.js
Normal file
@ -0,0 +1,56 @@
|
||||
export class Geo {
|
||||
static reverseGeocode(lat, lng) {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
let geocoder = new google.maps.Geocoder();
|
||||
|
||||
geocoder.geocode({
|
||||
'latLng': new google.maps.LatLng(lat, lng)
|
||||
}, (results, status) => {
|
||||
|
||||
if (status == google.maps.GeocoderStatus.OK) {
|
||||
|
||||
console.log('Reverse', results);
|
||||
|
||||
if(results.length > 1) {
|
||||
var r = results[1];
|
||||
var a, types;
|
||||
var parts = [];
|
||||
var foundLocality = false;
|
||||
var foundState = false;
|
||||
|
||||
for(var i = 0; i < r.address_components.length; i++) {
|
||||
a = r.address_components[i];
|
||||
types = a.types;
|
||||
for(var j = 0; j < types.length; j++) {
|
||||
if(!foundLocality && types[j] == 'locality') {
|
||||
foundLocality = true;
|
||||
parts.push(a.long_name);
|
||||
} else if(!foundState && types[j] == 'administrative_area_level_1') {
|
||||
foundState = true;
|
||||
parts.push(a.short_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log('Reverse', parts);
|
||||
resolve(parts.join(', '));
|
||||
}
|
||||
} else {
|
||||
console.log('reverse fail', results, status);
|
||||
reject(results);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
static getLocation() {
|
||||
return new Promise((resolve, reject) => {
|
||||
navigator.geolocation.getCurrentPosition((position) => {
|
||||
resolve(position);
|
||||
}, (error) => {
|
||||
reject(error);
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
123
ionic/components/app/test/weather/index.js
Normal file
123
ionic/components/app/test/weather/index.js
Normal file
@ -0,0 +1,123 @@
|
||||
import {Component, Directive} from 'angular2/src/core/annotations_impl/annotations';
|
||||
import {FormBuilder, Control, ControlGroup, Validators, formDirectives} from 'angular2/forms';
|
||||
|
||||
import {IonicView, Animation, Modal, NavController, NavParams, IonicComponent} from 'ionic/ionic';
|
||||
|
||||
import {Geo} from './geo';
|
||||
import {Weather} from './weather';
|
||||
import {Flickr} from './flickr';
|
||||
|
||||
console.log('Imported', Geo, Weather, Flickr);
|
||||
|
||||
@Component({
|
||||
selector: 'ion-app',
|
||||
appInjector: [Modal]
|
||||
})
|
||||
@IonicView({
|
||||
templateUrl: 'main.html'
|
||||
})
|
||||
class WeatherApp {
|
||||
constructor(Modal: Modal) {
|
||||
this.Modal = Modal;
|
||||
|
||||
this.currentLocationString = 'Madison, WI';
|
||||
this.current = {
|
||||
local_tz_short: 'CDT'
|
||||
};
|
||||
|
||||
this.activeBgImageIndex = 0;
|
||||
|
||||
/*
|
||||
$ionicPlatform.ready(function() {
|
||||
// Hide the status bar
|
||||
if(window.StatusBar) {
|
||||
StatusBar.hide();
|
||||
}
|
||||
});
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
onInit() {
|
||||
this.refreshData();
|
||||
}
|
||||
|
||||
showSettings() {
|
||||
this.Modal.show(SettingsModal).then((settingsModal) => {
|
||||
this.settingsModal = settingsModal;
|
||||
});
|
||||
}
|
||||
|
||||
getBackgroundImage(lat, lng, locString) {
|
||||
Flickr.search(locString, lat, lng).then((resp) => {
|
||||
let photos = resp.photos;
|
||||
if(photos.photo.length) {
|
||||
this.bgImages = photos.photo;
|
||||
this.cycleBgImages();
|
||||
}
|
||||
}, (error) => {
|
||||
console.error('Unable to get Flickr images', error);
|
||||
});
|
||||
}
|
||||
|
||||
getCurrent(lat, lng, locString) {
|
||||
Weather.getAtLocation(lat, lng).then((resp) => {
|
||||
this.current = resp.data;
|
||||
console.log('GOT CURRENT', this.current);
|
||||
}, (error) => {
|
||||
alert('Unable to get current conditions');
|
||||
console.error(error);
|
||||
});
|
||||
}
|
||||
|
||||
cycleBgImages() {
|
||||
setTimeout(() => {
|
||||
if(this.bgImages) {
|
||||
this.activeBgImage = this.bgImages[this.activeBgImageIndex++ % this.bgImages.length];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
refreshData() {
|
||||
Geo.getLocation().then((position) => {
|
||||
let lat = position.coords.latitude;
|
||||
let lng = position.coords.longitude;
|
||||
|
||||
Geo.reverseGeocode(lat, lng).then((locString) => {
|
||||
this.currentLocationString = locString;
|
||||
this.getBackgroundImage(lat, lng, locString);
|
||||
});
|
||||
|
||||
this.getCurrent(lat, lng);
|
||||
}, (error) => {
|
||||
alert('Unable to get current location: ' + error);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
.controller('SettingsCtrl', function($scope, Settings) {
|
||||
$scope.settings = Settings.getSettings();
|
||||
|
||||
// Watch deeply for settings changes, and save them
|
||||
// if necessary
|
||||
$scope.$watch('settings', function(v) {
|
||||
Settings.save();
|
||||
}, true);
|
||||
|
||||
$scope.closeSettings = function() {
|
||||
$scope.modal.hide();
|
||||
};
|
||||
|
||||
});
|
||||
*/
|
||||
|
||||
@IonicComponent(Modal)
|
||||
@IonicView({
|
||||
template: '<ion-view id="settings-modal"><ion-content padding><button primary (click)="close()">Close</button></ion-content></ion-view>'
|
||||
})
|
||||
export class SettingsModal extends Modal {}
|
||||
|
||||
export function main(ionicBootstrap) {
|
||||
ionicBootstrap(WeatherApp);
|
||||
}
|
18
ionic/components/app/test/weather/main.html
Normal file
18
ionic/components/app/test/weather/main.html
Normal file
@ -0,0 +1,18 @@
|
||||
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
|
||||
<link rel="stylesheet" href="style.css">
|
||||
<ion-view>
|
||||
<ion-toolbar id="header" class="no-border">
|
||||
<ion-title>
|
||||
<span class="city"><i id="city-nav-icon" class="icon ion-navigate"></i> {{currentLocationString}}</span><br>
|
||||
<current-time localtz="current.local_tz_short"></current-time>
|
||||
</ion-title>
|
||||
<button (^click)="showSettings()" class="toolbar-secondary-item"><i class="icon ion-ios-gear"></i></button>
|
||||
</ion-toolbar>
|
||||
|
||||
<ion-content>
|
||||
<div id="main-content">
|
||||
<current-weather></current-weather>
|
||||
<forecast></forecast>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-view>
|
240
ionic/components/app/test/weather/style.css
Normal file
240
ionic/components/app/test/weather/style.css
Normal file
@ -0,0 +1,240 @@
|
||||
body {
|
||||
text-shadow: 1px 1px 0px rgba(0,0,0,0.5);
|
||||
background-color: black;
|
||||
}
|
||||
#wrapper {
|
||||
background-color: black;
|
||||
}
|
||||
#scroller {
|
||||
}
|
||||
.bg-image {
|
||||
position: fixed;
|
||||
width: 120%;
|
||||
height: 120%;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
.bg-fade > .ng-enter {
|
||||
opacity: 0;
|
||||
-webkit-transition: opacity 2s ease-in-out;
|
||||
}
|
||||
.bg-fade > .ng-enter-active {
|
||||
opacity: 1;
|
||||
}
|
||||
.bg-fade > .ng-leave {
|
||||
opacity: 1;
|
||||
-webkit-transition: opacity 2s ease-in-out;
|
||||
}
|
||||
.bg-fade > .ng-leave-active {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.wunderground-logo {
|
||||
width: 100px;
|
||||
height: 14px;
|
||||
background: url('../img/wunderground.png') no-repeat transparent;
|
||||
}
|
||||
|
||||
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
|
||||
.wunderground-logo {
|
||||
background: url('../img/wunderground@2x.png') no-repeat transparent;
|
||||
background-size: 100px 14px;
|
||||
}
|
||||
}
|
||||
|
||||
h1,h2,h3,h4,h5 {
|
||||
color: #fff;
|
||||
font-weight: 300;
|
||||
}
|
||||
|
||||
#main-content {
|
||||
color: #fff;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.ion-ios7-sunny-outline {
|
||||
color: yellow;
|
||||
}
|
||||
|
||||
.ionic-refresher-content {
|
||||
color: rgb(255,255,255) !important;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
/**
|
||||
* Header
|
||||
*/
|
||||
#header {
|
||||
background-color: transparent !important;
|
||||
height: 44px;
|
||||
}
|
||||
#header > * {
|
||||
margin-top: 0;
|
||||
}
|
||||
#header .title {
|
||||
font-size: 12px;
|
||||
line-height: 20px;
|
||||
margin-top: 4px;
|
||||
}
|
||||
#header .title .city {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
#city-nav-icon {
|
||||
font-size: 11px;
|
||||
margin-right: 2px;
|
||||
}
|
||||
|
||||
.scroll-refresher {
|
||||
overflow: visible;
|
||||
}
|
||||
.ionic-refresher-content {
|
||||
background-color: rgba(0,0,0,0.4);
|
||||
height: 400px;
|
||||
bottom: 0;
|
||||
}
|
||||
.ionic-refresher-content i {
|
||||
margin-top: 360px;
|
||||
}
|
||||
/**
|
||||
* Current weather
|
||||
*/
|
||||
|
||||
#current-weather {
|
||||
height: 180px;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
#current-weather > * {
|
||||
color: #fff;
|
||||
}
|
||||
#current-weather .current-temp {
|
||||
font-size: 100px;
|
||||
font-weight: 100;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
line-height: 80px;
|
||||
}
|
||||
|
||||
|
||||
#current-icon {
|
||||
font-size: 42px;
|
||||
vertical-align: middle;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
#temp-hi, #temp-lo { display: inline-block; }
|
||||
#temp-lo {
|
||||
margin-left: 10px;
|
||||
}
|
||||
|
||||
/**
|
||||
* Forecast and details
|
||||
*/
|
||||
.weather-box {
|
||||
background-color: rgba(0,0,0,0.2);
|
||||
padding: 9px;
|
||||
margin: 10px 0px;
|
||||
color: rgba(255,255,255,0.9);
|
||||
}
|
||||
|
||||
.weather-box .title {
|
||||
color: rgba(255,255,255,0.9);
|
||||
font-weight: normal;
|
||||
margin: 0;
|
||||
padding-bottom: 5px;
|
||||
border-bottom: 1px solid #fff;
|
||||
}
|
||||
|
||||
|
||||
.weather-box .row {
|
||||
border-bottom: 1px dotted rgba(255,255,255,0.3);
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
.weather-box .col {
|
||||
text-align: center;
|
||||
}
|
||||
.weather-box .col:first-child {
|
||||
text-align: left;
|
||||
}
|
||||
.weather-box .col:last-child {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.weather-box span {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.weather-box .icon {
|
||||
font-size: 42px;
|
||||
line-height: 24px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.temp-high {
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
text-align: right;
|
||||
}
|
||||
.temp-low {
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
text-align: right;
|
||||
color: #4a87ee;
|
||||
}
|
||||
|
||||
|
||||
.no-header {
|
||||
top: 0 !important;
|
||||
}
|
||||
|
||||
#forecast-scroll {
|
||||
margin: 10px 0px;
|
||||
}
|
||||
#hourly-forecast {
|
||||
width: 2250px;
|
||||
height: 70px;
|
||||
}
|
||||
.hourly-hour {
|
||||
display: inline-block;
|
||||
margin-right: 10px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#forecast .credit {
|
||||
float: right;
|
||||
margin-top: 4px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
#forecast .credit a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Settings modal
|
||||
*/
|
||||
|
||||
#settings-modal {
|
||||
background-color: rgba(0,0,0,0.8);
|
||||
}
|
||||
|
||||
#settings-modal .item {
|
||||
background-color: rgba(0,0,0,0.9);
|
||||
border: none;
|
||||
color: #fff;
|
||||
}
|
||||
#settings-modal .input-label {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
|
||||
ion-view {
|
||||
background-color: black !important;
|
||||
}
|
||||
ion-content {
|
||||
background-color: black !important;
|
||||
}
|
||||
#header {
|
||||
background: transparent;
|
||||
color: #fff;
|
||||
}
|
12
ionic/components/app/test/weather/weather.js
Normal file
12
ionic/components/app/test/weather/weather.js
Normal file
@ -0,0 +1,12 @@
|
||||
import {Http} from 'ionic/net/http';
|
||||
|
||||
let WUNDERGROUND_API_KEY = '1cc2d3de40fa5af0';
|
||||
|
||||
let FORECASTIO_KEY = '4cd3c5673825a361eb5ce108103ee84a';
|
||||
|
||||
export class Weather {
|
||||
static getAtLocation(lat, lng) {
|
||||
let url = 'https://api.forecast.io/forecast/' + FORECASTIO_KEY + '/';
|
||||
return Http.get(url + lat + ',' + lng);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user