Posts tagged: javascript

Mappa dei click sul proprio sito

clickNon so voi, ma diverse volte mi sono chiesto quali sono i punti in cui l’utente effettuasse i click su un sito, in particolare sul mio blog. Sono varie le considerazioni che si possono fare da un’analisi del genere, ad esempio capire quali sono gli elementi più cliccati, se un elemento posto in un certo punto della pagina ha più appeal rispetto ad un altro punto, etc etc. In generale queste mappe mostrano i punti caldi di una pagina web per i quali può essere fatta una serie di analisi. Ciò detto passiamo alla pratica. Cercando un po in rete ho trovato una soluzione open-source che voglio condividere. La soluzione usa javascript per il rilevamento dei click e perl per la costruzione della mappa. Sarebbe interessante tradurre lo script in perl in un altro linguaggio, php o Java ad esempio, così da cambiarne il contesto. Ma procediamo per gradi.

Javascript

Non mi soffermerò molto sul codice javascript che realizza la rilevazione dei click, con l’utilizzo di jquery diventa veramente semplice scrivere 2 righe di codice (si fa per dire), dopo che il DOM si è reso disponibile (document.ready()), si aggancia all’evento onclick e registra le coordinate in cui è avvenuto il click assieme ad altri dati aggiuntivi. Supponiamo quindi che i dati rilevati siano:

x709y351
x350y348
x489y294
x655y346
x384y305
x332y288
x399y288

In questo modo è possibile rilevare le zone della pagina in cui sono avvenuti più click e associare loro dei valori di intensità tali da rappresentarli correttamente sulla mappa finale. A tal proposito assegnamo come valore di intensità massima 255 e come valore di intensità minima 0.

Perl

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/perl
use strict;
my $imgWidth=64;
open (LOG,"log.txt") || die;
my @log=<LOG>;
close (LOG);
my (@x,@y);
my ($xMax,$yMax,$repetitionsMax,$i,$j);
my %repetitions;
foreach my $line(@log){
	(my $coords)=$line;
	$repetitions{$coords}++;
	$coords=~s/x//;
	($x[$i],$y[$i])=split("y",$coords);
	$i++;
}
while ((my $key, my $value)=each(%repetitions)){
	$repetitionsMax=$value if $repetitionsMax<$value;
}
for ($j=0;$j<$i;$j++){
	$xMax=$x[$j] if $xMax<$x[$j];
	$yMax=$y[$j] if $yMax<$y[$j];
}
print $repetitionsMax,"\n$xMax;$yMax\n";

Analizziamo il codice di sopra. Dal file di log contenente le rilevazioni sui click effettuati, vengono lette le coordinate e salvate all’interno di due array $x e $y rispettivamente. Per ciascun valore acquisito viene determinato il valore massimo assoluto e il valore massimo della x e della y. Successivamente si procede con la creazione dell’immagine: 

my $xCanvas=$xMax+int($imgWidth/2);
my $yCanvas=$yMax+int($imgWidth/2);
my $createcanvas="convert -size ". $xCanvas.#//
"x".$yCanvas." pattern:gray100 empty.png";
system ($createcanvas);

impostando le dimensioni calcolate nello step precedente e sfruttando una funzionalità di sistema.
Dopo aver creato l’immagine procediamo col disegnare i punti della nostra mappa, anzi, invece di limitarci a disegnare dei singoli punti, andiamo a creare delle regioni a partire da un file png che ci consente di farlo. Scegliamo come valore di opacità 1 e calcoliamo una formula che ci consenta di determinare il livello di sovrapposizione (overlay) da usare per ciascuna regione. In questo modo le regioni più cliccate saranno sovrapposte e quindi più scure.

my $createNormalizedSpot="convert bolilla.png -fill #//
white -colorize ".int(100/$repetitionsMax)."% bol.png";
system ($createNormalizedSpot);
 
/* Procediamo per ciascuna riga di coordinata */
 
