
Дадено на ограничените способности на хостингот од wordpress.com, со овој блог пост (и затемнетиот дизајн) се приклучувам во протестот.

Дадено на ограничените способности на хостингот од wordpress.com, со овој блог пост (и затемнетиот дизајн) се приклучувам во протестот.
Во овој блог пост следи анализа на кодот на Skycons. Тоа е мала JavaScript библиотека која црта анимирани икони за временските состојби, користејќи го HTML5 <canvas> тагот. Се користи во одличниот сервис Forecast.
Кога ќе завршите со читање ќе знаете како се пишува една JS библиотека (притоа не jQuery или node/AMD/CommonJS библиотека, туку нај нај `нормална` библиотека), ќе знаете која и е структурата и може ќе научите и некоја финтица попат :)
Првин да видиме пример како се користи библиотеката:
Дефинираме канвас:
<canvas id="icon1" width="128" height="128"></canvas>
Ја вклучуваме библиотеката во HTML-от. И потоа во JavaScript кодот создаваме инстанца од Skycons
var icons = new Skycons();
и дефинираме која временска состојба да се исцрта за кој канвас и повикуваме нејзино анимирање.
icons.set("icon1", Skycons.RAIN);
icons.play();

Пример: различните икони кои ги нуди, притоа и во различни големини
Пред да почнеме да го анализираме кодот, може да приметиме дека нуди методи кои се пристапуваат `дирекно` од библиотеката (пр. .RAIN) и методи кои се пристапуваат од инстанцата (пр. .set и .play). Друго за напомена, верзијата на библиотеката која е дел од овој блог пост е со id cec079f77b (нормално е да има и понови/подобрени верзии од библиотеката во иднина). Да почнеме:
Кодот започнува со декларирање на варијабла наречена Skycons
var Skycons;
и притоа не се прави ништо повеќе со неа во овој момент, нема иницијализација. Повеќе за варијабли тука.
Следно, целиот преостанат код се наоѓа во овој блок
(function(global) {
}(this));
и тука ја користиме и варијаблата Skycons. Овој блок се нарекува анонимна самоповикувачка функција, која во нашиот слчај е со аргумент – референца до глобална променлива. Доколку експлицитно не дефинираме – сите функции и варијабли во неа се приватни и нема да може да се пристапат од надвор. Повеќе за анонимни самоповикувачки функции тука, тука и тука.
Во оваа функција прво нешто е изразот “use strict”, што значи дека целата функција се извршува под ‘strict mode’.
"use strict";
Оваа декларација мора да биде на самиот почеток на функцијата. Повеќе за овој мод на работа тука.
Следно се декларираат две варијабли
var requestInterval, cancelInterval;
и после нив има уште една анонимна самоповикувачка функција, во која двете варијабли се употребуваат
(function() {
var raf = global.requestAnimationFrame ||
global.webkitRequestAnimationFrame ||
global.mozRequestAnimationFrame ||
global.oRequestAnimationFrame ||
global.msRequestAnimationFrame ,
caf = global.cancelAnimationFrame ||
global.webkitCancelAnimationFrame ||
global.mozCancelAnimationFrame ||
global.oCancelAnimationFrame ||
global.msCancelAnimationFrame ;
if(raf && caf) {
requestInterval = function(fn, delay) {
var handle = {value: null};
function loop() {
handle.value = raf(loop);
fn();
}
loop();
return handle;
};
cancelInterval = function(handle) {
caf(handle.value);
};
}
else {
requestInterval = setInterval;
cancelInterval = clearInterval;
}
}());
Во функцијава се дефинираат рамките за анимација и за сопирање на анимацијата и се дефинирани на тој начин што би работеле на сите интернет пребарувачи кои ја подржуваат оваа функционалност. Ова се нарекува RequestAnimationFrame shim, повеќе информации има тука и тука.
Следно има код во коментар (скокаме коментари!) и после него се дефинираат неколку константи (кои како и претходните две варијабли, не се достапни надвор од библиотеката пример кога е инстанцирана – бидејќи се во анонимна самоповикувачка функција).
var KEYFRAME = 500,
STROKE = 0.08,
TWO_PI = 2.0 * Math.PI,
TWO_OVER_SQRT_2 = 2.0 / Math.sqrt(2);
После константите, следуваат функциите за цртање. Функциите се дефинирани на тој начин што може да се ре-искористат за повеќе икони наеднаш. Пример во сите случаи кога иконата за времето има облаче, се повикува истата функција за цртање на тој облак. Да ги разгледаме…
Првата е за цртање на круг.
function circle(ctx, x, y, r) {
ctx.beginPath();
ctx.arc(x, y, r, 0, TWO_PI, false);
ctx.fill();
}
Како параметри се праќаат контекстот, точките x, y и радиусот r. ctx е контекстот земен од канвас елементот и тој нуди методи за цртање најразлични геометриски форми и преку него се цртаат иконите. Но, ако цел код е повици кон ctx ќе има многу повторување и нема да биде читлив, па затоа се овие помошни функции. Повеќе за цртање форми во канвас тука и тука.
Следната функција е за цртање на линија.
function line(ctx, ax, ay, bx, by) {
ctx.beginPath();
ctx.moveTo(ax, ay);
ctx.lineTo(bx, by);
ctx.stroke();
}
Јасно е дека преку канвасот се дефинира линија од една до друга точка и се исцртува.
Нема да ги опишувам сите овие помошни методи, само ќе ги излистам, можете во библиотеката да видите кои повици кон кои методи од контекстот се искористени.
function puff(ctx, t, cx, cy, rx, ry, rmin, rmax) {...}
function puffs(ctx, t, cx, cy, rx, ry, rmin, rmax) {...}
function cloud(ctx, t, cx, cy, cw, s, color) {...}
function sun(ctx, t, cx, cy, cw, s, color) {...}
function moon(ctx, t, cx, cy, cw, s, color) {...}
function rain(ctx, t, cx, cy, cw, s, color) {...}
function sleet(ctx, t, cx, cy, cw, s, color) {...}
function snow(ctx, t, cx, cy, cw, s, color) {...}
function fogbank(ctx, t, cx, cy, cw, s, color) {...}
Потоа има помошни матрици со броеви за помош на цртањето на анимацијата на ветрот
var WIND_PATHS = [ ...
],
WIND_OFFSETS = [ ...
];
И уште две помошни функции
function leaf(ctx, t, x, y, cw, s, color) {...}
function swoosh(ctx, t, cx, cy, cw, s, index, total, color) {...}
Сега почнува интересното.
Skycons = function(opts) {
this.list = [];
this.interval = null;
this.color = opts && opts.color ? opts.color : "black";
};
Оваа функција се повикува кога во горниот пример беше извршено new Skyicons(). Опционално може и бојата да се дефинира, пример new Skyicons({"color" : "blue"}). Полето list е листата во која се додаваат канвас елементите при повикување на .add и .set и полето interval се користи во .play и .pause. Повеќе за овие функции кога ќе им дојде редот.
Следни се функциите за временските состојби.
Skycons.CLEAR_DAY = function(ctx, t, color) {
var w = ctx.canvas.width,
h = ctx.canvas.height,
s = Math.min(w, h);
sun(ctx, t, w * 0.5, h * 0.5, s, s * STROKE, color);
};
Во оваа функција се пресметуваат неколку варијабли во зависност од големината на канвасот, и се повикува помошната функција sun.
Следна функција е
Skycons.CLEAR_NIGHT = function(ctx, t, color) {
var w = ctx.canvas.width,
h = ctx.canvas.height,
s = Math.min(w, h);
moon(ctx, t, w * 0.5, h * 0.5, s, s * STROKE, color);
};
која е слична на претходната, но на крај ја повикува помошната функција moon.
Во овој стил, следат функциите
Skycons.CLOUDY = function(ctx, t, color) { ... };
Skycons.RAIN = function(ctx, t, color) { ... };
Skycons.SLEET = function(ctx, t, color) { ... };
Skycons.SNOW = function(ctx, t, color) { ... };
Skycons.WIND = function(ctx, t, color) { ... };
Skycons.FOG = function(ctx, t, color) { ... };
Функциите кои се достапни преку инстанцата на Skyicons (add, set, draw, …) се на ред. Следно во кодот е дефиниран блокот
Skycons.prototype = {
};
И во него прва е функцијата add
add: function(el, draw) {
var obj;
if(typeof el === "string")
el = document.getElementById(el);
obj = {
element: el,
context: el.getContext("2d"),
drawing: draw
};
this.list.push(obj);
this.draw(obj, KEYFRAME);
},
Пред да објаснам што прави функцијата, да размислиме зошто оваа е достапна преку инстанцата на Skycons. Тоа е бидејќи е дефинирана преку prototype. Повеќе за prototypes тука и тука.
Во функцијата се креира празна варијабла obj, со getElementById се зема канвас елементот по името (пр. icon1, повеќе инфо тука), се создава објектот, се додава во листата и се повикува за него draw.
Многу важно тука е назначувањето на draw за полето drawing во создавањето на објектот. Да го земеме примерот icons.add(“icon1″, Skycons.CLEAR_DAY); – во obj за полето drawing ја назначуваме функцијата CLEAR_DAY. Во JavaScript можеме функции да праќаме како аргументи на методи и да ги назначуваме на полиња. Повеќе за тоа тука.
Следна е функцијата set
set: function(el, draw) {
var i;
if(typeof el === "string")
el = document.getElementById(el);
for(i = this.list.length; i--; )
if(this.list[i].element === el) {
this.list[i].drawing = draw;
this.draw(this.list[i], KEYFRAME);
return;
}
this.add(el, draw);
},
Која го прави истото како add, само ако веќе постои објект со такво име на канвасот – го заменува во листата.
Следна функција е remove
remove: function(el) {
var i;
if(typeof el === "string")
el = document.getElementById(el);
for(i = this.list.length; i--; )
if(this.list[i].element === el) {
this.list.splice(i, 1);
return;
}
},
Која отстранува објект од листата.
Потоа е функцијата draw
draw: function(obj, time) {
var canvas = obj.context.canvas;
obj.context.globalCompositeOperation = 'destination-out';
obj.context.fillRect(0, 0, canvas.width, canvas.height);
obj.context.globalCompositeOperation = 'source-over';
obj.drawing(obj.context, time, this.color);
},
Која се повикува во play функцијата, и како параметри прима објект од листата и време. Првин го зема канвасот, го чисти, и за објектот го повикува методот drawing. А drawing е впрочем еден од методите за времињата, како RAIN, CLOUDY, итн… такада еден од тие методи се извршува соодветно.
Следна е функцијата play
play: function() {
var self = this;
this.pause();
this.interval = requestInterval(function() {
var now = Date.now(),
i;
for(i = self.list.length; i--; )
self.draw(self.list[i], now);
}, 1000 / 60);
},
Во неа првин се забележува интересното var self = this; – оваа варијабла self ни помага да чуваме референца до this во случаи кога може контекстот на извршување на this да се менува. Повеќе за тоа тука. Потоа повикуваме pause – функција која ќе ја објасниме следна, и потоа повикуваме requestInterval и во секоја итерација ги итерираме сите објекти во листата и повикуваме исцртување – така ја добиваме анимираноста.
И последната функција, pause
pause: function() {
var i;
if(this.interval) {
cancelInterval(this.interval);
this.interval = null;
}
}
Во неа, доколку interval е некогаш дефиниран (што значи доколку е повикано претходно play) се повикува cancelInterval и interval се поставува на null.
Крај на кодот. Структурата на библиотеката графички преставено изгледа вака:
Преглед на структурата на Skycons
Сега уште еден коментар. Зошто некои методи се достапни преку Skycons дирекно, а некои преку инстанцата? Затоа што можеме да имаме повеќе икони на една иста веб страна, и не сакаме сите да бидат со исти бои, или некои сакаме да се анимирани а некои статички. На овој начин тоа е возможно.
И тоа е тоа. Доколку имате сугестии, поправки, идеи, надополнувања или било каков коментар – бујрум!
Оперативните системи се софтвер, кој од сите типови на софтвер, ја има имаат потребата најмногу и најбрзо да се менуваат, да се подобруваат и да бидат во тек со најновите харверски новости но и со посакувањата на крајните корисници – меѓу кои барањата за поголема интуитивност и услужливост.
Очигледно зборувам оперативните системи наменети за “десктоп” машините, за мобилните уреди и таблетите, оние кои имаат најмногу контакт со нас – секојдневните корисници. Во овој пост нема да зборувам за оперативните системи кои се наоѓаат во сателитите, во системите кои не смеат ни за еден момент од времето да потфрлат, во серверите (виртуелизирани или не), во уредите во нулеарните реактори, болниците и слично – тие си заслужуваат посебна дискусија и секако не влегуваат во опсегот на она што сакам да го кажам во следните редови.
Имам мислење дека во период од следните години ќе видиме многу промени во декстоп и мобилните оперативни системи, мислење до кое дојдов поради неодамнешни случувања и трендови.
Да видиме што се случува тука во последно време:
Ова укажува на неколку трендови:
Некои од точкиве се испреплетуваат/се зависни меѓусебно.
Во ова поле, кајшто великаните iOS и Android доминираат и Windows Phone е во пораст, се очекува да имаат конкуренција или годинава или 2014та.
Во горенаведените мобилни оперативни системи нема некои ‘сеизмички’ промени, нови верзии од нив добиваме секои неколку месеци, со нови оптимизации и подобрувања но не некои круцијални промени во корисничкиот интерфејс или ‘под хаубата’ во архитектурата на системот и начинот на кој се пишуваат апликации за него.
Но затоа, во развој се неколку оперативни системи кај кои главна работа која ги разликува од горенаведените е тоа што пишувањето на апликации за нив се врши во веб технологии како HTML, CSS и JavaScript.
Тие се веб технологии, но во овие нови оперативни системи ќе создаваат ‘нативни’ апликации за нив. Пионир во овој тип на мобилни оперативни системи беше webOS – кој падна во рацете на HP и отиде во неповрат. Но затоа има нови играчи:

