sabato 28 aprile 2012

Una bussola con javascript

Partendo dalla libreria Highstock o Highcharts (http://www.highcharts.com/) è possibile realizzare una semplice ma funzionale bussola in Javascript che indichi i punti cardinali e una direzione.
Come detto sopra occorre la libreria Highstock, la cui licenza è a pagamento ma è possibile scaricarla gratuitamente dal sito per provarla. Ritengo questa forma di vendita davvero intelligente in quanto permette agli sviluppatori di provare il prodotto prima di comprarlo.
Per far funzionare la nostra bussola sarà necessario includere la libreria nel nostro sito. Ci basterà aggiungerla nell'header con questo codice

<script src="http://www.agriculturalsupport.it/wp-content/themes/provisionpress/js/highstock.js" type="text/javascript">

</script>


Passiamo quindi alla creazione di un DIV con un ID specifico all'interno della pagina.



<div id="chart"></div>



A questo punto non dobbiamo fare altro che creare un grafico di tipo "gauge". Ovvero i grafici che indicano un valore con la lancetta. In rete si trovano esempi di come creare gauge a 180° ovvero π, ma noi dovremmo crearlo a 360° o meglio a .

function drawDial(options) {

var mis= 90;

var renderTo = options.renderTo,

    value = options.value,

    centerX = options.centerX,

    centerY = options.centerY,

    min = options.min,

    max = options.max,

    minAngle = options.minAngle,

    maxAngle = options.maxAngle,

    tickInterval = options.tickInterval,

    ranges = options.ranges;

    

var renderer = new Highcharts.Renderer(

    document.getElementById(renderTo),

    240,

    240

);





// internals

var angle,

    pivot;



function valueToAngle(value) {

    return (maxAngle - minAngle) / (max - min) * value-Math.PI/2 + minAngle;

}



function setValue(value) {

    // the pivot

    angle = valueToAngle(value);

    

    var path = [

         'M',

         centerX, centerY,

         'L',

         centerX + mis * Math.cos(angle), centerY + mis * Math.sin(angle)

     ];

    

    if (!pivot) {

        pivot = renderer.path(path)

        .attr({

            stroke: 'black',

            'stroke-width': 3

        })

        .add();

    } else {

        pivot.attr({

            d: path

        });

    }

}



// background area

renderer.arc(centerX, centerY, mis+5, 0, minAngle, maxAngle)

    .attr({

        fill: {

            linearGradient: [0, 0, 0, 200],

            stops: [

                [0, '#FFF'],

                [1, '#DDD']

            ]

        },

        stroke: 'silver',

        'stroke-width': 1

    })

    .add();





// ranges

$.each(ranges, function(i, rangesOptions) {

    renderer.arc(

        centerX,

        centerY,

        mis,

        mis-5,

        valueToAngle(rangesOptions.from),

        valueToAngle(rangesOptions.to)

    )

    .attr({

        fill: rangesOptions.color

    })

    .add();

});



// ticks

var dir;

for (var i = min; i <= max; i += tickInterval) {

dir=''

        if (i==0){dir='N'}

    if (i==90){dir='E'}

    if (i==180){dir='S'}

    if (i==270){dir='W'}

            if (i==360){dir='N'}

    angle = valueToAngle(i);

    

    // draw the tick marker

    renderer.path([

            'M',

            centerX + 90 * Math.cos(angle), centerY + 90 * Math.sin(angle),

            'L',

            centerX + 70 * Math.cos(angle), centerY + 70 * Math.sin(angle)

        ])

        .attr({

            stroke: 'silver',

            'stroke-width': 2

        })

        .add();

    

    // draw the text

    renderer.text(

            dir,

            centerX + 90 * Math.cos(angle),

            centerY + 90 * Math.sin(angle)

        )

        .attr({

            align: 'center'

        })

        .add();

    

}



// the initial value

setValue(value);



// center disc

renderer.circle(centerX, centerY, 20)

    .attr({

        fill: '#4572A7',

        stroke: 'black',

        'stroke-width': 1

    })

    .add();



return {

    setValue: setValue

};



}

    

    

// Build the dial

var dial = drawDial({

    renderTo: 'statsframe',

    value: 250, //<-- questo valore espresso in gradi indica la direzione

    centerX: 120,

    centerY: 120,

    min: 0,

    max: 360,

    minAngle: 0,

    maxAngle: 2*Math.PI,

    tickInterval: 45,

    ranges: [{

        from: 0,

        to: 45,

        color: '#D3fd53'

    }, {

        from: 45,

        to: 90,

        color: 'transparent'

    }, {

        from: 90,

        to: 135,

        color: '#D3fd53'

    }, {

        from: 135,

        to: 180,

        color: 'transparent'

    }, {

        from: 180,

        to: 225,

        color: '#D3fd53'

    }, {

        from: 225,

        to: 270,

        color: 'transparent'

    }, {

        from: 270,

        to: 315,

        color: '#D3fd53'

    }, {

        from: 315,

        to: 360,

        color: 'transparent'

    }]

});


Nel codice soprastante la variabile "mis" è utilizzata per stabilire la grandezza della nostra bussola. Assegnandole valori più grandi si ingrandirà anche la bussola. Dobbiamo però prestare attenzione anche ai parametri della variabile "render" che vanno a stabilire larghezza e lunghezza del div su cui la bussola viene rappresentata.
Per direzionare l'ago della bussola non dobbiamo fare altro che cambiare il valore del parametro "value" nella variabile dial, che è quella che costruisce il grafico. Il valore è espresso in gradi, perciò se vogliamo indicare il Nord il valore da assegnare sarà 0 (o 360), per l'Est sarà 90, per il Sud 180, per l'Ovest 270. Ovviamente possiamo assegnare un qualsiasi valore intermedio.

Nessun commento:

Posta un commento