for ($j=0;$j<$i;$j++){
    my ($x,$y);
    $x=$x[$j]-32;
    $y=$y[$j]-32;
    system ("composite -compose multiply -geometry #//
    +$x+$y bol.png empty.png empty.png\n");
    print "used $j of $i clicks\n";
}

Otteniamo quindi un’immagine del genere:

 

empty_p

 

Come piccolo tocco di classe, rendiamo l’immagine creata, in modo tale che abbia il tipico schema di colore delle mappe di calore, in cui i punti più cliccati saranni quelli più caldi e quelli meno cliccati più freddi. Per fare questo usiamo la libreria di Imagemagick, a partire da un file di immagine contenente il gradiente del colore in questione:

convert empty.png -negate full.png
convert full.png colors.png -fx "v.p{0,u*v.h}" final.png

ottenenedo come risultato:

 

map_p

 

La mappa finale

Bene, come risultato finale, prendiamo un’immagine del nostro sito web, ottenuto attraverso uno screenshot di sistema o qualunque altra cosa adatta a farlo e sovrapponiamo la mappa creata con il seguente comando:

composite -blend 40% final.png blog.png heatmap.png

heatmap

E’ facile notare che, guardare l’immagine del risultato fa totalmente un’altro effetto rispetto al piatto file di log da cui siamo partiti.
Stay tuned !!

Vortice di immagini

vorticeQuesta volta vi propongo (o forse è il caso di dire ripropongo) un piccolo trucchetto javascript. Provate a fare una ricerca su google immagini…ricercate qualunque cosa. Dopo di che, fate copia/incolla del seguente scriptlet javascript, direttamente nella barra degli indirizzi del vostro browser, che spero sia Firefox :P

1
2
 
javascript:R=0; x1=.1; y1=.05; x2=.25; y2=.24; x3=1.6; y3=.24; x4=300; y4=200; x5=300; y5=200; DI= document.images; DIL=DI.length; function A(){for(i=0; i<DIL; i++){DIS=DI[ i ].style; DIS.position='absolute'; DIS.left=Math.sin(R*x1+i*x2+x3)*x4+x5; DIS.top=Math.cos(R*y1+i*y2+y3)*y4+y5}R++}setInterval('A()',5 ); void(0)

Premete invio, ehhhh…. Se volete usarlo per far impazzire i vostri visitatori fare pure.

Nested Set + Java + Spring + Postgresql + Pl/pgsql + Yahoo framework

hierarchicE’ da 4-5 giorni che sono alle prese con un problemino, che all’inizio sembrava di facile soluzione, ma alla fine, ha impegnato un pò di tempo e non solo….ha richiesto l’uso di molte tecnologie e alla fine mi ha dato soddisfazione, che ovviamente voglio condividere con voi….voi chi, visto che non posta ancora nessuno? ancora non è chiaro :P Dunque il problema in origine era: come faccio a memorizzare una struttura dati gerarchica all’interno di un database ? Se vi fermate un attimo a pensarci, vi accorgerete che la risposta non è né banale, né immediata.Avevo già utilizzato una soluzione tempo fa, ma mi sono reso conto che non era molto potente dal momento che, la struttura gerarchica per quella particolare specifica era statica, quindi non era possibile aggiungere/eliminare alcun elemento, e per modificarla occorreva un grosso refactoring. Dopo di che mi sono imbattuto nell’algoritmo Preorder traversal tree o Nested set molto potente che consente di memorizzare una struttura gerarchica da albero all’interno di un database relazionale, e mi accorgo che la soluzione da me usata in precedenza ha un nome ben preciso Adjacency List Model che in effetti ha una serie di limitazioni come ho potuto riscontrare sul campo. Non starò qui a descrivere nel dettaglio come funzionano i 2 algoritmi, potete tranquillamente approfondire seguendo i link di sopra che spiegano in modo esaustivo il concetto che sta dietro. Sappiate solo che per risolvere i problemi dell’Adjacency List Model, l’algoritmo Nested Set tende ad aggiungere delle meta-informazioni che permettono di recuperare i dati relativi alla struttura gerarchica al costo di query molto semplici che usano dei self-join. Analizziamo ora lo sviluppo dell’applicazione in blocchi.

  • Business Logic La logica di business include diverse componenti, tra cui Spring il potente framework utilizzato per lo sviluppo di applicazione web J2EE, database Postgresql e il linguaggio procedurale PL/pgsql. La logica di Spring ha richiesto lo sviluppo di un interfaccia che descrive le operazioni possibili sull’albero, una classe che la implementa che definisce la logica delle operazioni e comunica con lo strato del database. Il database contiene la struttura di una tabella per memorizzare le informazioni sull’albero, con le sue meta-informazioni. Ho aggiunto una meta-informazione aggiuntiva che definisce la profondità di ciascun nodo, utile poi in fase di visualizzazione.
     CREATE TABLE nestedset ( idnode serial NOT NULL, nome character varying NOT NULL, descrizione character varying NOT NULL, lft integer NOT NULL, rgt integer NOT NULL, depth integer );

    Tutte le operazioni a livello di database per la gestione dell’albero, sono implementate all’interno del database stesso sotto forma di funzioni procedurali scritte in linguaggio PL/pgsql. Le funzioni realizzate sono:

    • setnodesdepth che aggiorna il campo profondità della tabella subito dopo un operazione di inserimento o cancellazione.
    • insertnode, inserisce un nodo all’interno dell’albero.
    • deletesubtree, elimina un nodo dall’albero. Distinguiamo 2 casi: 1, nodo non ha figli e viene eliminato; 2, nodo ha figli e quindi tutto il sottoalbero viene eliminato.
    • deleteparentnode, elimina un singolo nodo dall’albero. Se il nodo ha figli, questi ultimi vengono spostati verso l’alto di un livello.

    Sono ’slegate’ dall’implementazione Java in modo da poter apportare modifiche senza influire sul codice, ovviamente dipende dalla modica.

  • Presentation logic La logica di presentazione include il framework di Yahoo, in particolare il TreeView Control che mappa l’albero sul componente grafico per visualizzarlo, con in aggiunta un menù contestuale, che permette di realizzare le operazioni di Aggiunta nodo/elimina sottoalbero. Nota:La funzione elimina singolo nodo non è stata mappata ad alcuna voce di menù.

DI seguito trovate alcuni riferimenti sull’argomento e qui il pacchettino con i file sorgenti.

Alla prossima….

 

You need to log in to vote

The blog owner requires users to be logged in to be able to vote for this post.

Alternatively, if you do not have an account yet you can create one here.

Powered by Vote It Up

WordPress Themes