Една од сликите од најавувањето на Firefox OS (превземено од http://live.theverge.com/firefox-os-mwc-2013-live-blog/ )

Ubuntu за мобилни (превземено од http://www.theverge.com/2013/2/19/4005514/ubuntu-phones-2014-might-be-locked-down-by-mobile )
Дали овој нов бран на мобилни оперативни системи ќе создаде промени останува да видиме. Тоа зависи од дали:
Доколку има основа, одностно горните зависности се исполнат, ќе доведе до трендови како:
Околу овие промени, да не ги заборавиме и веќе постоечките решенија како PhoneGap/Apache Cordova, Titanium, и така натаму, кои веќе овозможуваат користење веб технологии за изработка на мобилни апликации. Доколку имате апликација во Phonegap/Cordova – голема е можноста со лесност во иднина да ја приспособите за горенаведените нови мобилни оперативни системи. Поважниот дел во промените што иднината ги носи е што користењето на овие техологии ќе се извршува на пониско ниво на оперативниот систем од што се случува моментално, со тоа и перформансите ќе бидат подобри од што се моментално.
Уште една мисла за крај: Покрај сите овие промени кои надоаѓаат во софтверот, јасно е дека ќе треба да има промени/надградби и во вештините кои ги поседуваат развивачите на софтвер. Односно да не се само “шлапа” JavaScript туку и да се навлезе во подлабоките концепти и можности кои ги нуди јазикот и да се искористат.
И тоа е тоа, може многу да се навлегува, истражува па и филозофира на темава, но мислам дека има доволно ментална стимулација во постов за да ве замисли.
Доколку забележите некаква грешка, или сакате да го споделите вашето мислење, не се двоумете.
Сте се замислиле ли некогаш, каде колку се користи Forusquare, еден од најпопуларните геолокациски сервиси во светот? Дали има повеќе ‘чекини’ еден град или друг? Или држави споредено?
Како одговор за љубопитните, Mashable објавија дека Foursquare нудат нова алатка која впрочем е мапа на светот врз која е графички претставена активноста на корисниците. Мапата, може да се прегледа и без корисничка сметка на сервисот.
Скриншоти од сервисот, поставени врз соодветни скриншоти од Google Maps, еден филтер за транспарентност, и ги имаме следните резултати (клик на сликата ја отвора во нов таб/јазиче во `оригиналната` големина).
Како стои балканот?
Според претставените податоци, Албанија и БиХ најслабо го користат сервисот, а Грција најмногу. Македонија солидно се држи.
Каква е ситуацијата во Македонија, по кои градови има ‘чекини’?
Скопје како најголем град (и со најмногу хипстери :P) логично е на прво место. Може да приметиме дека скоро во сите градови (Охрид, Битола, Велес, Штип, итн…) има доста активност. Има и други интересни детали, како на пример линиите околу Охридско и Мавровско езеро.
Интересно би било и Facebook да објават слична алатка кадешто ќе бидат преставени податоците од нивниот геолокациски сервис којшто е интегриран во социјалната мрежа.
Геолокациските сервиси се дел од иднината, такада останува да бидеме дел од неа.