mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-19 03:32:21 +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