Мы познакомились с ней десятого октября 2013 год. Сегодня у нас 264 дня. Волей случайностей такая уж завелась у нас традиция — отмечать не круглые даты отношений. Мы покупаем вино на 99 день, устраивали фуршет на 111, а про 123-й рассказывать неприлично. Во всяком случае это уже вошло в хорошую традицию и мы её очень ценим.
Это пост о том, как я сделал довольно милое приложение с фоточками и котятами.
Немного входных данных. У меня нет аккаунта разработчика Apple, потому это будет псевдо-приложение под iPhone (кто не понимает о чем я прочтете дальше). У меня имеется пара часов свободного времени, два аккаунта в инстаграме (её и мой) знания хорошие знания html, js, css, лишние 100 рублей, и её безграничная любовь к котятам.
У неё iPhone 5s потому писаться и верстаться всё будет под конкретную модель, что облегчит задачу.
Для начала я пошел и зарегистрировал за 99 руб домен отношенияэтоад.рф на котором всё действо и будет происходить. Цель приложения — автоматически при открытии подсчитывать и отображать сегодняшний день. Идея навеяна одним из моих любимых фильмов «500 дней лета».
Написать скрипт отсчета дней от определенной даты до сегодняшнего дня совершенно не сложно и в сети подобных полно. Дабы не заморачиваться, взял один из таких за основу и подогнал под свои непосредственные нужды.
<SCRIPT LANGUAGE="JavaScript">
<!--
function GoodYear (year) {
return (year<1900 ? year+1900 : year);
}
function LeapYear (year) {
if ((year%4==0) && (year%100!=0) || (year%400==0)) return true;
else return false;
}
function KolDays (d1,m1,d2,m2,y) {
var i,s;
var mondays= new Array (31,28,31,30,31,30,31,31,30,31,30,31);
if (LeapYear (y)==true) mondays[1]=29;
if (m1==m2) s=d2-d1;
else {
s=mondays[m1-1]-d1+1;
for (i=m1+1;i<m2;i++) s+=mondays[i-1];
s+=(d2-1);
}
return s;
}
function DaysBetween (day1,mon1,year1,day2,mon2,year2) {
var i,f;
if (year1==year2) f=KolDays (day1,mon1,day2,mon2,year1);
else {
f=KolDays (day1,mon1,31,12,year1)+1;
for (i=year1+1; i<year2; i++) {
f+=365;
if (LeapYear (i)) f++;
}
f+=(KolDays(1,1,day2,mon2,year2));
}
return f;
}
function WeekDay (day,month,year) {
if (month<3) month+=10; else month-=2;
if (month>10) year--;
var cent=Math.floor(year/100);
year %= 100;
var dday= Math.floor(2.6*month-0.2)+day+year+Math.floor(year/4)+Math.floor(cent/4)-2*cent;
dday= Math.floor((dday+777)%7);
return ((dday==0) ? 7 : dday);
}
function PutInForm (d) {
if ( ((d%100) > 9) && ((d%100) < 21) ) s="";
else if ((d % 10) ==1) s="";
else if (((d % 10) >1) && ((d % 10)<5)) s="";
else s="";
document.getElementById("life").innerHTML = '('+ d + ')'+''+s;;
}
function InitForm() {
var wkd= new Array ("Пн","Вт","Ср","Чт","Пт","Сб","Вс");
var today = new Date();
d=today.getDate();
m=today.getMonth();
y=GoodYear(today.getYear());
m++;
t=DaysBetween (24,10,2013,d,m,y);
PutInForm (t);
w=WeekDay(d,m,y);
document.Q.wk2.value=wkd[w-1];
First=true;
}
function CorrectDate (d,m,y) {
var mondays= new Array (31,28,31,30,31,30,31,31,30,31,30,31);
if (y<1) {
return false;
}
if (LeapYear (y)==true) mondays[1]=29;
if ((d<1) || (d>mondays[m-1])) {
return false;
}
return true;
}
function Validate () {
var wkd= new Array ("Пн","Вт","Ср","Чт","Пт","Сб","Вс");
var d1,m1,y1,d2,m2,y2,t,d,w;
d1=parseInt(document.Q.day1.value);
m1=document.Q.month1.selectedIndex+1;
y1=parseInt(document.Q.year1.value);
d2=parseInt(document.Q.day2.value);
m2=document.Q.month2.selectedIndex+1;
y2=parseInt(document.Q.year2.value);
if ( (isNaN (d1)==true) || (isNaN (d2)==true) || (isNaN (y1)==true) || (isNaN (y2)==true)) {
window.alert ("Введен недопустимый день или год! Пожалуйста, исправьте данные в форме.");
return false;
}
t=CorrectDate(d1,m1,y1);
if (t==false) {
window.alert ("Введена недопустимая начальная дата! Пожалуйста, исправьте данные в форме.");
return false;
}
t=CorrectDate(d2,m2,y2);
if (t==false) {
window.alert ("Введена недопустимая конечная дата! Пожалуйста, исправьте данные в форме.");
return false;
}
if ( (y1>y2) || (y1==y2) && ((m1>m2)||(m1==m2)&&(d1>d2)) ) {
window.alert ("Начальная дата больше конечной! Пожалуйста, исправьте данные в форме.");
return false;
}
d=DaysBetween (d1,m1,y1,d2,m2,y2);
PutInForm(d);
w=WeekDay(d1,m1,y1);
document.Q.wk1.value=wkd[w-1];
w=WeekDay(d2,m2,y2);
document.Q.wk2.value=wkd[w-1];
return true;
}
// -->
</SCRIPT>
Дальше я хочу что б количество дней отображалось на фоне случайно фотографии из моего и ее инстаграма. API у них не особенно сложный, но для удобства я пользуюсь очень удобной библиотекой instafeedjs.com. Подключил библиотеку к документу, добавил в тело
<div class="feed" id="instafeed"></div>
Пользоваться библиотекой, еще раз, очень удобно. Допустим если мы хотим вывести поток фоток с тегом #love:
<script type="text/javascript">
var feed = new Instafeed({
get: 'tagged',
tagName: 'love',
clientId: 'YOUR_CLIENT_ID'
});
feed.run();
</script>
На странице instafeedjs есть ёмкое, но достаточное описание. CLIENT_ID можно получить в девелоп-разделе инстаграма. Нужно будет создать (зарегистрировать) новую программу и сервис выдаст все необходимые вам ключи.
Я решил, что мне нужно подключиться к аккаунту и выбрать случайным образом одну из, скажем, 11 последних снимков. Мой скрипт выглядит вот так:
var feed = new Instafeed({
get: 'user',
userId: 30922527,
clientId: '445c6ebabb324139a654630c0d2ed008d9076',
accessToken: '30922527.467ede5.6af64d56d9f34762a33535f349db5fbd7096',
resolution: 'standard_resolution',
sortBy: 'random',
links:'false',
limit:'11',
template: '<img class="front" src="{{image}}" />'
});
feed.run();
get: 'user', — запрос к юзеру. userId: 30922527, — к какому конкретно. resolution: 'standard_resolution', — это размер выдаваемых изображений. Инстаграм предлагает три варианта:
thumbnail 150x150
low_resolution 306x306
standard_resolution 612x612
clientId нам уже известен, а accessToken предварительно залогиневшись, можно получить на сайте того же instafeedjs (внизу есть ссылка).
С помощью links:'false', отключаем залинковывание снимков, ведущих в аккаунт.
sortBy: 'random', и limit:'11', вот здесь загвоздка произошла. Мне бы хотелось выводить каждый раз случайный снимок и здесь работает sortBy: 'random',, но для этого их сначала нужно прогрузить limit:'11',, иначе, установив лимит загрузок единичку — он и сортировать будет только среди одного единственного снимка. Все в общем то и логично, но покопаться в коде библиотеки мне моя лень к сожалению пока не позволила. Кстати говоря, максимум можно загружать 60 снимков этим параметром.
т.к. мне нужен всего один а не целая лента, я наложил снимки один на другой и выровнял по центру страницы таким css:
.feed{
width:912px;
height:912px;
position:absolute;
left:40%;
top:40%;
margin:-345px 0 0 -345px;
}
.front{
width:912px;
height:912px;
z-index:0;position:absolute;
}
Вот такой костыль, дико извиняюсь.
Хочу здесь заметить что открывать это предполагалось на конкретном устройстве, а в данном случае iPhone 5s, потому были заранее известны размеры и оставалось подогнать всю конструкцию под них с помощью CSS. С десктопа, верстка скорее всего повалится, но это подправить и адаптировать при необходимости всего лишь дело техники.
Поверх изображения накладываем результат выполнения нашего скрипта, высчитывающее часы, которые некоторые счастливые все-таки наблюдают.
.life{
position:absolute;
left:50%;
top:50%;
margin:-150 0 0 -190;
text-shadow: 1px 1px 2px black, 0 0 1em black;
font: Georgia;
font-size: 210px;
color: #f5f5f5;
}
А теперь то, чего вы так долго ждали — котята.
По одному котенку мы посадим на верхний край загруженного снимка
.cat{
position:absolute;
left:50%;
top:50%;
margin:-635 0 0 170;
text-shadow: 1px 1px 2px black, 0 0 1em black;
font: Georgia;
font-size: 210px;
color: #f5f5f5;
}
И будем выводить каждый раз разного
function rand(min, max){
return (max-min)*Math.random()+min
}
var r=Math.round(rand(1,14));
document.write('<div class="cat"><a href=><img id="cat" src="cats/'+r+'.png "/></a></div>')
К тому же, котенок-кнопка обновляет страницу перегружая следующий случайный рисунок.
Теперь всё готово для сборки псевдо-приложения под iPhone.
Заливаем все это на сервер, заходим с мобильного браузера Safari на делегированный к этому моменту домен отношенияэтоад.рф видим то, что мы получили:
Теперь, пользуясь возможностями мобильного Safari помещаем иконку сайта на экран домой. Это делается в меню шаринга:
Теперь у нас на домашнем экране среди приложений присутствует ничем не отличающийся от остальных ярлычок нашего псевдо-апп.
Тут я должен рассказать про создание иконки. Есть некоторая спецификация у компании Apple, т.к. иконку, поддерживаемую iOs можно сделать для любого сайта, достаточно прописать:
<meta name="apple-mobile-web-app-capable" content="yes" />
<link rel="apple-touch-icon" href="touch-icon-iphone.png">
<link rel="apple-touch-icon" sizes="76x76" href="touch-icon-ipad.png">
<link rel="apple-touch-icon" sizes="120x120" href="touch-icon-iphone-retina.png">
<link rel="apple-touch-icon" sizes="152x152" href="touch-icon-ipad-retina.png">
Здесь, по названию файлов понятно для каких устройств они предназначены и каких размеров должны быть. Остается лишь залить соответствующие пиктограммы.
И ещё один важный момент. Пропишите в самом начале
<meta name="apple-mobile-web-app-capable" content="yes" />
Этот код избавит нас от юзер-бара снизу и строки ввода адреса вверху, сделав страницу более «приложение-похожее».
Что в итоге:
Маше эта штука очень понравилась. Ну и я рад.
Должен сказать, что несложно было бы модернизировать и показывать не сколько дней прошло а сколько дней прошло на момент снятого фото (в api можно вытянуть дату снимка) получится забавное приложение для любителей понастольгировать например. Да и инстаграм использовать необязательно. Куда больше фотоархивы хранятся у людей на других сервисах. Тут уж вопрос цели.
Исходники: прилагаются
Автор: heroino