WeatherIcon.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991
  1. // WeatherIcon.js is released as
  2. // "Creative Commons - Attribution - ShareAlike 3.0".
  3. //
  4. // http://creativecommons.org/licenses/by-sa/3.0/
  5. //
  6. //
  7. //
  8. // You are free to:
  9. //
  10. // Share Ñ copy and redistribute the material in any medium or format
  11. // Adapt Ñ remix, transform, and build upon the material for any purpose, even commercially.
  12. //
  13. // The licensor cannot revoke these freedoms as long as you follow the license terms.
  14. //
  15. //
  16. //
  17. // Under the following terms:
  18. //
  19. // Attribution Ñ You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use.
  20. // ShareAlike Ñ If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original.
  21. //
  22. // No additional restrictions Ñ You may not apply legal terms or technological measures that legally restrict others from doing anything the license permits.
  23. //
  24. //
  25. //
  26. // Notices:
  27. //
  28. // You do not have to comply with the license for elements of the material in the public domain or where your use is permitted by an applicable exception or limitation.
  29. // No warranties are given. The license may not give you all of the permissions necessary for your intended use. For example, other rights such as publicity, privacy, or moral rights may limit how you use the material.
  30. "use strict";
  31. var WeatherIcon = (function(){
  32. function WeatherIcon(container,stroke,shadow) {
  33. this.isPlaying = false;
  34. this.canvas = new WeatherIcon.Canvas(container);
  35. this.canvas.setCanvasSize(128,128);
  36. this.fps = 30;
  37. this.particlesBorder = 20;
  38. this.spf = 1000/this.fps;
  39. this.objects = [];
  40. this.particles = [];
  41. this.timer = false;
  42. // fill
  43. this.canvas.ctx.fillStyle = '#fff';
  44. // stroke
  45. if (stroke) {
  46. this.stroke = true;
  47. this.canvas.ctx.lineWidth = 2;
  48. this.canvas.ctx.strokeStyle = '#000';
  49. } else {
  50. this.stroke = false;
  51. this.canvas.ctx.strokeStyle = 'transparent';
  52. }
  53. // shadow
  54. if(shadow) {
  55. this.canvas.ctx.shadowOffsetX = 0;
  56. this.canvas.ctx.shadowOffsetY = 0;
  57. this.canvas.ctx.shadowBlur = 5;
  58. this.canvas.ctx.shadowColor = "black";
  59. }
  60. };
  61. // Point
  62. WeatherIcon.Canvas = (function(){
  63. // Canvas
  64. function Canvas(obj,id) {
  65. if (obj) {
  66. if (obj.nodeName=='CANVAS') {
  67. this.canvas = obj;
  68. } else {
  69. this.canvas = document.createElement("canvas");
  70. if(id) this.canvas.id = id;
  71. obj.appendChild(this.canvas);
  72. // IE
  73. if (Canvas.ieMode) G_vmlCanvasManager.initElement(this.canvas);
  74. }
  75. } else {
  76. this.canvas = document.createElement("canvas");
  77. if (Canvas.ieMode) G_vmlCanvasManager.initElement(this.canvas);
  78. }
  79. // GET CONTEXT
  80. this.ctx = this.canvas.getContext('2d');
  81. }
  82. Canvas.prototype = {
  83. setSize:function(w,h) {
  84. this.setCanvasSize(w,h);
  85. this.setHtmlSize(w+'px',h+'px');
  86. },
  87. setCanvasSize:function(w,h) {
  88. this.canvas.width = w;
  89. this.canvas.height = h;
  90. },
  91. setHtmlSize:function(w,h) {
  92. this.canvas.style.width = w;
  93. this.canvas.style.height = h;
  94. },
  95. drawBox:function(w,h,rad) {
  96. this.ctx.beginPath();
  97. this.ctx.moveTo(rad, 0);
  98. this.ctx.lineTo(w-rad, 0);
  99. this.ctx.bezierCurveTo(w, 0, w, 0, w, rad);
  100. this.ctx.lineTo(w, h-rad);
  101. this.ctx.bezierCurveTo(w, h, w, h, w-rad, h);
  102. this.ctx.lineTo(rad, h);
  103. this.ctx.bezierCurveTo(0, h, 0, h, 0, h-rad);
  104. this.ctx.lineTo(0, rad);
  105. this.ctx.bezierCurveTo(0, 0, 0, 0, rad, 0);
  106. this.ctx.fill();
  107. },
  108. clear:function(){
  109. this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height);
  110. }
  111. }
  112. Canvas.supported = function() {
  113. // Make sure we don't execute when canvas isn't supported
  114. var canvas = document.createElement("canvas");
  115. return (canvas.getContext) ? true:false;
  116. }
  117. // Detect internet explorer to load google canvas code (G_vmlCanvasManager)
  118. var
  119. rv = -1, // Default value assumes no ie
  120. ua = navigator.userAgent,
  121. re = new RegExp("MSIE ([0-9]{1,}[\.0-9]{0,})");
  122. if (re.exec(ua) != null) rv = parseFloat( RegExp.$1 );
  123. Canvas.ieMode = (rv>-1&&rv<9);
  124. return Canvas;}());
  125. // Point
  126. WeatherIcon.Point = (function(){
  127. function Point(x, y){ this.x = x || 0; this.y = y || 0; };
  128. Point.prototype.add = function(p){ this.x+=p.x;this.y+=p.y };
  129. Point.prototype.set = function(x,y){ this.x=x;this.y=y };
  130. Point.prototype.prod = function(n){ this.x*=n;this.y*=n };
  131. Point.prototype.clone = function() { return new WeatherIcon.Point(this.x, this.y); };
  132. Point.prototype.rotate = function(r) {var x = this.x;var y = this.y;this.x = x*r.x-y*r.y;this.y = x*r.y+y*r.x;};
  133. return Point;}());
  134. // Circle
  135. WeatherIcon.Circle = function( center , r ){ this.center=center;this.r=r };
  136. // Prototype
  137. WeatherIcon.prototype = {
  138. draw:function(){
  139. var n;
  140. this.canvas.clear();
  141. n = this.particles.length;
  142. while(n--) {
  143. this.particles[n].update(10);
  144. this.particles[n].draw(this.canvas.ctx);
  145. }
  146. n = this.objects.length;
  147. while(n--) {
  148. this.objects[n].update(10);
  149. this.objects[n].draw(this.canvas.ctx);
  150. }
  151. },
  152. update:function() {
  153. this.isPlaying = true;
  154. this.draw();
  155. this.timer = setTimeout(this.update.bind(this),this.spf);
  156. },
  157. play:function() {
  158. this.stop();
  159. this.update();
  160. },
  161. stop:function(){
  162. this.isPlaying=false;
  163. if (this.timer) {
  164. clearTimeout(this.timer);
  165. this.timer = false;
  166. }
  167. },
  168. setBody:function(body){
  169. this.body = body;
  170. },
  171. setIcon:function(icon){
  172. this.icon = icon;
  173. },
  174. toggle:function() {
  175. this.isPlaying?this.stop():this.play();
  176. },
  177. change:function(icon,mode){
  178. this.icon = icon;
  179. this.setIcon(icon);
  180. this.setBody(mode===WeatherIcon.NIGHT?WeatherIcon.NIGHT:WeatherIcon.DAY);
  181. this.build();
  182. this.draw();
  183. },
  184. addRain:function(type){
  185. type = type==WeatherIcon.LIGHT?WeatherIcon.LIGHT:WeatherIcon.HEAVY;
  186. var
  187. speed = 0.2,
  188. angle = 0.2,
  189. yo = 60,
  190. n = WeatherIcon.particles[type].length;
  191. while(n--) this.particles.push(new WeatherIcon.Drop(WeatherIcon.particles[type][n],speed,angle,yo));
  192. },
  193. addSnow:function(type){
  194. type = type==WeatherIcon.LIGHT?WeatherIcon.LIGHT:WeatherIcon.HEAVY;
  195. var
  196. speed = 0.2,
  197. angle = 0.2,
  198. yo = 60,
  199. n = WeatherIcon.particles[type].length;
  200. while(n--) this.particles.push(new WeatherIcon.Snow(WeatherIcon.particles[type][n],speed,angle,yo));
  201. },
  202. addSleet:function(){
  203. // add rain and snow
  204. var
  205. type = WeatherIcon.LIGHT,
  206. speed = 0.2,
  207. angle = 0.2,
  208. yo = 60,
  209. n = WeatherIcon.particles[type].length;
  210. while(n--) {
  211. var drop = (n%2) ? new WeatherIcon.Drop(WeatherIcon.particles[type][n],speed,angle,yo):new WeatherIcon.Snow(WeatherIcon.particles[type][n],speed,angle,yo);
  212. this.particles.push(drop);
  213. }
  214. },
  215. build:function(){
  216. this.objects = [];
  217. this.particles = [];
  218. switch(this.icon) {
  219. case WeatherIcon.SUN:
  220. this.objects.push(this.body==WeatherIcon.DAY?new WeatherIcon.Sun(64,64,30):new WeatherIcon.Moon(64,64,30));
  221. break;
  222. case WeatherIcon.LIGHTCLOUD:
  223. this.objects.push(new WeatherIcon.Cloud(80,100,40));
  224. this.objects.push(this.body==WeatherIcon.DAY?new WeatherIcon.Sun(64,64,30):new WeatherIcon.Moon(64,64,30));
  225. break;
  226. case WeatherIcon.PARTLYCLOUD:
  227. this.objects.push(new WeatherIcon.Cloud(68,90,80));
  228. this.objects.push(this.body==WeatherIcon.DAY?new WeatherIcon.Sun(64,54,30):new WeatherIcon.Moon(64,54,30));
  229. break;
  230. case WeatherIcon.CLOUD:
  231. this.objects.push(new WeatherIcon.Cloud(90,80,40));
  232. this.objects.push(new WeatherIcon.Cloud(68,60,80));
  233. break;
  234. case WeatherIcon.LIGHTRAINSUN:
  235. this.objects.push(new WeatherIcon.Cloud(68,60,80));
  236. this.objects.push(this.body==WeatherIcon.DAY?new WeatherIcon.Sun(40,30,20):new WeatherIcon.Moon(40,30,20));
  237. this.addRain(WeatherIcon.LIGHT);
  238. break;
  239. case WeatherIcon.SLEETSUN:
  240. this.objects.push(new WeatherIcon.Cloud(68,60,80));
  241. this.objects.push(this.body==WeatherIcon.DAY?new WeatherIcon.Sun(40,30,20):new WeatherIcon.Moon(40,30,20));
  242. this.addSleet();
  243. break;
  244. case WeatherIcon.SNOWSUN:
  245. this.objects.push(new WeatherIcon.Cloud(68,60,80));
  246. this.objects.push(this.body==WeatherIcon.DAY?new WeatherIcon.Sun(40,30,20):new WeatherIcon.Moon(40,30,20));
  247. this.addSnow(WeatherIcon.LIGHT);
  248. break;
  249. case WeatherIcon.SNOW:
  250. this.objects.push(new WeatherIcon.Cloud(68,50,80));
  251. this.addSnow();
  252. break;
  253. case WeatherIcon.SNOWTHUNDER:
  254. this.objects.push(new WeatherIcon.Cloud(68,50,80));
  255. this.addSnow(WeatherIcon.LIGHT);
  256. this.objects.push(new WeatherIcon.Thunder(55,82,0.8));
  257. break;
  258. case WeatherIcon.THUNDER:
  259. this.objects.push(new WeatherIcon.Cloud(68,50,80));
  260. this.objects.push(new WeatherIcon.Thunder(30,75,0.6));
  261. this.objects.push(new WeatherIcon.Thunder(60,80,0.7));
  262. this.objects.push(new WeatherIcon.Thunder(90,75,0.6));
  263. break;
  264. case WeatherIcon.SLEETSUNTHUNDER:
  265. this.objects.push(new WeatherIcon.Cloud(68,60,80));
  266. this.objects.push(this.body==WeatherIcon.DAY?new WeatherIcon.Sun(40,30,20):new WeatherIcon.Moon(40,30,20));
  267. this.addSleet();
  268. this.objects.push(new WeatherIcon.Thunder(95,85,0.7));
  269. this.objects.push(new WeatherIcon.Thunder(58,88,0.8));
  270. break;
  271. case WeatherIcon.LIGHTRAINTHUNDERSUN:
  272. this.objects.push(new WeatherIcon.Cloud(68,60,80));
  273. this.objects.push(this.body==WeatherIcon.DAY?new WeatherIcon.Sun(40,30,20):new WeatherIcon.Moon(40,30,20));
  274. this.addRain(WeatherIcon.LIGHT);
  275. this.objects.push(new WeatherIcon.Thunder(30,75,0.6));
  276. this.objects.push(new WeatherIcon.Thunder(58,90,0.7));
  277. break;
  278. case WeatherIcon.SNOWSUNTHUNDER:
  279. this.objects.push(new WeatherIcon.Cloud(68,60,80));
  280. this.objects.push(this.body==WeatherIcon.DAY?new WeatherIcon.Sun(40,30,20):new WeatherIcon.Moon(40,30,20));
  281. this.addSnow(WeatherIcon.LIGHT);
  282. this.objects.push(new WeatherIcon.Thunder(30,75,0.6));
  283. this.objects.push(new WeatherIcon.Thunder(58,90,0.7));
  284. break;
  285. case WeatherIcon.LIGHTRAIN:
  286. this.objects.push(new WeatherIcon.Cloud(68,50,80));
  287. this.addRain(WeatherIcon.LIGHT);
  288. break;
  289. case WeatherIcon.RAIN:
  290. this.objects.push(new WeatherIcon.Cloud(68,50,80));
  291. this.addRain();
  292. break;
  293. case WeatherIcon.FOG:
  294. this.objects.push(new WeatherIcon.Fog(68,90,80));
  295. this.objects.push(this.body==WeatherIcon.DAY?new WeatherIcon.Sun(64,54,30):new WeatherIcon.Moon(64,54,30));
  296. break;
  297. case WeatherIcon.LIGHTRAINTHUNDER:
  298. this.objects.push(new WeatherIcon.Cloud(68,50,80));
  299. this.addRain(WeatherIcon.LIGHT);
  300. this.objects.push(new WeatherIcon.Thunder(30,72,0.7));
  301. this.objects.push(new WeatherIcon.Thunder(58,88,0.8));
  302. break;
  303. case WeatherIcon.RAINTHUNDER:
  304. this.objects.push(new WeatherIcon.Cloud(68,50,80));
  305. this.addRain();
  306. this.objects.push(new WeatherIcon.Thunder(30,72,0.7));
  307. this.objects.push(new WeatherIcon.Thunder(58,88,0.8));
  308. break;
  309. case WeatherIcon.SLEETTHUNDER:
  310. this.objects.push(new WeatherIcon.Cloud(68,50,80));
  311. this.addSleet();
  312. this.objects.push(new WeatherIcon.Thunder(95,85,0.7));
  313. this.objects.push(new WeatherIcon.Thunder(58,88,0.8));
  314. break;
  315. case WeatherIcon.EXTREME: // TODO
  316. case WeatherIcon.SLEET:
  317. this.objects.push(new WeatherIcon.Cloud(68,50,80));
  318. this.addSleet();
  319. break;
  320. }
  321. }
  322. };
  323. // COMPONENTS
  324. WeatherIcon.Cloud = (function(){
  325. var Cloud = function(xo,yo,w) {
  326. xo=xo?xo:68;
  327. yo=yo?yo:50;
  328. w=w?w:80;
  329. var h = w*0.5;
  330. var center = new WeatherIcon.Point(xo,yo);
  331. var size = new WeatherIcon.Point(w,h)
  332. var sizeMed = new WeatherIcon.Point(w>>1,h>>1)
  333. this.size = size;
  334. this.po = new WeatherIcon.Point( center.x - sizeMed.x , center.y );
  335. this.p1 = this.po.clone();
  336. this.p1.x += size.x;
  337. this.cl = new WeatherIcon.Circle(new WeatherIcon.Point( center.x - sizeMed.x , center.y ),w*0.14);
  338. this.cr = new WeatherIcon.Circle(new WeatherIcon.Point( center.x + sizeMed.x , center.y + w*0.03 ),w*0.1);
  339. this.ca = new WeatherIcon.Circle(new WeatherIcon.Point(center.x - sizeMed.x*0.42 , center.y ),w*0.35);
  340. this.cb = new WeatherIcon.Circle(new WeatherIcon.Point(center.x + sizeMed.x*0.45 , center.y ),w*0.25);
  341. this.cc = new WeatherIcon.Circle(new WeatherIcon.Point(center.x - sizeMed.x*0.20 , center.y ),w*0.28);
  342. this.pi = Math.PI;
  343. this.pi2 = this.pi/2;
  344. this.p2 = new WeatherIcon.Point( +this.w , this.h );
  345. }
  346. Cloud.prototype = {
  347. update:function(dt) {},
  348. draw:function(ctx) {
  349. // fill
  350. ctx.beginPath();
  351. ctx.arc(this.cl.center.x,this.cl.center.y, this.cl.r , 0, 2*this.pi );
  352. ctx.arc(this.cl.center.x+this.cl.r,this.cl.center.y, this.cl.r , 0, 2*this.pi );
  353. ctx.arc(this.cc.center.x,this.cc.center.y, this.cc.r , 0 , 2*this.pi );
  354. ctx.arc(this.ca.center.x,this.ca.center.y, this.ca.r , this.pi , 0 );
  355. ctx.arc(this.cb.center.x,this.cb.center.y, this.cb.r , 0 , 2*this.pi );
  356. ctx.arc(this.cr.center.x,this.cr.center.y, 1.3*this.cr.r , 0, 2*this.pi );
  357. ctx.closePath();
  358. ctx.stroke();
  359. ctx.fill();
  360. }
  361. };
  362. return Cloud;}());
  363. WeatherIcon.Snow = (function(){
  364. var Snow = function(posIni,speed,angle_,yo) {
  365. this.angle = angle_;
  366. this.speed = speed;
  367. this.posIni = posIni;
  368. this.w = 3;
  369. this.dy = this.w*4;
  370. this.pos = this.posIni.clone();
  371. this.rot = new WeatherIcon.Point(Math.cos(this.angle),Math.sin(this.angle));
  372. this.v = new WeatherIcon.Point(0,this.speed);
  373. this.v.rotate(this.rot);
  374. this.po = new WeatherIcon.Point( );
  375. this.po.add(this.pos);
  376. // reset position
  377. var dy = this.po.y - yo;
  378. var m = this.rot.y/this.rot.x;
  379. this.pr = new WeatherIcon.Point( this.po.x+dy*m , yo );
  380. this.angle = Math.PI/3.5;
  381. this.angle2 = 2*this.angle;
  382. this.r = (this.w>>1);
  383. };
  384. Snow.prototype = {
  385. reset:function(){
  386. this.po.set(0,0);
  387. this.po.add(this.pr);
  388. },
  389. update:function(dt) {
  390. var dPos = new WeatherIcon.Point(this.v.x*dt,this.v.y*dt);
  391. this.po.add(dPos);
  392. if (this.po.y>128) { this.reset(); }
  393. },
  394. draw:function(ctx) {
  395. ctx.beginPath();
  396. ctx.arc(this.po.x,this.po.y + this.dy , this.w , 0, 6.28 );
  397. ctx.closePath();
  398. ctx.stroke();
  399. ctx.fill();
  400. /*
  401. ctx.beginPath();
  402. ctx.save();
  403. ctx.translate( this.po.x,this.po.y );
  404. ctx.rect(-this.r , 0 , this.w , 1);
  405. ctx.rotate(-this.angle);
  406. ctx.rect(-this.r , 0 , this.w , 1);
  407. ctx.rotate(this.angle2);
  408. ctx.rect(-this.r , 0 , this.w , 1);
  409. ctx.restore();
  410. ctx.closePath();
  411. ctx.stroke();
  412. ctx.fill();
  413. */
  414. }
  415. }
  416. return Snow;}());
  417. WeatherIcon.Drop = (function(){
  418. var Drop = function(posIni,speed,angle_,yo) {
  419. this.angle = angle_;
  420. this.speed = speed;
  421. this.posIni = posIni;
  422. this.isFreeze = false;
  423. this.elongation = 2;
  424. this.w = 10;
  425. this.h = this.w*this.elongation;
  426. this.pos = this.posIni.clone();
  427. this.rot = new WeatherIcon.Point(Math.cos(this.angle),Math.sin(this.angle));
  428. this.v = new WeatherIcon.Point(0,this.speed);
  429. this.v.rotate(this.rot);
  430. this.po = new WeatherIcon.Point( );
  431. this.p1 = new WeatherIcon.Point( -this.w , this.h );
  432. this.p2 = new WeatherIcon.Point( +this.w , this.h );
  433. this.p1.rotate(this.rot);
  434. this.p2.rotate(this.rot);
  435. this.po.add(this.pos);
  436. this.p1.add(this.pos);
  437. this.p2.add(this.pos);
  438. // reset position
  439. var dy = this.po.y - yo;
  440. var m = this.rot.y/this.rot.x;
  441. var xo = this.po.x+dy*m;
  442. //_('debug').innerHTML += this.angle+'>'+Math.cos(this.angle)+","+Math.sin(this.angle)+"<br>";
  443. this.pr = new WeatherIcon.Point( xo , yo );
  444. };
  445. Drop.prototype = {
  446. freeze:function(){
  447. this.isFreeze = true;
  448. this.angle = Math.PI/3.5;
  449. this.r = (this.w>>1);
  450. },
  451. reset:function(){
  452. this.po.set(0,0);
  453. this.p1.set( -this.w , this.h );
  454. this.p2.set( +this.w , this.h );
  455. this.p1.rotate(this.rot);
  456. this.p2.rotate(this.rot);
  457. this.po.add(this.pr);
  458. this.p1.add(this.pr);
  459. this.p2.add(this.pr);
  460. },
  461. update:function(dt) {
  462. var dPos = new WeatherIcon.Point(this.v.x*dt,this.v.y*dt);
  463. this.po.add(dPos);
  464. this.p1.add(dPos);
  465. this.p2.add(dPos);
  466. if (this.po.y>128) { this.reset(); }
  467. },
  468. draw:function(ctx) {
  469. ctx.beginPath();
  470. if (this.isFreeze) {
  471. ctx.save();
  472. ctx.translate( this.po.x,this.po.y );
  473. ctx.rect(-this.r , 0 , this.w , 1);
  474. ctx.restore();
  475. ctx.save();
  476. ctx.translate( this.po.x,this.po.y );
  477. ctx.rotate(this.angle);
  478. ctx.rect(-this.r , 0 , this.w , 1);
  479. ctx.restore();
  480. ctx.save();
  481. ctx.translate( this.po.x,this.po.y );
  482. ctx.rotate(-this.angle);
  483. ctx.rect(-this.r , 0 , this.w , 1);
  484. ctx.restore();
  485. //ctx.lineTo(this.po.x - this.w , this.po.y);
  486. } else {
  487. ctx.moveTo(this.po.x,this.po.y);
  488. ctx.bezierCurveTo(this.p1.x,this.p1.y,this.p2.x,this.p2.y,this.po.x,this.po.y+1e-5); // +1e-5 debug chrome bezierCurveTo bug
  489. }
  490. ctx.closePath();
  491. ctx.stroke();
  492. ctx.fill();
  493. }
  494. }
  495. return Drop;}());
  496. WeatherIcon.Thunder = (function(){
  497. function Thunder(x,y,s){
  498. this.so = s||1;
  499. this.s = this.so;
  500. this.x = x;
  501. this.y = y;
  502. this.ti = 500*Math.random();
  503. this.p = [];
  504. this.n = Thunder.points.length;
  505. };
  506. Thunder.prototype.update = function() {
  507. if (!this.t) {
  508. this.t = new Date().getTime() + this.ti;
  509. this.s = this.so;
  510. return;
  511. }
  512. var t = new Date().getTime();
  513. var dt = t - this.t - this.ti;
  514. this.s = 0;
  515. if (dt>2000) {this.s = 0;this.t = t;}
  516. else if (dt>1000) this.s = this.so;
  517. else if (dt>700) this.s = (Math.random()<0.5)?this.so:0;
  518. }
  519. Thunder.prototype.draw = function(ctx) {
  520. ctx.beginPath();
  521. ctx.save();
  522. ctx.translate( this.x , this.y );
  523. ctx.scale(this.s,this.s);
  524. ctx.moveTo(Thunder.points[0].x,Thunder.points[0].y);
  525. var n = this.n;
  526. while (n--) ctx.lineTo(Thunder.points[n].x,Thunder.points[n].y);
  527. ctx.stroke();
  528. ctx.fill();
  529. ctx.restore();
  530. }
  531. Thunder.size = { w:30 , h:45 }
  532. Thunder.points = [{x:0,y:0},{x:0,y:22},{x:13,y:20},{x:3,y:43},{x:28,y:15},{x:12,y:13},{x:21,y:0}];
  533. return Thunder;}());
  534. WeatherIcon.Sun = (function(){
  535. var Sun = function(xo,yo,ri,re) {
  536. xo = xo?xo:64;
  537. yo = yo?yo:64;
  538. ri = ri?ri:20;
  539. re = re?re:ri*1.25;
  540. var center = new WeatherIcon.Point(xo,yo);
  541. this.rotation = { val:0 , inc:0.001 };
  542. this.center = center;
  543. this.points = [];
  544. this.pointsExt = [];
  545. var n = 20;
  546. var angle = 0;
  547. var dAngle = Math.PI/n;
  548. while(n--){
  549. var x = ri*Math.cos(angle);
  550. var y = ri*Math.sin(angle);
  551. this.points.push(new WeatherIcon.Point(x,y));
  552. angle += dAngle;
  553. var x = re*Math.cos(angle);
  554. var y = re*Math.sin(angle);
  555. this.pointsExt.push(new WeatherIcon.Point(x,y));
  556. angle += dAngle
  557. }
  558. };
  559. Sun.prototype = {
  560. update:function(dt) {},
  561. draw:function(ctx) {
  562. var nMax = this.points.length;
  563. var n = 0;
  564. ctx.save();
  565. ctx.translate( this.center.x , this.center.y );
  566. ctx.rotate( this.rotation.val+=this.rotation.inc );
  567. ctx.beginPath();
  568. ctx.moveTo(this.pointsExt[nMax-1].x,this.pointsExt[nMax-1].y);
  569. for (n=0;n<nMax;n++) ctx.quadraticCurveTo(this.points[n].x,this.points[n].y,this.pointsExt[n].x,this.pointsExt[n].y);
  570. ctx.stroke();
  571. ctx.fill();
  572. ctx.restore();
  573. }
  574. }
  575. return Sun;}());
  576. WeatherIcon.Fog = (function(){
  577. var Fog = function() { this.angle = 0; }
  578. Fog.PI2 = Math.PI*2;
  579. Fog.prototype = {
  580. update:function(dt) { this.angle += 0.01;},
  581. draw:function(ctx) {
  582. var dx;
  583. // fill
  584. dx = 0.2*Math.cos(this.angle)
  585. ctx.beginPath();
  586. ctx.save();
  587. ctx.translate( 85,62 );
  588. ctx.scale(13,1);
  589. ctx.arc(dx,0, 2 , 0, Fog.PI2 );
  590. ctx.closePath();
  591. ctx.restore();
  592. ctx.stroke();
  593. ctx.fill();
  594. dx = 0.2*Math.cos(this.angle+0.5)
  595. ctx.beginPath();
  596. ctx.save();
  597. ctx.translate( 40,70 );
  598. ctx.scale(6,0.5);
  599. ctx.arc(dx,0, 5 , 0, Fog.PI2 );
  600. ctx.closePath();
  601. ctx.restore();
  602. ctx.stroke();
  603. ctx.fill();
  604. dx = 0.3*Math.cos(this.angle)
  605. ctx.beginPath();
  606. ctx.save();
  607. ctx.translate( 80,80 );
  608. ctx.scale(6,0.5);
  609. ctx.arc(dx,0, 7 , 0, Fog.PI2 );
  610. ctx.closePath();
  611. ctx.restore();
  612. ctx.stroke();
  613. ctx.fill();
  614. dx = 0.4*Math.cos(this.angle+0.9)
  615. ctx.beginPath();
  616. ctx.save();
  617. ctx.translate( 56,92 );
  618. ctx.scale(10,1);
  619. ctx.arc(dx,0, 5 , 0, Fog.PI2 );
  620. ctx.closePath();
  621. ctx.restore();
  622. ctx.stroke();
  623. ctx.fill();
  624. dx = 0.2*Math.cos(this.angle)
  625. ctx.beginPath();
  626. ctx.save();
  627. ctx.translate( 100,104 );
  628. ctx.scale(7,1);
  629. ctx.arc(dx,0, 3 , 0, Fog.PI2 );
  630. ctx.closePath();
  631. ctx.restore();
  632. ctx.stroke();
  633. ctx.fill();
  634. }
  635. }
  636. return Fog;}());
  637. WeatherIcon.Moon = (function(){
  638. function Moon(x,y,r){ this.x = x||0; this.y = y||0; this.r=r||20;
  639. this.rotDirection = 1;
  640. this.rotAngle = 0;
  641. this.angleMax = 10*Math.PI/180;
  642. };
  643. Moon.prototype = {
  644. update:function() {
  645. if(this.rotAngle>this.angleMax) this.rotDirection = -1;
  646. else if(this.rotAngle<-this.angleMax)this.rotDirection = 1;
  647. this.rotAngle += 0.002*this.rotDirection;
  648. },
  649. draw:function(ctx) {
  650. ctx.save();
  651. ctx.translate( this.x , this.y );
  652. ctx.rotate( -0.6 + this.rotAngle );
  653. var a = 0.31*Math.PI;
  654. ctx.beginPath();
  655. ctx.arc(0,0, this.r , a , -a );
  656. ctx.arc(this.r,0, this.r , Math.PI+a , Math.PI-a , true);
  657. ctx.stroke();
  658. ctx.fill();
  659. ctx.restore();
  660. }
  661. };
  662. return Moon;}());
  663. // PARAMETERS
  664. WeatherIcon.particles = {
  665. heavy:[
  666. new WeatherIcon.Point(22,96),
  667. new WeatherIcon.Point(22,116),
  668. new WeatherIcon.Point(36,71),
  669. new WeatherIcon.Point(47,95),
  670. new WeatherIcon.Point(47,115),
  671. new WeatherIcon.Point(57,64),
  672. new WeatherIcon.Point(66,88),
  673. new WeatherIcon.Point(66,108),
  674. new WeatherIcon.Point(78,61),
  675. new WeatherIcon.Point(83,94),
  676. new WeatherIcon.Point(83,114),
  677. new WeatherIcon.Point(95,72),
  678. new WeatherIcon.Point(104,88),
  679. new WeatherIcon.Point(104,108)
  680. ],light:[
  681. new WeatherIcon.Point(22,96),
  682. new WeatherIcon.Point(36,71),
  683. new WeatherIcon.Point(47,110),
  684. new WeatherIcon.Point(66,88),
  685. new WeatherIcon.Point(78,61),
  686. new WeatherIcon.Point(83,110),
  687. new WeatherIcon.Point(104,88),
  688. ]};
  689. // day / night / todo midnight soon ... ( todo c95 )
  690. WeatherIcon.DAY = 'Sun';
  691. WeatherIcon.NIGHT = 'Moon';
  692. // precipitation ammount
  693. WeatherIcon.LIGHT = 'light';
  694. WeatherIcon.HEAVY = 'heavy';
  695. // icons list
  696. WeatherIcon.SUN = 1; // SUN
  697. WeatherIcon.LIGHTCLOUD = 2; // SUN , SMALL CLOUD
  698. WeatherIcon.PARTLYCLOUD = 3; // SUN , BIG CLOUD
  699. WeatherIcon.CLOUD = 4; // BIG CLOUD , SMALL CLOUD
  700. WeatherIcon.LIGHTRAINSUN = 5; // SUN , BIG CLOUD , LIGHT RAIN
  701. WeatherIcon.LIGHTRAINTHUNDERSUN = 6; // SUN , BIG CLOUD , LIGHT RAIN , THUNDER
  702. WeatherIcon.SLEETSUN = 7; // SUN , BIG CLOUD , LIGHT RAIN , SNOW
  703. WeatherIcon.SNOWSUN = 8; // SUN , BIG CLOUD , SNOW
  704. WeatherIcon.LIGHTRAIN = 9; // BIG CLOUD , LIGHT RAIN
  705. WeatherIcon.RAIN = 10; // BIG CLOUD , HARD RAIN
  706. WeatherIcon.RAINTHUNDER = 11; // BIG CLOUD , HARD RAIN , THUNDER
  707. WeatherIcon.SLEET = 12; // BIG CLOUD , RAIN , SNOW
  708. WeatherIcon.SNOW = 13; // BIG CLOUD , SNOW
  709. WeatherIcon.SNOWTHUNDER = 14; // BIG CLOUD , SNOW , THUNDER
  710. WeatherIcon.FOG = 15; // SUN , FOG
  711. WeatherIcon.SLEETSUNTHUNDER = 20 // SUN , SLEET , THUNDER
  712. WeatherIcon.SNOWSUNTHUNDER = 21; // BIG CLOUD, SUN , SNOW , 2x THUNDER
  713. WeatherIcon.LIGHTRAINTHUNDER = 22; // BIG CLOUD , lIGHT RAIN , THUNDER
  714. WeatherIcon.SLEETTHUNDER = 23; // TODO
  715. // dark days (todo c95)
  716. WeatherIcon.DARKDAY_SUN = 16;
  717. WeatherIcon.DARKDAY_LIGHTCLOUD = 17;
  718. WeatherIcon.DARKDAY_LIGHTRAINSUN = 18;
  719. WeatherIcon.DARKDAY_SNOWSUN = 19;
  720. // extreme conditions
  721. WeatherIcon.THUNDER = 50; // BIG CLOUD , 3 x THUNDER
  722. WeatherIcon.EXTREME = 99; // TODO
  723. // STATIC FUNCTIONS
  724. WeatherIcon.add = function(dom,icon,param) {
  725. if(typeof dom=='string') dom = document.getElementById(dom);
  726. if (param==undefined) param = {};
  727. var weatherIcon = new WeatherIcon(dom,param.stroke===false?false:true,param.shadow===true?true:false);
  728. weatherIcon.setIcon(icon);
  729. weatherIcon.setBody(param.mode===WeatherIcon.NIGHT?WeatherIcon.NIGHT:WeatherIcon.DAY);
  730. weatherIcon.build();
  731. weatherIcon.draw();
  732. if(param.animated===true) weatherIcon.update();
  733. return weatherIcon;
  734. };
  735. return WeatherIcon;}());