În Studii de caz

Studiu de caz: Macroscop – proces de dezvoltare

Reproducerea designului cu clasa Graphics

Dacă în prima parte a acestui studiu de caz ați putut citi despre cum s-a derulat procesul de creație în cazul infograficului interactiv Macroscop, în această parte va fi prezentat procesul de dezvoltare, cu accent pe interactivitate și animații.

Studiu de caz: infograficul interactiv Macroscop
Link dascloud.ro/macroscop/
Client Das Cloud
Dată lansare 26 martie, 2013
Tehnologii folosite ActionScript, Flash, Adobe Illustrator
Echipă
  • Creative Direction: Sorin Bechira
  • Graphic Design & Animation: Erik Erdőközi
  • Interactive Developer: Cătălin Săveanu

Procesul de dezvoltare

Cerința proiectului a fost aceea de a construi un grafic interactiv, pentru a vizualiza dinamic o cantitate mare de date preluate folosind Google Trends și Media IQ. Au fost folosite ActionScript 3 și FlashDevelop pentru scrierea de cod, compilare și debugger. În ceea ce privește reproducerea graficii cu ajutorul AS3-ului, s-a dorit să fie totul vectorial, pentru ca site-ul să poată fi afișat pe orice rezoluție.

O primă provocare a constat în reproducerea designului cu ajutorul clasei “Graphics” din AS3.

Exemplu: Dreptunghiul din mijlocul laturii hexagoanelor mari.

Reproducerea designului cu clasa Graphics

[as3]
/**
* _model.bigR – reprezintă raza cercului în care se înscriu
* hexagoanele mari care se rotesc
*/
var s:Shape = new Shape();
s.graphics.beginFill(0xcfcfcf, .7);
s.graphics.drawRect(-0.3 * _model.bigR, -2, 0.6 * _model.bigR, 4);
s.x = _model.bigR * Math.cos(Math.PI / 6) * Math.cos(Math.PI / 3);
s.y = _model.bigR * Math.cos(Math.PI / 6) * Math.sin(Math.PI / 3);
s.rotation = -30;
[/as3]

Crearea interactivității

Pentru butoanele principale (cele care selectează termenul medical) s-a folosit un singur movieclip, care a fost mai apoi multiplicat, rotit și colorat după nevoie, iar textul, împreună cu tooltip-ul care se află în interiorul lui, au fost rotite în sens contrar, pentru a putea fi citite. Totodată, o altă provocare a constat în mișcarea thumb-ului pe o rază fixă. (vezi imaginea și codul de mai jos)

Miscarea thumb-ului pe o raza fixa

[as3]
/**
* mx, my – coordonatele globale la care se află cursorul mouse-ului
* cx, cy – coordonatele centrului scenei
* angle – unghiul la care se va poziționa thumb-ul
* r – raza cercului pe care se mișcă thumb-ul
*/
var mx:Number = e.stageX;
var my:Number = e.stageY;
var cx:Number = mc.stage.stageWidth / 2;
var cy:Number = mc.stage.stageHeight / 2;
var angle:Number = Math.atan2(my – cy, mx – cx);
thumb.x = Math.cos(angle) * r;
thumb.y = Math.sin(angle) * r;
thumb.rotation = angle * 180 / Math.PI + 90;
[/as3]

Crearea graficelor pe baza XML-urilor generate din tabele Excel

Graficele s-au realizat pe baza datelor primite în format XML de la Media IQ. Pentru fiecare boală, au fost trimise câte 4 valori săptămânale, care prezentau evoluția bolii la data respectivă. Fiecare valoare reprezintă un punct în grafic, care s-a poziționat astfel:

[as3]
/**
* value – reprezintă valoarea primită în XML
* angle – este unghiul la care este poziționat punctul
* day, month – reprezinta ziua, luna la care am primit valoarea
*/
var dayAngle:Number = (day – 1) * (2 * Math.PI / 12) / 31;
var monthAngle:Number = (month – 1) * (2 * Math.PI / 12);
var angle:Number = -Math.PI / 2 + dayAngle + monthAngle;
var p:Point = new Point();
p.x = value * Math.cos(angle);
p.y = value * Math.sin(angle);
[/as3]

Unirea punctelor s-a făcut cu ajutorul curbelor Bezier, astfel s-a obținut o formă închisă.

Unirea punctelor cu curbele Bezier

Pentru a desena graficul final, acesta a fost împărțit în două părți, una pentru valori pozitive, iar alta pentru valori negative.

a. Valori pozitive

Pentru desenarea graficului pe valori pozitive, a fost folosită forma închisă obținută anterior, peste care a fost pusă o mască în formă de cerc de grosime: (Rmax - R), unde Rmax reprezintă raza maximă la care se pot pune valori pe grafic, iar R reprezintă raza care corespunde valorii de 0, primite prin XML.

Desenarea graficului pe valori pozitive

b. Valori negative

Pentru desenarea graficului pe valori negative a fost necesară obținerea inversului formei închise, realizate anterior.

Desenarea graficului pe valori negative

Cu forma obținută și cu o mască în formă de cerc plin de raza R (raza corespunde valorii de 0, primite din XML) s-a obținut graficul pentru valorile negative.

Graficul pentru valorile negative

Crearea animațiilor de Intro

Animațiile de intro au fost realizate folosind biblioteca de animații TweenMax.  Aceasta e cea mai cunoscută librărie de animații, este gratuită în anumite condiții, foarte bine documentată, ușor de folosit și are performanțe foarte bune.

Pentru început, au fost create cercurile si hexagoanele care  înconjoară liniile, printr-o animație de scalare. Apoi, pe durata a 1,5 secunde, au fost desenate liniile mici de jur împrejur (vezi imaginea de mai jos). În același timp, cu ajutorul unei tranziții de opacitate, și-au făcut apariția și  elementele grafice din spate. Lunile anului au fost puse radial pe un cerc rotit de la 180 grade la 0. Tot printr-o rotație, de data aceasta de 360 grade, au fost animate hexagoanele cele mai mari.

Butoanele care reprezintă anul pentru care se desenează graficul au fost puse pe un arc de cerc, care a crescut de la 0 la 90 de grade. Meniul de jos a fost adus cu ajutorul unei translații pe verticală. Pentru final, a rămas animația butoanelor principale (tranzitate de opacitate) și a graficelor (animarea punctelor de la valoarea 0 la valoarea primită din XML).

Animație linii mici
Exemplu de cod pentru animația de mai sus:

[as3]
/**
* line3 – shape-ul în care desenăm toate liniile
* rLines – raza calculată de la centru la care se desenează liniile
* line3Obj – obiectul cu proprietatea „i” animată de la 0 la 240.
*/
var line3Obj:Object = { i : 0};
TweenMax.to(line3Obj, 1.5, { i: 240, roundProps:[„i”], onUpdateParams:[line3, rLines, line3Obj], onUpdate: onUpdateAnimLine3};

//funcție ce se apelează la fiecare actualizare a animației definite mai sus
protected function onUpdateAnimLine3(line3:Shape, rLines:Number, line3Obj:Object):void {
line3.graphics.clear();

for (var i:uint = 0; i < line3Obj.i; i++) {
//unghiul la care se desenează linia
var angle:Number = i * 2 * Math.PI / 240 – Math.PI / 2;

//liniile cele mai mari orizontale și verticale
if (i % 60 == 0) {
line3.graphics.lineStyle(2, 0x3f3f3f);
line3.graphics.moveTo((rLines) * Math.cos(angle), (rLines ) * Math.sin(angle));
line3.graphics.lineTo((rLines – 22) * Math.cos(angle), (rLines – 22) * Math.sin(angle));
}else if (i % 20 == 0) {
//liniile cele mai mari oblice
line3.graphics.lineStyle(2, 0x3f3f3f);
line3.graphics.moveTo((rLines) * Math.cos(angle), (rLines) * Math.sin(angle));
line3.graphics.lineTo((rLines – 16) * Math.cos(angle), (rLines – 16) * Math.sin(angle));
}else if (i % 2 == 0) {
//liniile mai mici
line3.graphics.lineStyle(1, 0xaeaeae);
line3.graphics.moveTo((rLines – 3) * Math.cos(angle), (rLines – 3) * Math.sin(angle));
line3.graphics.lineTo((rLines – 13) * Math.cos(angle), (rLines – 13) * Math.sin(angle));
}else if (i % 2 == 1) {
//liniile cele mai mici
line3.graphics.lineStyle(1, 0xaeaeae);
line3.graphics.moveTo((rLines – 6) * Math.cos(angle), (rLines – 6) * Math.sin(angle));
line3.graphics.lineTo((rLines – 10) * Math.cos(angle), (rLines – 10) * Math.sin(angle));
}
}
}
[/as3]

Pe lângă cunoștințele de programare, au fost necesare și cunoștințe de matematică pe tot parcursul dezvoltării proiectului, ceea ce l-a făcut interesant, distractiv și provocator în același timp.