Looge ja muutke JavaScripti abil asjade Internetiga ühendatud andurite andmete SVG-graafikat
Joonistamist käsitleva artiklisarja viimases osas graafika asjade Internetti ühendatud andurite andmetega, on aeg rääkida, kuidas luua või muuta JavaScript joonised formaadis SVG ja mõned elemendid HTML mis toimivad konteinerina või esitavad graafikale täiendavat teavet.
Selle õpetuse sihtkasutajad peaksid moodustama elektroonika- ja arvutiprogrammeerimisprofiili. mikrokontrollerid, nad ei pruugi olla tuttavad HTML, CSS o SVG; Sel põhjusel tehti eelmistes osades keele või vastava tehnoloogia lühitutvustus. Selles viimases osas on lähenemine veidi erinev, kuna lugejad oskavad kindlasti programmeerida, on võimalik, et keelt kasutades C + + see, nagu JavaScript, jagab põhisüntaksit C ja seda võib võtta kui viidet enamiku põhiliste programmeerimiskontseptsioonide vahelejätmiseks ja seega keskenduda erinevustele ja konkreetsele kasutamisele, mis meid asjade Internetis sensorgraafika loomiseks huvitab.
Nimi annab vihje esimesele erinevusele: JavaScript See on programmeerimiskeel käsikiri (sidekriips) ja sellisena see on tõlgendatud, seda pole vaja koostada; kontekst, milles käsikiri (näiteks veebibrauser) loeb, tõlgib ja täidab korraldusi. Kui täpne olla, siis enamikul juhtudel on olemas a käitusaegne kompileerimine (JIT), vaid koodi kirjutamise protsessi jaoks JavaScript See ei mõjuta meid, me lihtsalt kirjutame koodi ja see võib töötada.
Nimes sisaldub ka esimene segadus: JavaScript ei oma vähimatki suhet Java. Esialgu, kui see välja töötati Netscape oma brauseri jaoks nimetati seda kõigepealt Mochaks ja seejärel vähem segaseks LiveScriptiks. Pärast selle edukat rakendamist brauserites ja nende ületamist standardiseeriti see järgmiselt ECMAScript (To ECMA-262, versioon 6 kirjutamise ajal), et muutuda seda rakendavate brauserite suhtes neutraalseks. Praegu on olemas ka standard ISO alates versioonist 5, 2011 (ISO / IEC 16262: 2011 artikli kirjutamise ajal)
Muutujad, põhiandmetüübid ja objektid JavaScriptis
Erinevalt sellest, mis juhtub näiteks aastal C + +, en JavaScript andmetüüpi muutuja deklareerimisel ei arvestata ja ka muutujaga seotud tüüp ei ole fikseeritud, on võimalik kogu programmi täitmise jooksul omistada erinevat tüüpi väärtust.
1
2
3
4
5
6
7
|
var cosa;
cosa=“texto”;
console.log(typeof cosa); // Debería mostrar string en la consola
cosa=123;
console.log(typeof cosa); // Debería mostrar number en la consola
cosa={temperatura:22,corriente:1.5};
console.log(typeof cosa); // Debería mostrar object en la consola
|
Eelmises näites on muutuja "asi" deklareeritud (andmetüüpi märkimata), seejärel määratakse teist tüüpi andmed ja seda uuritakse typeof
tüüp, mis JavaScript mida ta on tõlgendanud. Koodi silumiseks võite selle kirjutada veebibrauseri inspektori konsooli (mis ei mõjuta veebi esitlust) console.log()
.
Andmete, eriti teksti numbriteks teisendamise sundimiseks saate kasutada selliseid funktsioone nagu parseInt()
o parseFloat()
mis teisendavad vastavalt täisarvudeks või ujukomaarvudeks. Vastupidise teisenduse saab teha String()
, kuigi see pole tõenäoliselt vajalik, kuna tavaliselt piisab automaatsest teisendamisest. Koos parseFloat()
Näiteks võite saada veebilehe atribuudi väärtuse (nt ühikuid sisaldava objekti laiuse või kõrguse); Sel viisil väljendus parseFloat("50px");
tagastab tulemuseks numbrilise väärtuse 50.
En JavaScript topelt- ja üksikjutumärkidel ei tehta vahet; Mõlemal juhul on andmetüüp string
, ja igaüks neist võib sisaldada teist ilma paokoode kasutamata.
1
2
3
4
5
6
7
8
9
10
|
var texto;
console.log(typeof texto); // Debería mostrar string en la undefined
texto=“esto es un texto”;
console.log(typeof texto); // Debería mostrar string en la consola
texto=‘A’;
console.log(typeof texto); // Debería mostrar string en la consola
texto=“esto es un ‘texto'”;
console.log(typeof texto); // Debería mostrar string en la consola
texto=‘”A”‘;
console.log(typeof texto); // Debería mostrar string en la consola
|
Eelmises näites on näha, et muutuja, kui see on deklareeritud (olemas), kuid sellele pole väärtust omistatud, sisaldab määratlemata andmetüüpi (undefined
). Määramata objektil on väärtus null
; See tähendab, et objekt on olemas, kuid ilma väärtuseta; muutujal, mis sellele viitas, ei oleks a typeof
undefined
aga object
. Objekt võib olla ka tühi, st mitte null, kuid sellel ei ole mingeid omadusi.
et defineerige sees objekt JavaScript on suletud traksidega ({
y }
) omadused või meetodid, eraldatuna kooloniga (:
) atribuudi nimi atribuudi väärtus ja komaga (,
) erinevad omadused. Lisateavet selle objekti väljendamise viisi kohta leiate artiklist JSON-vorming.
Kuigi võite kasutada süntaksit, mis võib panna teid teisiti mõtlema, en JavaScript Pole klasse, vaid prototüübidSee tähendab, et objekti omaduste ja meetodite pärimiseks luuakse teine objekt (prototüüp), mida teised (lapsed) kasutavad viitena. Stiilile lähim süntaks JavaScript prototüübi kasutamine on Object.create
kuigi seda on ka võimalik (ja mõnikord kasulik) kasutada new
nagu ka teistes objektorienteeritud keeltes.
1
2
3
4
|
var perro=new Mamifero(); // Esto funciona, pero no es exactamente el nuevo estilo JavaScript
console.log(perro instanceof Mamifero);
var gato=Object.create(Mamifero); // Crear un objeto usando un prototipo al estilo JavaScript
console.log(Mamifero.isPrototypeOf(gato));
|
et päring, kas üks objekt on teise eksemplar, kui kasutate seda prototüübina, kui päridate selle omadused, ühesõnaga saate kasutada instanceof
(loodud koos new
) Või isPrototypeOf
(loodud koos Object.create
), mis hindab tõeseks, kui objekt kasutab prototüüpi, ja vääraks, kui seda ei kasuta.
Kui objekt on loodud kasutades teist prototüübina, st kui objekt on instantseeritud, saab seda lisage uusi atribuute või tühistage prototüübi atribuudid kasutades punktisüntaksit nagu näidatud gato.peso=2.5
.
La massiivid sisse JavaScript Need erinevad neist, mida te ilmselt teate C. Alustuseks deklareeritakse need ilma nende pikkust märkimata, ainult avamise ja sulgemise nurksulgudega ([
y ]
), võivad komponendid olla heterogeensed (samas massiivi erinevad andmetüübid) ja uusi elemente saab lisada ilma piiranguteta. Maatriksid JavaScript on tegelikult loendid (kogud) elementidest, millele millele viidatakse numbrilise indeksi või nimega. Massiiv võib samaaegselt sisaldada numbrilisi indekseid ja elementide nimesid, kuid teise tüübi kasutamiseks kasutatakse tavaliselt objekte (atribuute).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
// Declarar matrices (arrays)
var preparada=[]; // La matriz ha sido declarada pero (todavía) no contiene valores
var cosas=[“silla”,“mesa”,“caja”]; // Matriz declarada con componentes formada por cadenas de texto
var valores=[200,“lleno”,0.5,true,“simple”,false,false,10]; // Matriz declarada con componentes heterogéneos
var ramas=[20,“abc”,[1,2,3],false,[10,20,[“uno”,“dos”]]]; // Matriz que contiene matrices
var demode=new Array(10,20,30,4,3,2,1); // La sintaxis con new no es la preferida de JavaScript aunque funciona…
var peligrosa=new Array(10); // …pero con el riesgo de confundir índices con elementos: la matriz peligrosa tiene 10 elementos, no un elemento de valor 10
// Acceder a los valores de la matriz
preparada.push(33.33); // Añade un nuevo valor al final de la matriz
console.log(“La matriz ‘preparada’ contiene “+preparada.length+” elementos”); // Ahora contine 1 elemento
console.log(cosas[0]); // Muestra en la consola el primer valor de la matriz (las matrices empiezan en el índice cero)
cosas[2]=“tarro”;
preparada[10]=50; // Los índices no tienen que ser consecutivos
console.log(“La matriz ‘preparada’ contiene “+preparada.length+” elementos”); // Ahora contine 11 elementos
console.log(“Elemento sexto: “+preparada[5]); // undefined
// Verificar si una variable es (apunta a) una matriz
console.log(Array.isArray(cosas)); // Nuevas versiones de JavaScript (ECMAScript versión 5 o superior)
console.log(cosas instanceof Array); // Implementaciones de JavaScript (ECMAScript) más viejas
// Para esto es mejor usar objetos
var frutas=[];
frutas[“peras”]=20;
frutas[“manzanas”]=30;
frutas[4]=10;
console.log(frutas.peras);
console.log(frutas[“manzanas”]);
console.log(frutas[4]);
console.log(frutas[3]); // undefined
|
Nagu eelmisest näitest näha, saate teada, kas muutuja vastab massiivi eksemplarile (see on massiiviobjekt), instanceof
, nagu on juba kasutatud üldiste objektide puhul või uuemates versioonides JavaScript võite pöörduda Array.isArray()
Massiivi elementidele juurde pääsemiseks võite kasutada selle indeksit (matriz[7]
) või atribuudi nime järgi, mille nimi on nurksulgudes (matriz["nombre"]
) või objektide jaoks tavalise punktisüntaksiga (matriz.nombre
). Kuna nimi on tekstistring, saab selle koostamiseks kasutada avaldist, sealhulgas muutujaid. Atribuutidega massiivi läbimiseks võib kasutada vorminguga tsüklit for(propiedad in matriz)
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
var matriz=[];
matriz[“color”]=“verde”;
matriz[“grosor”]=10;
matriz[“estado”]=“nuevo”;
matriz[0]=25.0;
matriz[1]=“uno”;
for(propiedad in matriz)
{
console.log(propiedad+” valor “+matriz[propiedad]);
}
/* El resultado en la consola será:
0 valor 25
1 valor uno
color valor verde
grosor valor 10
estado valor nuevo
*/
|
Seda on meie eesmärgi jaoks huvitav ravida objekt Date
, millega saate kuupäeva ja kellaaega esitada ja hallata JavaScript. Objekti saab luua ilma andmeteta, nii et see võtab praeguse kuupäeva ja kellaaja või selle saab luua, näidates väärtusena kuupäeva, kas millisekundites alates 1. jaanuarist 1970 (näiteks Unixi aeg või POSIX aeg kuid väljendatuna sekundite asemel millisekundites) või määrates eraldi aasta, kuu, päeva, tunni väärtused...
Objekt sisaldab täielikku seeriat kuupäeva ja kellaaja päringu või seadmise meetodid:
-
now()
Tagastab praeguse kuupäeva ja kellaaja millisekundites alates 1. jaanuarist 1970 -
getTime()
|setTime()
Hangib või muudab vastavalt ajaväärtust millisekundites alates 1. jaanuarist 1970. KasutadesvalueOf()
, mis on enamikus objektides esinev meetod, saadakse ka vastava Date objekti väärtus, ntgetTime()
koos Unixi aeg või POSIX aeg väljendatud ms-des. -
getMilliseconds()
|setMilliseconds()
Kasutatakse objekti murdosa millisekundiosa pärimiseks või määramiseksDate
millel see täidetakse. Kui konsulteerida, on saadud väärtus vahemikus 0 kuni 999, kuid saab määrata suuremaid väärtusi, mis kogunevad kogu kuupäeva ja kellaaega, nii et nagu ülejäänud hankimismeetodid, aitab see suurendada objekti väärtustDate
(või vähendage seda, kui kasutatakse negatiivseid väärtusi). -
getSeconds()
|setSeconds()
Tagastab või muudab vastavalt objekti sekundite väärtustDate
. -
getMinutes()
|setMinutes()
Kasutatakse objekti konsultatsiooniks või protokolli määramiseksDate
. -
getHours()
|setHours()
Võimaldab vaadata või muuta objekti tunde (0 kuni 23).Date
. -
getDay()
Tagastab kuupäeva jaoks nädalapäeva, mis on väljendatud väärtusena vahemikus 0 kuni 6 (pühapäevast laupäevani). -
getDate()
|setDate()
Tagastab või muudab objekti kuu päevaDate
millele seda rakendatakse. -
getMonth()
|setMonth()
Kasutatakse objekti kuunumbri vaatamiseks või muutmiseksDate
. -
getFullYear()
|setFullYear()
Küsib või määrab kuupäeva ja kellaaega sisaldava objekti aasta väärtuse.
Varasemad meetodid Date
lisada versioon UTC et oleks võimalik töötada otse universaalajaga, ilma vahepealseid arvutusi tegemata. Selles mõttes näiteks getHours()
omab versiooni getUTCHours()
o getMilliseconds()
alternatiiv getUTCMilliseconds()
töötada vaheldumisi ametliku (seadusliku) või universaalajaga. Koos getTimezoneOffset()
Saate teada, mis vahe on universaalaja ja kohaliku ametliku aja vahel.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
var dia_semana=[“domingo”,“lunes”,“martes”,“miércoles”,“jueves”,“viernes”,“sábado”];
var nombre_mes=[“enero”,“febrero”,“marzo”,“abril”,“mayo”,“junio”,“julio”,“agosto”,“septiembre”,“octubre”,“noviembre”,“diciembre”];
var digitos_hora;
var hoy=new Date();
var texto_hoy=“”;
texto_hoy+=“Hoy es “;
texto_hoy+=dia_semana[hoy.getDay()];
texto_hoy+=“, “;
texto_hoy+=hoy.getDate();
texto_hoy+=” de “;
texto_hoy+=nombre_mes[hoy.getMonth()];
texto_hoy+=” de “;
texto_hoy+=hoy.getFullYear();
texto_hoy+=” y son las “;
digitos_hora=hoy.getHours();
texto_hoy+=digitos_hora>9?digitos_hora:“0”+digitos_hora;
texto_hoy+=“:”;
digitos_hora=hoy.getMinutes();
texto_hoy+=digitos_hora>9?digitos_hora:“0”+digitos_hora;
texto_hoy+=“:”;
digitos_hora=hoy.getSeconds();
texto_hoy+=digitos_hora>9?digitos_hora:“0”+digitos_hora;
|
JavaScripti funktsioonid
Kui loete seda, teate kindlasti, kuidas programmeerida. mikrokontrollerid en C aastal C + + ja tunnevad funktsiooni mõistet. Kuigi põhiidee on sama, in JavaScript Nende määratlemise ja kasutamise viis on veidi erinev. Alustuseks on juba öeldud, JavaScript See ei kasuta selgesõnaliselt andmetüüpe, nii et te ei pea seda funktsiooni määratlemisel märkima. Järgima, Funktsioonil ei ole kohustuslik nimi, need võivad olla anonüümsed. Neid saab seostada muutujaga, et neid välja kutsuda, kuid see ei pruugi olla vajalik, kuna mõnikord on kasulik neid kohe välja kutsuda, mille jaoks lisatakse sulud ja parameetrid pärast funktsiooni määratlust.
Funktsiooni määratlemiseks lisage eesliide function
, kui see on olemas, kirjutage sulgudesse nimi, argumendid (funktsioonile edastatud parameetrid) ja funktsiooni käivitamisel käivitatav kood sulgudes.
1
2
3
4
5
|
function doble(numero)
{
var resultado=numero*2;
return resultado;
}
|
Kindlasti ei olnud eelmises näites muutujat "tulemus" üldse vaja, kuid see on hea ettekääne, et meeles pidada muutuv ulatus, mis töötab ootuspäraselt: muutuja "result" eksisteerib ainult funktsiooni "double" sees. sisse JavaScript saab ka kasutada let
, selle asemel var
, et hõlmata muutuja koodiploki konteksti (sulgudes, {
y }
)
Eelmises jaotises objektidest rääkides jäi midagi põhjapanevat puudu: atribuudid on defineeritud, kuid meetodeid pole defineeritud. Ootuspäraselt, objektmeetodid on funktsioonid, neil pole nime ja neid kasutatakse (kutsutakse välja) objekti definitsiooniga määratud (oma)nimest.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
var
termostato=
{
temperatura_actual:0.0,
temperatura_frio:18.5,
temperatura_calor:22.0,
consumo:0,
ver_temperatura:
function()
{
console.log(“Temperatura actual: “+this.temperatura_actual+” °C”);
}
}
|
Eelmises näites on juba olemas meetod "view_temperature", mis kuvab konsooli kaudu atribuudi "current_temperature" väärtust. See pole eriti kasulik, kuid annab täielikuma ülevaate sellest, milline on objekti määratlus JavaScript.
Objekti (funktsioonide) meetoditele selle omaduste juurde pääsemiseks kasutage this
, nagu ka eelmises näites real 11, kui kasutate atribuuti "current_temperature".
Juurdepääs JavaScriptiga dokumendiobjekti mudelile (DOM).
pärit JavaScript Teil on juurdepääs selle veebilehe sisule, millel see töötab, ja ka seda lehte kuvava brauseri teatud aspektidele, kuigi mitte süsteemiressurssidele. Andmestruktuur, mis toetab atribuute ja meetodeid, millele pääsete juurde JavaScript osa aknaobjektist, täpsemalt objekti (dokumendi) sisu HTML) vastab objektile document
. Kuigi seda kasutatakse mõnikord selguse huvides, ei ole nendele viitamiseks vaja meetoditele või omadustele eelneda aken, piisab näiteks document
, pole vaja kirjutada juurobjekti nime nagu on window.document
, seni kuni viidatakse praegusele aknale.
Enimkasutatav vorm leida dokumendist objekt HTML Seda meetodi kaudu getElementById()
, millele antakse argumendina edasi koodi loomisel märgitud id HTML. Eelmistes osades selgitatu põhjal on lihtne eeldada, et pääsete ligi ka objekti sees olevatele komponentidele document
kasutades punkti süntaksit (document.componente
) või sulgudes, kasutades mõlemat nime (document["componente"]
), kõige kasulikum, näiteks numbriline indeks, mida on raske kasutada ja käsitsi koostatud veebilehe sisule juurdepääsul ebapraktiline.
koos JavaScript saate hankige element, mis sisaldab teist elementi (element või emasõlm) oma kinnisvaraga konsulteerimine parentNode
või teie vara parentElement
, erinevus seisneb selles, et põhielement (parentElement
) stringi viimasest elemendist DOM See on null (null
) ja emasõlm (parentNode
) on dokument ise (document
).
et muuta elemendi sisu HTML, näiteks sildi oma <div>
, Seda saab kasutada innerHTML
ja selle atribuutide muutmiseks saate määrata sellele mõne muu klassi className
või muuta selle omadusi eraldi style
. Veebilehe elemendi kuvatava stiili vaatamine pole tingimata kasulik style
kuna see võib sõltuda mitmest tegurist või pole lihtsalt selgesõnaliselt määratletud. Veebilehel lõpuks kuvatava elemendi stiili kontrollimiseks kasutatakse meetodit getComputedStyle.
Dokumendi elemendile HTML Selle välimuse ja käitumise määramiseks saab sellele määrata mitu klassi hallata objekti klasside loendit JavaScript võite pöörduda classList
mis pakub meetodeid add
uue klassi lisamiseks loendisse, remove
selle eemaldamiseks, toggle
selle asendamiseks või elemendi klassiloendi sisuga tutvumiseks item
ja contains
, mis tagastab klassi, mis asub loendis teatud positsioonil, ja väärtuse true
o false
kas teatud klass on loendis või mitte.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
var contenedor_temperatura=document.getElementById(“temperatura”); // Encontrar el div con id=”temperatura”
contenedor_temperatura.innerHTML=“”; // Eliminar el contenido provisionalmente para que no se vean los cambios
contenedor.className=“bloque_temperatura”; // Asignar una nueva clase
if(temperatura>20) // Si la temperatura es mayor que 20 °C…
{
contenedor.style.color=“#FF6666”; // …usar el color rojo en lugar del color normal de la clase
}
contenedor_temperatura.innerHTML=“La temperatura es “+temperatura+” °C”; // Cuando el aspecto esté preparado mostrar el valor
if(document[“titulo”].classList.contains(“estilo_titulo”)) // Si el objeto “titulo” tiene la clase “estilo_titulo”…
{
if(document[“titulo”].classList.contains(“general”)) // …y la clase “general”…
{
document[“titulo”].classList.remove(“general”); // …quitar la clase “general”
}
}
else // Si el objeto “titulo” no tiene la clase “estilo_titulo”…
{
document[“titulo”].classList.add(“estilo_titulo”); // …añadir la clase “estilo_titulo” (da igual que tenga o no la clase “general”)
}
|
Eelmises näites asub see koos getElementById
objekt, mida soovite manipuleerida (element <div>
tema eest id
), enne välimuse muutmist kustutatakse sisu, määrates innerHTML
tühja tekstistringi, määratakse sellele uus klass className
ja selle stiili on muudetud style
sõltuvalt sisu väärtusest (temperatuurist) värvi muutmine, kui see on asjakohane, läbi vara color
. Kui aspekt on kindlaks määratud, kirjutatakse väärtus uuesti kasutades innerHTML
.
Ülaltoodud näite teises osas (read 9 kuni 19) pääseb juurde koodielemendile HTML kasutades süntaksit document[]
ja vara id
elemendi klassiloendi muutmiseks meetodiga classList.remove()
ja meetodigaclassList.add()
, mis põhineb mitme tingimusliku täitmise käigus sooritatud päringu tulemusel, mida nad võrdlevad kasutades classList.contains()
.
Millal see läheb viidata elemendile HTML mitu korda kogu koodi jooksul JavaScript, see on vähe tõhusam määrata see muutujale või kasutage nime asemel selle indeksit, kuna vastasel juhul kasutaksite meetodit JavaScript selle iga kord hankimine eeldab selle nime otsimist, mis võtab veidi rohkem aega kui muutujale juurdepääsu korral.
et lisada dokumenti uusi objekte HTML, saab need kõigepealt luua meetodiga createElement
de document
ja hiljem lisada need ülejäänud elementidele puu punktis, mis on vajalik appendChild
. Objekti loomiseks XML, nagu esemed SVG mida kasutame asjade Interneti-andurite graafiku joonistamiseks, saate kasutada createElementNS
(NS jaoks nimeruum). Nagu vormingust rääkides selgitatud SVG, on sellele vastav nimeruum (praeguse versiooni jaoks). http://www.w3.org/2000/svg
, mis tuleks edastada createElementNS
argumendina koos elemendi tüübiga, svg
, sel juhul.
A. alternatiiv innerHTML
teksti lisamiseks dokumendielemendile sisuna HTML on meetod createTextNode()
objekti document
. Selle alternatiiviga saate luua uus tekst (millele pääseb juurde hiljem, kui see on määratud muutujale), mis lisatakse objektipuusse meetodiga appendChild()
. Nagu alternatiiv appendChild()
, mis lisab uue sisu selle lõppu, mis on juba olemas sõlmes, kuhu see lisatakse, saate kasutada meetod insertBefore()
, mis lisab uue objekti olemasoleva ette. Kanda insertBefore()
asemel appendChild()
pakub meetodit, mis teenib näiteks sorteerida uusi objekte olemasolevate ette kui element peab olema teise ees (nagu loendis) või katma või olema kaetud graafilise struktuuriga, milles on esiplaanile või taustale lähemal olevad elemendid.
Reageerige sündmustele JavaScriptiga
Kui viis kasutage veebilehte asjade Internetiga ühendatud andurite graafikute konteinerina seda kasutati onload
Sildil <body>
graafiku joonistamise alustamiseks. See atribuut, mis on seotud koodiobjektidega HTML, viitab Sündmused JavaScript. Nagu juba selgitatud, täidab see funktsiooni, kui leht on laaditud. Kuigi seda on koodiga seostatud HTML et seda rohkem meeles pidada, oleks see võinud koodis kirjas olla JavaScript kui body.onload=dibujar;
olemine dibujar
funktsiooni nimi, mis tuleks veebilehe laadimisel käivitada.
Rakenduse uusimates versioonides JavaScript sündmusi saab seostada funktsioonidega, mis kasutavad addEventListener
vorminguga objeto.addEventListener(evento,función);
või kasutades süntaksit objeto.evento=función;
mis töötab ka vanemates rakendustes. Sündmusega seotud funktsiooni linkimise tühistamiseks peate removeEventListener
millel on sama formaat nagu addEventListener
.
JavaScript See on võimeline reageerima paljudele sündmustele, mis võivad veebilehel aset leida. Näiteks suudab see tuvastada, millal elemendil klõpsatakse HTML koos onmousedown
või kui klõpsate nupuga onclick
, kui klahvi vajutatakse onkeydown
, kasutades kerimisriba nupuga onscroll
. Meie eesmärgi saavutamiseks piisab meile sellest tuvastada lehe laadimine onload
ja selle suuruse muutmine koos onresize
. Seome need sündmused objektidega body
y window
kohta DOM vastavalt. Esimese saab määrata koodis HTML, nagu näha ja teine koodi sees JavaScript funktsiooni sees, mille kutsus esimene ja vorminguga window.onresize=redimensionar;
olemine redimensionar
funktsioon, mida kutsutakse välja iga kord, kui akna suurus muutub.
Jookse pärast teatud ajavahemikku
JavaScript jaoks on kaks ressurssi edasilükatud täitmine: setTimeout
, mis täidab funktsiooni pärast ajavahemikku ja setInterval
mis käivitab funktsiooni iga teatud ajaintervalli järel. Mõlemad meetodid nõuavad parameetritena (1) käivitatavat funktsiooni ja (2) millisekundites väljendatud ajavahemikku. Nende toimimise peatamiseks saate määrata nende funktsioonide tagastatud tulemuse muutujatele ja edastada need argumendina clearTimeout
või clearInterval
kui te ei soovi neid uuesti välja kutsuda (või kui te ei soovi, et neid esimest korda täidetaks) setTimeout
o setInterval
vastavalt.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
var cuenta_atras=setTimeout(descansar,1000*60*20); // Recordar que hay que descansar cuando pasen 20 minutos
var repeticion=setInterval(consultar_correo,1000*60*5); // Revisar el correo cada 5 minutos
function descansar()
{
alert(“Puedes descansar un rato”); // Esto solamente aparecerá una vez
}
function consultar_correo()
{
alert(“Revisa el correo electrónico”); // Esto aparecerá cada cinco minutos
}
function detener_cuenta_atras() // No utiliza argumentos sino la variable global
{
clearTimeout(cuenta_atras); // Detener la cuenta atrás para avisar a los 20 minutos
}
function no_avisar_lectura_correo() // No utiliza argumentos sino la variable global
{
clearInterval(repeticion); // Dejar de avisar cada 5 minutos
}
|
Eelmises näites tutvustatakse meetodit alert
mis on ette nähtud hoiatusmärgi kuvamiseks. Kuigi seda kasutati varem laialdaselt, on see praegu koodist peaaegu keelatud JavaScript sest kui agressiivne (pealetükkiv) on veebilehe katmine dialoogiboksiga.
A jaoks kirjutatud programmis mikrokontroller väikesest seeriast (näiteks plaadil olev). Arduino uno) on levinud globaalsete muutujate kasutamine, nagu eelmises näites JavaScript, kuna kood on lühike ja mitte eriti segane, kuna sageli rakendatakse funktsioone ad hoc ja kuna globaalsete muutujate kasutamine võimaldab ennustada mälukasutust väga lihtsalt ja intuitiivselt, mis on väheste ressurssidega süsteemides ülioluline . Selle asemel en JavaScript Üldine on vähendada globaalsete muutujate kasutamist võimalikult miinimumini. kuna see ei pea mälukasutusega kiirustama, kuna see töötab tavaliselt a Protsessor ressurssidega, mis on palju paremad kui a MCU, kuna see eksisteerib tõenäoliselt koos paljude kolmanda osapoole koodidega, millega see peab töötama ilma sekkumiseta ja kuna tegemist on avatud süsteemiga, ei saa tulevast täitmiskonteksti ennustada ( mikrokontroller Small määrab selle toimimise täielikult kindlaks, lisamata rohkem koodi, kui see on töökorras) ja kuna rakenduste mõõtmed võivad lugemise raskendada, kui kood ei kapselda selle toimimist, muutes meetodid võimalikult iseseisvaks.
Matemaatilised toimingud JavaScript Math objektiga
Keerulisemate matemaatilise arvutamise matemaatilised tehted on objektis grupeeritud Math
. Seda objekti kasutatakse otse, sellesse kaasatud meetodite või omaduste (konstantide) kasutamiseks pole seda vaja instantseerida.
Math.abs(n)
Parameetri n absoluutväärtusMath.acos(n)
Parameetri n arkosiinus (tulemus radiaanides)Math.asin(n)
Parameetri n arcsiinus (tulemus radiaanides)Math.atan(n)
Parameetri n arktangent (tulemus radiaanides)Math.atan2(n,m)
Arktangent n/m (tulemus radiaanides)Math.ceil(n)
Ümarda parameeter lähima täisarvuni ülesMath.cos(α)
Parameetri α koosinus (α radiaanides)Math.E
e-number (≃ 2.718281828459045)Math.exp(n)
e tõstetakse parameetrini n: enMath.floor(n)
Ümarda parameeter n lähima täisarvuni allapooleMath.log(n)
Parameetri n naturaallogaritm (baas e).Math.LN2
Naturaallogaritm (baas e) 2-st (≃0.6931471805599453)Math.LN10
Naturaallogaritm (baas e) 10-st (≃2.302585092994046)Math.LOG2E
e 2. aluse logaritm (≃ 1.4426950408889634)Math.LOG10E
e 10. aluse logaritm (≃ 0.4342944819032518)Math.max(a,b,c,…)
Läbitud parameetrite loendi suurim väärtusMath.min(a,b,c,…)
Läbitud parameetrite loendi väikseim väärtusMath.PI
Number π (≃3.141592653589793)Math.pow(n,m)
Esimene parameeter n tõstetakse teiseks parameetriks m: nmMath.random()
(Peaaegu) juhuslik arv vahemikus 0.0 kuni 1.0Math.round(n)
Ümarda parameeter n lähima täisarvuniMath.sin(α)
Parameetri α siinus (α radiaanides)Math.sqrt(n)
Ruutjuur parameetrist nMath.SQRT1_2
Ruutjuur 1/2-st (≃0.7071067811865476)Math.SQRT2
Ruutjuur 2-st (≃1.4142135623730951)Math.tan(α)
Parameetri α tangens (α radiaanides)
Laadige andmed serverist AJAX-iga
IoT-sse salvestatud teabe joonistamiseks kasutatav meetod seisneb andmete aeg-ajalt serverist laadimises ja graafiku ümberkujundamises, millega need on esitatud. Andmete lugemiseks serverist kasutatakse tehnoloogiat AJAX (asünkroonne JavaScript ja XML) objekti kaudu XMLHttpRequest
de JavaScript. Andmegraafiku joonistamine toimub objekti taaskasutamise teel SVG mis on juba koodis HTML ja see sisaldab graafikut, mille koordinaate on muudetud, et need vastaksid uutele laaditud andmetele.
Selle ettepaneku näites uuendatakse lisaks joonise uuendamisele ka veebilehel olevat teksti, mis näitab iga graafiku puhul viimaste mõõdetud andmete kuupäeva ja väärtust.
Serveri poolel on andmebaas, mis sisaldab teavet et asjade internetiga ühendatud andurid on jälginud. Seda andmebaasi loeb objektipäring XMLHttpRequest
vastates koodisse kodeeritud teabega JSON-vorming, kuigi kasutatud meetodi nimi viitab seosele vorminguga XML.
Esimeses polaridad.es õpetuses teemal IoT andmete salvestamine Näete näidet infrastruktuurist, mis haldab asjade Internetiga ühendatud seadmete pakutavat teavet serveri poolelt. Selles artikliseerias kasutatakse ressursina serverit Apache millest saate programmeerimiskeelt kasutada PHP andmebaasi pääsemiseks MySQL o MariaDB. IoT-i toetamiseks kasutatavates serverites on andmebaaside leidmine väga levinud MongoDB (NoSQL) ja programmeerimiskeelt JavaScript edasi Node.js tarkvara infrastruktuurina.
Järgmine funktsioon vastutab serverist ühelt andurilt uusimate andmete küsimise eest. Funktsioonikutses kasutatakse objekti argumendina JavaScript mis toetab joonistatud andmeid. Kui sama graafik esindab mitut väärtust, näiteks visuaalseks korrelatsiooni otsimiseks, võib serverile esitada päringu mitme samaaegse tagastamiseks, mis on serveri tööviisist tulenevalt optimaalsem meetod. HTTP protokoll.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
function consultar_ultimo_valor_sensores(objeto_grafico)
{
var consulta=‘zona=”+objeto_grafico.sufijo_nombre;
var pagina=“ultimo_valor_sensor.php”;
var resultado;
var ajax;
if(window.XMLHttpRequest)
{
ajax=new XMLHttpRequest(); // ajax=Object.create(XMLHttpRequest);
}
else // Versiones antiguas de MS Internet Explorer
{
ajax=new ActiveXObject(“Microsoft.XMLHTTP”);
}
ajax.onreadystatechange=
function()
{
if(ajax.readyState==4&&ajax.status==200&&ajax.responseType==“json”)
{
resultado=JSON.parse(ajax.responseText);
if(resultado.fecha>objeto_grafico.fecha[objeto_grafico.fecha.length–1])
{
// Normalmente se gestionará la respuesta utilizando el objeto
redibujar_grafico(objeto_grafico,resultado);
// Si los datos son sencillos y tienen una estructura clara puede ser más práctico usarla directamente
// redibujar_grafico(objeto_grafico,[resultado.fecha,resultado.temperatura]);
}
}
}
ajax.open(“POST”,pagina);
ajax.setRequestHeader(“Method”,“POST “+pagina+” HTTP/1.1″);
ajax.setRequestHeader(“Content-type”,“application/x-www-form-urlencoded”);
ajax.setRequestHeader(“Content-length”,consulta.length);
ajax.setRequestHeader(“Connection”,“close”);
ajax.send(consulta);
}
|
Eelmise näite kolmandal real koostatakse serverile esitatav päring, milles edastatakse argument "tsoon", mille väärtuseks on jälgitava koha nimi või kood, kuna teave ala võib samas andmebaasis koos eksisteerida.erinevad andurid (näiteks termomeetrid, mis mõõdavad temperatuuri erinevates ruumides). Eelmisele funktsioonile, diagrammi andmetega objektile edastatud parameeter peaks sisaldama atribuuti ruumi nimega ("name_suffix").
Eelmise koodi ridade 7 ja 14 vahel on objekt XMLHttpRequest
mis on salvestatud muutujasse "ajax". Enne objekti loomise viisi valimist otsite window
kui XMLHttpRequest
ei olnud saadaval (midagi juhtus Microsoft Exploreri vanades versioonides ja kuigi see on kaugel maha jäänud, on see näide alternatiividest objekti loomiseks, kasutades (natiivsemat) süntaksit. Object.create
o new
, mis sarnaneb teiste objektorienteeritud keelte omaga.
Et vastust saaks kohe hallata, koostatakse seda käsitlev kood ridadel 15 kuni 26 enne päringu esitamist serverile.
Viis sooritage päring HTTP serverisse koosneb avage ühendus koos open
tüübi ja lehe märkimine (valikuliselt kasutajanimi ja parool), valmistage päised ette protokolli koos setRequestHeader
y saata päring koos send
. Päis HTTP Content-length
peate teadma päringu pikkust (märkide arvu), mille abil arvutatakse length
.
Kui taotlus AJAX on valmis, käivitatakse sündmusega seotud funktsioon onreadystatechange
. Funktsiooni määramise asemel on eelmises näites defineeritud käigult anonüümne funktsioon, mis hakkab haldama serverist saabuvate andmete vastuvõtmist. Esiteks kontrollitakse real 18, et päringu olek on "lõpetatud", mis vastab väärtusele 4
vara readyState
, et olek on "OK". HTTP protokoll (kood 200
), mida saab kinnisvarast saada status
ja et saabunud andmed on JSON-vorming, kinnisvaraga konsulteerimine responseType
.
Kui olete veendunud, et vastuse olek on ootuspärane, eelmise näite real 20 loob tulemusega objekti, teisendades teksti JSON. Vastuses on ette nähtud tagastatav kuupäev, mis võimaldab meil näha, kas serveri saadetud tulemus oli graafikus juba varem esindatud, mida kontrollitakse real 21. Kui andmed on uued, siis real 23 Funktsioon, mis vastutab graafiku ümberjoonistamise eest uue teabega.
Selle lugemismeetodi väljapakkumise idee seisneb selles, et andmeid värskendatakse väga sageli. Kui esitatud teave vastab pikaajalisele perioodile (nt päeva või nädala temperatuurid), saab rakendada esialgse päringu, mis kogub kõik saadaolevad andmed ja seejärel ühe, sarnaselt näites olevale, mis värskendab seda perioodi korrespondent.
Looge testimiseks juhuslikud andmed
Kui kogu serveri ja kliendi infrastruktuur on valmis, vastutab andmete lugemise ja nendega graafiku joonistamise eest funktsioon, nagu eelmises jaotises, kuid Testimisfaasis võib olla otstarbekam kasutada juhuslikke numbreid kontrollitud vahemikus et näha, kas kirjutatav kood on õige. Järgmine funktsioon võib olla näide andmete hankimiseks lõpliku rakenduse loomisel.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
function consultar_ultimo_valor_sensores
(
objeto_grafico,// Objeto dentro del elemento SVG que representa el trazado
valor_maximo, // Valor máximo
valor_minimo, // Valor mínimo
margen_valor // Cantidad extra que se representa sobre/bajo el valor máximo/mínimo
)
{
// La forma más genérica es usar objetos
/*
var nuevo_valor_inventado=
{
fecha:Math.round(Date.now()+Math.random()*1000),
temperatura:Math.random()*Math.abs(valor_maximo-valor_minimo)+valor_minimo
};
*/
// En este caso concreto, como son pocos datos y con una estructura concreta es más práctico usar un vector
var nuevo_valor_inventado=
[
Math.round(Date.now()+Math.random()*1000),
Math.random()*Math.abs(valor_maximo–valor_minimo)+valor_minimo
];
redibujar_grafico(objeto_grafico,nuevo_valor_inventado);
}
|
Andmebaasist teabe lugemise asemel genereerib ülaltoodud näide need juhuslikult ja edastab need graafiku joonistamise eest vastutavale funktsioonile. Leiutatud andmed on vektor, mille moodustavad kuupäev, mis on väljendatud väärtusena millisekundites, anduri teabe salvestamise hetk ja jälgitavad andmed, mis jäävad maksimumväärtuse ja miinimumväärtuse vahele.
Selles näites võib kuupäeva genereerimisel seda kuni ühe sekundi (1000 millisekundi) võrra edasi lükata, võrreldes leiutamisaegse kuupäevaga. Nagu Math.random()
genereerib arvu vahemikus 0.0 kuni 1.0, korrutades selle 1000-ga, saadakse arv vahemikus 0 kuni 1000, mis seejärel teisendatakse täisarvuks. Samamoodi saadakse väärtus juhusliku arvu korrutamisel vahemikuga (maksimaalne miinus miinimum) ja miinimumi liitmine.
Joonistage IoT-andurite graafik SVG-graafikuga
Kuna oleme näinud, kuidas saame saada väärtused, mida soovime esitada (näites temperatuur) ja nende ajalist asukohta, mida saab väljendada koos koordinaatidena, on allolevas näites näidatud tee joonistamise funktsioon. mis ühendab neid punkte ja soovi korral selle joonega piiritletud värvilise ala ülaosas. Tulemus oleks nagu järgmine pilt.
Graafiku horisontaaltelg (X) tähistab aega ja vertikaaltelg (Y) väärtusi, mida IoT-ga ühendatud andurid on jälginud. Horisontaalne intervall on mõni sekund, kuna selles ettepanekus uuendatakse graafikut väga sageli (näiteks iga sekund), et anda andurite oleku kohta peaaegu reaalajas teavet.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
|
function actualizar_grafico
(
grafico, // Objeto SVG con el que se dibuja la gráfico
coordenada, // Matriz con las coordenadas del trazado formada por pares [tiempo,valor] ordenados primero el más antiguo (tiempo menor) último el más nuevo
tiempo_total_representado, // Tiempo total representado por la gráfico (en milisegundos)
valor_maximo, // Valor máximo aceptable antes de emitir una alarma
valor_minimo, // Valor mínimo aceptable antes de emitir una alarma
margen_valor, // Cantidad extra que se representa sobre/bajo el valor máximo/mínimo
parametro_cerrado, // Valor booleano que indica si el trazado se cierra o no (por defecto false)
parametro_ancho_caja, // Ancho de la caja que contiene la gráfico (por defecto 100.0)
parametro_alto_caja // Alto de la caja que contiene la gráfico (por defecto 100.0)
)
{
var cerrado=parametro_cerrado||false; // Valor booleano que indica si el trazado se cierra o no (por defecto false)
var ancho_caja=parametro_ancho_caja||100.0; // Ancho de la caja que contiene la gráfico (por defecto 100.0)
var alto_caja=parametro_alto_caja||100.0; // Alto de la caja que contiene la gráfico (por defecto 100.0)
var coordenadas_trazado=“M “; // Cadena de texto que representa la propiedad “d” del trazado SVG
var desplazamiento=[]; // Desplazamientos X e Y para posicionar el tiempo y el valor representado dentro del rango del gráfico
var escala=[]; // Coeficientes X e Y para calcular el tamaño al representar el gráfico
var sin_recortar=true; // False si la gráfico se sale de la caja (si se sale, si recorta, se hace false para no seguir dibujando puntos)
var contador_valor=coordenada.length–1; // Variable para recorrer los valores (índice)
var posicion=[]; // Variable intermedia (para hacer más legible el código) con la que calcular la posición horizontal y vertical de un punto del trazado
escala[0]=ancho_caja/tiempo_total_representado; // Coeficiente que multiplica a los valores horizontales (tiempo) para calcular las coordenadas X
escala[1]=alto_caja/(Math.abs(valor_maximo–valor_minimo)+margen_valor*2); // Coeficiente que multiplica a los valores (vertical) para calcular las coordenadas Y
desplazamiento[0]=coordenada[coordenada.length–1][0]–tiempo_total_representado; // Valor desde el que se empieza a contar el tiempo: el valor mayor (último) menos el rango de tiempo representado
desplazamiento[1]=margen_valor–valor_minimo; // Valor menor mostrado (al menor se le añade un margen para visualizar el principio de los valores fuera del rango permitido)
if(cerrado) // Si se dibuja un path (trazado) cerrado…
{
coordenadas_trazado+=ancho_caja+“,”+alto_caja+” L “; // …se empieza por la parte inferior de la caja
}
while(contador_valor>=0&&sin_recortar) // Mientras queden valores por representar y no se haya llegado al borde izquierdo del gráfico…
{
posicion[0]=(coordenada[contador_valor][0]–desplazamiento[0])*escala[0]; // Calcular la X restando al tiempo el desplazamiento y convirtiéndolo a la escala del gráfico con el coeficiente horizontal
posicion[1]=alto_caja–(coordenada[contador_valor][1]+desplazamiento[1])*escala[1]; // Calcular la Y restando del alto de la caja (la Y crece hacia abajo en SVG)
coordenadas_trazado+=posicion[0]+“,”+posicion[1]; // Formar la coordenada con la X y la Y
if(posicion[0]>0) // Si no se ha rebasado el margen izquierdo…
{
coordenadas_trazado+=contador_valor>0?” L “:“”; // …y quedan valores que represntar, añadir una nueva línea (código L) para el próximo
contador_valor—; // Pasar al siguiente valor
}
else // Si se ha rebasado el margen izquierdo…
{
sin_recortar=false; // …abandonar el modo sin recorte (lo que terminará de calcular coordenadas)
}
}
if(cerrado) // Si se dibuja un trazado (path) cerrado…
{
coordenadas_trazado+=” L “+posicion[0]+“,”+alto_caja+” Z”; // …se termina por la parte inferior de la caja y se añade Z para cerrarlo en SVG
}
grafico.setAttribute(“d”,coordenadas_trazado); // Cambiar las coordenadas del trazado (propiedad “d”) por las que se han calculado
}
|
Eelmises koodis on kaks huvitavat aspekti, esiteks arvutus, mis võimaldab kohandada esitatud väärtuste vahemikku ja teiseks kinnisvara ehitus d
mis näitab paigutuse punktide koordinaate (path
).
Esitatud väärtuste vahemiku kohandamiseks nihutatakse neid miinimumist ja skaleeritakse nii, et nähtav suurus vastab graafiku suurusele. Aja puhul saadakse nihe, lahutades kuvatava vahemiku pikimast ajast (praegusele lähim kuupäev ja kellaaeg) (näites 20 sekundit). Temperatuuriväärtuste nihe on madalama vahemiku (üks kraad) miinus madalaim väärtus, nii et allpool näidatud andmed on kõige sarnasemad madalaima lubatud väärtusega, kuid jätavad varu, mis võimaldab meil hinnata neid, mis seda teevad. . üle andma
Koefitsient, mis korrutab ajaväärtused graafiku horisontaalkoordinaatide saamiseks, saadakse graafiku kogulaiuse (näites 100 ühikut) jagamisel esitatud ajavahemikuga (näites 20 sekundit). Koefitsiendi saamiseks skalaartemperatuuri väärtustega tuleb meeles pidada, et kujutatud vahemik ulatub minimaalsest väärtusest allapoole jäävast veerist maksimumist kõrgemale, mõlemal juhul üks kraad. Sel viisil saadakse vertikaalskaala koefitsient graafiku kõrguse (näites 100 ühikut) jagamisel maksimaalse väärtusega, millest on lahutatud miinimum pluss ülemine ja alumine veeris. Kuna need väärtused võivad negatiivsetel temperatuuridel täielikult areneda, kasutame Math.abs()
erinevuse absoluutväärtuse kasutamiseks.
Vara d
objekti path
See konstrueeritakse teksti punktide koordinaatide ühendamise teel. Igale koordinaatide paarile eelneb kood SVG L
, mis tõmbab joone praegusest asukohast absoluutväärtuseni, mida näitavad koordinaadid. X- ja Y-väärtused eraldatakse komadega ja iga toiminguga SVG on järgmisest eraldatud tühikuga.
Paigutuse alustamiseks kasutage koodi M
(liigu absoluutsele koordinaadile). Suletud ja täidetud graafiku puhul alustad all paremalt, avatud graafiku puhul, mis joonistab andmeprofiili, alustad viimati esindatud väärtusest (kõige värskemast). Suletud paigutuse lõpetamiseks kasutatakse koodi Z
lisades viimaseks punktiks selle, millel on sama X-koordinaadi väärtus kui sirge viimasel punktil ja Y-koordinaadiks väikseim esitatud väärtus.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
function dibujar_grafico()
{
var tiempo_mostrado=20000; // Se representan 20 segundos (20000 milisegundos)
var valor_maximo=10; // 10 grados sobre cero
var valor_minimo=–5; // Cinco grados bajo cero
var fecha_hora=Date.now(); // Hora actual
var matriz_de_coordenadas_de_prueba=[]; // Preparar el vector de coordenadas
for(var contador=0;contador<20;contador++)
{
fecha_hora+=500+1500*Math.random(); // Añadir medio segundo a la hora anterior y entre 0 y segundo y medio aleatoriamente
matriz_de_coordenadas_de_prueba[contador]=[]; // Preparar el siguiente punto del vector de coordenadas
matriz_de_coordenadas_de_prueba[contador][0]=fecha_hora; // En la coordenada horizontal, situar la hora
matriz_de_coordenadas_de_prueba[contador][1]=Math.random()*Math.abs(valor_maximo–valor_minimo)+valor_minimo; // En la coordenada vertical situar el valor del sensor
}
actualizar_grafico
(
document.getElementById(“relleno_temperatura”), // Trazado para el relleno definido en el código HTML
matriz_de_coordenadas_de_prueba,
tiempo_mostrado,
valor_maximo, // Diez grados de valor máximo
valor_minimo, // Cinco grados bajo cero como valor mínimo
1, // Un grado por encima y por debajo de las temperatura mínimas y máximas respectivamente
true // Cerrar el trazado para representar el área rellena
);
actualizar_grafico
(
document.getElementById(“linea_temperatura”), // Trazado para el relleno definido en el código HTML
matriz_de_coordenadas_de_prueba,
tiempo_mostrado,
valor_maximo, // Diez grados de valor máximo
valor_minimo, // Cinco grados bajo cero como valor mínimo
1, // Un grado por encima y por debajo de las temperatura mínimas y máximas respectivamente
false // No cerrar el trazado para representar la linea que une los puntos que representan las temperaturas
);
}
|
Selles näites funktsioon dibujar_grafico()
, mis on lehe laadimise kutse, saab testimiseks algväärtused (mitte viimase reaalajas väärtuse) ja valmistab ette vahemiku, milles andmed renderdatakse: 20 sekundit (20000 ms) horisontaalselt ja 15 °C vertikaalne vahemikus -5°C kuni +10°C ühe kraadise ülemise ja alumise veerisega. Tehke kaks kõnet numbrile actualizar_grafico()
, esimesel läbimisel true
argumendina, mis näitab, et diagramm tuleks suletud ala esindamiseks sulgeda ja teisel kutsel see möödub false
piiri tõmbamiseks. Igal juhul objekt path
modifitseeritud on see, millel on vastav välimus, esimesel juhul täidisega ja ilma äärisega ning teisel juhul teatud joone paksusega ja täidiseta.
Funktsioon actualizar_grafico()
objektil töötama SVG mis kasutab konteinerina järgmist koodi HTML. Objekt SVG sisaldab kahte rada, üks joone tõmbamiseks ja teine täidetud ala joonistamiseks. Veebilehe laadimisel elemendist <body>
eelmine funktsioon kutsutakse automaatselt välja, dibujar_grafico()
tänu üritusele JavaScript onload
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
<!DOCTYPE html>
<html lang=“es”>
<head>
<meta charset=“utf-8”>
<title>Temperatura</title>
<script type=“text/javascript” src=“https://polaridad.es/javascript-grafico-svg-sensor-internet-de-las-cosas-iot/grafico.js”></script>
</head>
<body onload=“dibujar_grafico();” style=“margin:0;”> <!– Cuerpo del documento HTML. Al cargar el contenido llama a la función JavaScript dibujar_grafico() –>
<div id=“temperatura”>
<div id=“bloque_temperatura” style=“width:820px;height:150px”>
<svg
id=“grafico_temperatura”
width=“100%”
height=“100%”
viewBox=“0 0 100 100”
preserveAspectRatio=“none”>
<path
id=“relleno_temperatura”
d=“”
style=“fill:#A8C3EA;stroke:none;”
vector-effect=“non-scaling-stroke”
/>
<path
id=“linea_temperatura”
d=“”
style=“fill:none;stroke:#205587;stroke-width:4;stroke-opacity:1;”
vector-effect=“non-scaling-stroke”
/>
</svg>
</div>
</div>
</body>
</html>
|
Koodi real 10 HTML ülal on stiilis laius (näitena) 820 px ja kõrgus 150 px (mis on lõplikus versioonis soovitatav teha klassi ja dokumendiga CSS). Tundub kummaline, et read 13 ja 14 määravad objekti suuruse SVG nagu 100% laius ja kõrgus (mis sobib kõige paremini akna mõõtmetega, 100 × 100). Nagu juba mainitud, on selle põhjuseks alati töötada teadaolevate mõõtmetega ja kohandada esitatavaid väärtusi sellele. Teised alternatiivid oleks arvutada iga kord graafiku ruum ja kohandada väärtusi hiljem või kehtestada graafikule fikseeritud mõõtmed, millest dokument peab kinni pidama.
Olles valinud graafiku, mille mõõtmed muutuvad vastavalt koodile HTML, on vaja vara lisada vector-effect
julgusega non-scaling-stroke
et vältida joonte paksuse deformeerumist, kui graafik ei säilita valitud 1:1 proportsioone veebilehel, millel see kuvatakse, nagu eelmises ettepanekus.
Graafiku kärpimiseks ja ainult valitud ala kuvamiseks kasutage viewBox
. Sel juhul oleme valinud graafiku osa, mis algab 0,0-st (ülemine vasak nurk) ja mõõdab 100x100 alla ja paremale. Joonise osa, mis asub negatiivsete või suuremate kui 100 väärtustega koordinaatides, ei kuvata veebilehel, isegi kui need on objektil olemas SVG
Lisage SVG joonisele uusi elemente
Eelmises näites funktsioon actualizar_grafico()
kasutage paigutust SVG mille omandiõigust muudetakse d
, mis väljendab koordinaatide ahelat. Alternatiiv oleks luua kogu objekt iga kord, kui see ümber joonistatakse. Esimese valiku eeliseks on see, et graafiline välimus (nt paksus või värv) on koodis määratletud HTML, piirang on see, et objektid peavad olema eelnevalt loodud.
SVG-objektide loomiseks kasutage createElementNS()
, mis võimaldab kaasata nimeruum. Allolevas näites luuakse uus tekstiobjekt (text
) ja on seotud elemendiga SVG mis on koodis juba olemas HTML veebisaidilt. Kui uus element on loodud, määratakse selle omadused setAttribute()
ja lisatakse SVG koos appendChild()
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
function
rotular
(
objeto_grafico,
texto,
inicio=[0,0],
altura=10.0,
tipo_letra=“SircuitoRegularMedium”,
color_texto=“#000000”,
color_fondo=“#FFFFFF”
)
{
nuevo_objeto_svg=document.createElementNS(“http://www.w3.org/2000/svg”,“text”);
nuevo_objeto_svg.setAttribute(“x”,inicio[0]);
nuevo_objeto_svg.setAttribute(“y”,inicio[1]);
nuevo_objeto_svg.setAttribute(“font-family”,tipo_letra);
nuevo_objeto_svg.setAttribute(“font-size”,altura);
nuevo_objeto_svg.setAttribute(“fill”,color_texto);
nuevo_objeto_svg.textContent=texto;
objeto_grafico.appendChild(nuevo_objeto_svg);
}
//rotular(document.getElementById(“cosa_svg”),”HOLA”,[10,10]);
|
Muutke joonise elementide osakaalu
Kui olete proovinud eelmise jaotise näites oleva funktsiooniga sildistada, olete näinud, et tekst näib olevat deformeerunud, kui objekti osakaal veebilehel (width
y height
Koodist HTML) ei ole võrdne kujutatud ala omaga (viewBox
). Proportsiooni kohandamiseks on vaja teada objekti mõõte SVG mille kohta saate vaadata objekti või konteineri stiili HTML, kui objekt SVG võõrandada see vara. Omandiõiguse määramine transform
objektide juurde SVG mis sõltuvad proportsioonist, saab deformatsiooni korrigeerida skaleerimisoperatsiooniga scale()
milles X koefitsient erineb Y koefitsiendist.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
function
rotular
(
objeto_grafico,
texto,
inicio=[0,0],
altura=10.0,
proporcion=1.0,
tipo_letra=“SircuitoRegularMedium”,
color_texto=“#000000”,
color_fondo=“#FFFFFF”
)
{
var escala_horizontal=parseFloat(getComputedStyle(objeto_grafico).height)/parseFloat(getComputedStyle(objeto_grafico).width);
nuevo_objeto_svg=document.createElementNS(“http://www.w3.org/2000/svg”,‘text’);
nuevo_objeto_svg.setAttribute(“transform”,“scale(“+escala_horizontal+“,1.0)”); // scale permite cambiar la escala en X e Y
//nuevo_objeto_svg.setAttribute(“transform”,”scaleX(“+escala_horizontal+”)”); // Como se sabe que sólo cambia la escala en X, se puede usar scaleX
nuevo_objeto_svg.setAttribute(“x”,inicio[0]);
nuevo_objeto_svg.setAttribute(“y”,inicio[1]);
nuevo_objeto_svg.setAttribute(“font-family”,tipo_letra);
nuevo_objeto_svg.setAttribute(“font-size”,altura);
nuevo_objeto_svg.setAttribute(“fill”,color_texto);
nuevo_objeto_svg.textContent=texto;
objeto_grafico.appendChild(nuevo_objeto_svg);
}
//rotular(document.getElementById(“cosa_svg”),”HOLA”,[10,10]);
|
SVG võimaldab mitut objekti rühmitada, moodustades uue komposiitelemendi, mis toetab ka omadusi, nagu lihtsad objektid. Sama teisenduse rakendamiseks objektide seeriale korraga, mitte iga objekti eraldi, saate need selle ressursi järgi rühmitada ja rakendada ühte atribuuti transform
neile kõigile.
Nagu selgitati rääkides SVG-vormingus, on rühma elemendid siltide sees <g>
y </g>
. Lisamiseks JavaScript elemendid rühma SVG kasutatakse, nagu on näha eelmises näites, appendChild()
kui uus objekt on määratletud.
Päritolu tuvastamiseks teisenduste rakendamisel saab omadust kasutada objektidel SVG transform-origin
, mille väärtus on teisenduse alguse punkti X- ja Y-koordinaadid. Kui teisenduse alguspunkti väärtust pole selgelt näidatud (veebibrauseris), kasutatakse koordinaatide keskpunkti. Kahjuks ei ole selle kirjutamise ajal teisenduste käitumise täpsustamine, kasutades muud allikat kui vaikeallikas, brauserites homogeenne ja seda tuleks kasutada ettevaatlikult.
Koos skaala teisendusega scale
On ka teisi, näiteks koos pööramine rotation
ja liikumine koos translate
, mis pakuvad a alternatiiv graafilisele esitusele: uute koordinaatide hankimise asemel saate neid esitada oma ruumis ja teisendada graafiku vormingusse, milles soovite neid esitada.
Lisage diagrammile viiteid
Nüüd, kui graafiku põhiosa on lahendatud väärtuste joonistamise teel profiili ja täidetud alaga, saab seda täiendada viidetega, mis aitavad selle lugemist. Näiteks alustame mõne horisontaalse viite (joone) joonistamisega, mis tähistavad maksimaalset ja minimaalset vastuvõetavat väärtust ning soovitud väärtust. Nagu selgitatud, saate objekte lisada SVG otse JavaScript või lisage need koodi käsitsi HTML ja muutke neid hiljem rakendusega JavaScript.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
var CONTENEDOR_SVG; // Objeto SVG que contiene el gráfico que representa los valores monitorizados por los sensores en la IoT
var NS=“http://www.w3.org/2000/svg”; // Nombre del espacio de nombres (name space NS)
var ANCHO_CAJA=100.0; // Ancho del objeto SVG (aunque al dibujarlo con el código HTML tomará otras dimensiones
var ALTO_CAJA=100.0; // Alto del objeto SVG (aunque al dibujarlo con el código HTML tomará otras dimensiones
var VALOR_MAXIMO=10.0; // Mayor valor admisible en el gráfico SVG. Los valores mayores se saldrán del gráfico salvo por un margen que permite tener una idea de la tendencia
var VALOR_MINIMO=–5.0; // Menor valor admisible en el gráfico SVG. Los valores menores se saldrán del gráfico salvo por un margen que permite tener una idea de la tendencia
var VALOR_DESEADO=5.0; // Mejor valor del parámetro medido (temperatura). Sirve para tener una idea rápida de cómo de correcto es el estado del sistema
var MARGEN_VALOR=1.0; // Zona por encima del valor mayor y por debajo del valor menor que se representa para tener una idea aproximada de la tendencia cuando los datos monitorizados rebasen los valores máximo y/o mínimo
function inicializar_grafico()
{
CONTENEDOR_SVG=document.getElementById(“contenedor_svg”);
crear_referencia_horizontal_svg(VALOR_MAXIMO,“#FF0000”);
crear_referencia_horizontal_svg(VALOR_DESEADO,“#00FF00”);
crear_referencia_horizontal_svg(VALOR_MINIMO,“#0000FF”);
}
function crear_referencia_horizontal_svg
(
altura=0.0,
color=“#000000”,
grosor=0.5,
opacidad=1.0
)
{
var altura_corregida=ALTO_CAJA–(altura+MARGEN_VALOR–VALOR_MINIMO)*ALTO_CAJA/(Math.abs(VALOR_MAXIMO–VALOR_MINIMO)+MARGEN_VALOR*2);
var referencia_horizontal=document.createElementNS(NS,‘line’);
referencia_horizontal.setAttribute(“x1”,0.0);
referencia_horizontal.setAttribute(“x2”,ANCHO_CAJA);
referencia_horizontal.setAttribute(“y1”,altura_corregida);
referencia_horizontal.setAttribute(“y2”,altura_corregida);
referencia_horizontal.style.stroke=color;
referencia_horizontal.style.strokeWidth=grosor;
referencia_horizontal.style.strokeOpacity=opacidad;
CONTENEDOR_SVG.appendChild(referencia_horizontal);
}
//inicializar_grafico();
|
Tundub loogiline märgistada need horisontaalsed viited tekstiga, mis selgitab nende esindatavat väärtust. Teksti esiletõstmiseks võite kasutada ristkülikuid, mis eristuvad taustast ja graafikast. Kuna deformatsiooni kompenseerimiseks tuleb tekstidele rakendada skaala teisendust, saab need kõik rühmitada objektiks, millele skaala rakendatakse; Sel viisil toimimise peamiseks eeliseks on võimalus neid ühe toiminguga muuta, kui graafiku konteineri (brauseriakna) suurust muudetakse ja see proportsioon muutub, mida skaala korrigeerib.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
// Este código de ejemplo usa constantes para hacerlo más legible a desarrolladores de aplicaciones para microcontroladores de series pequeñas. La opción más recomendable, y más propia del estilo JavaScript, es crear un objeto cuyas propiedades serían las constantes y que incluiría los métodos (aquí funciones) que generan o modifican el gráfico o en este caso las referencias
var CONTENEDOR_SVG; // Objeto SVG que contiene el gráfico que representa los valores monitorizados por los sensores en la IoT
var NS=“http://www.w3.org/2000/svg”; // Nombre del espacio de nombres (name space NS)
var ANCHO_CAJA=100.0; // Ancho del objeto SVG (aunque al dibujarlo con el código HTML tomará otras dimensiones
var ALTO_CAJA=100.0; // Alto del objeto SVG (aunque al dibujarlo con el código HTML tomará otras dimensiones
var TIEMPO_REPRESENTADO=30000; // Milisegundos visibles en el gráfico empezando en el valor mayor (fecha y hora del último valor monitorizado)
var VALOR_MAXIMO=10.0; // Mayor valor admisible en el gráfico SVG. Los valores mayores se saldrán del gráfico salvo por un margen que permite tener una idea de la tendencia
var VALOR_MINIMO=–5.0; // Menor valor admisible en el gráfico SVG. Los valores menores se saldrán del gráfico salvo por un margen que permite tener una idea de la tendencia
var VALOR_OPTIMO=5.0; // Mejor valor del parámetro medido (temperatura). Sirve para tener una idea rápida de cómo de correcto es el estado del sistema
var MARGEN_VALOR=2.0; // Zona por encima del valor mayor y por debajo del valor menor que se representa para tener una idea aproximada de la tendencia cuando los datos monitorizados rebasen los valores máximo y/o mínimo
var desplazamiento_valor=desplazamiento(Date.now());
var escala_valor=escala();
var TIPOGRAFIA=“SircuitoRegularMedium”; // Tipografía con la que se rotula todo el gráfico (se usa una constante buscando la uniformidad, pero se puede rotular usando diferentes tipos de letra si es necesario)
var ALTURA_TEXTO=10.0; // Altura de los textos en valor absoluto (píxeles)
var COLOR_MINIMO=“#621D87”; // Color de la referencia que indica el valor mínimo
var COLOR_OPTIMO=“#1D8762”; // Color de la referencia que indica el valor máximo
var COLOR_MAXIMO=“#871E35”; // Color de la referencia que indica el valor óptimo
var COLOR_TIPOGRAFIA=“#A8C3EA”; // Color del tipo de letra con que se rotulan las referencias
var GROSOR_REFERENCIA=0.5; // Grosor de la línea que se dibuja como referencia en valor absoluto (píxeles)
var OPACIDAD_REFERENCIA=1.0; // Opacidad de la línea de referencia. Si se dibuja sobre el gráfico con cierta transparencia permite ver el dibujo bajo ella
var RELLENO_FONDO_REFERENCIA=4.0; // Margen entre el fondo de la referencia y el texto medido en valor absoluto (la línea empieza en el margen izquierdo y recorre todo el gráfico)
var MARGEN_FONDO_REFERENCIA=10.0; // Separación de la referencia y el borde izquierdo del gráfico medido en valor absoluto (la línea empieza en el margen izquierdo y recorre todo el gráfico)
var ANCHO_FONDO_REFERENCIA=34.0; // Medida horizontal del rectángulo que hace de fondo al texto de la referencia medido en valor absoluto
function proporcion_grafico()
{
return parseFloat(getComputedStyle(CONTENEDOR_SVG).height)/parseFloat(getComputedStyle(CONTENEDOR_SVG).width); // La escala debe calcularse cada vez ya que no se sabe si se ha redimensionado el objeto HTML que contiene al objeto SVG y que le da el tamaño
}
function medida_grafico()
{
var proporcion=[]; // Coeficiente que calcula la medida absoluta en píxeles en función del ancho/alto base del gráfico y de la representación en la página web // Coeficiente que calcula la medida absoluta en píxeles en función del ancho/alto base del gráfico y de la representación en la página web
proporcion[0]=ANCHO_CAJA/parseFloat(getComputedStyle(CONTENEDOR_SVG).width);
proporcion[1]=ALTO_CAJA/parseFloat(getComputedStyle(CONTENEDOR_SVG).height);
return proporcion;
}
function desplazamiento(valor_mayor)
{
var desplazamiento_valor=[];
desplazamiento_valor[0]=valor_mayor–TIEMPO_REPRESENTADO; // Valor desde el que se empieza a contar el tiempo: el valor mayor (último) menos el rango de tiempo representado
desplazamiento_valor[1]=MARGEN_VALOR–VALOR_MINIMO; // Valor menor mostrado (al menor se le añade un margen para visualizar el principio de los valores fuera del rango permitido)
return desplazamiento_valor;
}
function escala()
{
var escala_valor=[];
escala_valor[0]=ANCHO_CAJA/TIEMPO_REPRESENTADO; // Coeficiente que multiplica a los valores horizontales (tiempo) para calcular las coordenadas X
escala_valor[1]=ALTO_CAJA/(Math.abs(VALOR_MAXIMO–VALOR_MINIMO)+MARGEN_VALOR*2); // Coeficiente que multiplica a los valores (vertical) para calcular las coordenadas Y
return escala_valor;
}
function crear_referencia_horizontal_svg
(
posicion=0.0,
color_dibujo=“#000000”,
grosor_linea=GROSOR_REFERENCIA,
opacidad_linea=OPACIDAD_REFERENCIA,
color_texto=COLOR_TIPOGRAFIA,
altura_texto=ALTURA_TEXTO
)
{
var proporcion_horizontal=proporcion_grafico(); // La escala debe calcularse cada vez ya que no se sabe si se ha redimensionado el objeto HTML que contiene al objeto SVG y que le da el tamaño
var coeficiente_medida=medida_grafico();
var posicion_corregida=ALTO_CAJA–(posicion+desplazamiento_valor[1])*escala_valor[1];
var referencia_horizontal=document.createElementNS(NS,‘line’); // El orden en el que se crean los objetos determina qué tapa (lo último) y que es tapado (lo primero)
var fondo_referencia=document.createElementNS(NS,‘rect’); // El rectángulo (opaco) se creará después de la línea (que puede ser un poco transparente) para definir con claridad el fondo del texto
var texto_referencia=document.createElementNS(NS,‘text’); // El texto se creará en último lugar para que quede sobre los otros objetos
referencia_horizontal.setAttribute(“x1”,0.0);
referencia_horizontal.setAttribute(“x2”,ANCHO_CAJA);
referencia_horizontal.setAttribute(“y1”,posicion_corregida);
referencia_horizontal.setAttribute(“y2”,posicion_corregida);
referencia_horizontal.style.stroke=color_dibujo;
referencia_horizontal.style.strokeWidth=grosor_linea*coeficiente_medida[1];
referencia_horizontal.style.strokeOpacity=opacidad_linea;
CONTENEDOR_SVG.appendChild(referencia_horizontal); // Añadir la línea de referencia lo más abajo
fondo_referencia.setAttribute(“x”,MARGEN_FONDO_REFERENCIA*coeficiente_medida[0]);
fondo_referencia.setAttribute(“y”,posicion_corregida–(ALTURA_TEXTO+RELLENO_FONDO_REFERENCIA*2.0)*coeficiente_medida[1]/2.0);
fondo_referencia.setAttribute(“width”,ANCHO_FONDO_REFERENCIA*coeficiente_medida[0]);
fondo_referencia.setAttribute(“height”,(ALTURA_TEXTO+RELLENO_FONDO_REFERENCIA*2.0)*coeficiente_medida[1]);
fondo_referencia.style.fill=color_dibujo;
fondo_referencia.style.fillOpacity=1.0;
fondo_referencia.style.strokeWidth=0;
CONTENEDOR_SVG.appendChild(fondo_referencia);
texto_referencia.setAttribute(“x”,(MARGEN_FONDO_REFERENCIA+RELLENO_FONDO_REFERENCIA)*coeficiente_medida[0]/proporcion_horizontal);
texto_referencia.setAttribute(“y”,posicion_corregida+ALTURA_TEXTO/2.0*coeficiente_medida[1]);
texto_referencia.setAttribute(“font-family”,TIPOGRAFIA);
texto_referencia.setAttribute(“font-size”,ALTURA_TEXTO*coeficiente_medida[1]);
texto_referencia.setAttribute(“fill”,COLOR_TIPOGRAFIA);
texto_referencia.setAttribute(“transform”,“scale(“+proporcion_horizontal+“,1.0)”);
texto_referencia.textContent=(posicion>=0?“+”:“”)+posicion;
CONTENEDOR_SVG.appendChild(texto_referencia);
}
function inicializar_grafico()
{
CONTENEDOR_SVG=document.getElementById(“contenedor_svg”);
crear_referencia_horizontal_svg(VALOR_MAXIMO,COLOR_MAXIMO);
crear_referencia_horizontal_svg(VALOR_OPTIMO,COLOR_OPTIMO);
crear_referencia_horizontal_svg(VALOR_MINIMO,COLOR_MINIMO);
}
//inicializar_grafico();
|
Ülaltoodud näitekoodis on mitmeid huvitavaid aspekte. Kõigepealt kommenteerige, et konstante (globaalseid muutujaid) on kasutatud selleks, et muuta näide programmeerimisest pärit kasutajatele loetavamaks. mikrokontrollerid en C aastal C + +. Nagu hiljem näha, optimaalne viis selle sisse programmeerimiseks JavaScript See kasutaks neid väärtusi sisaldavaid objekte ja meetodeid, mis haldaksid selle näite viiteid või üldiselt tootmissüsteemis graafikut.
Teisest küljest on üldisema koodi edendamiseks välja töötatud eraldi funktsioonid, mis arvutavad erinevaid koefitsiente, mis korrigeerivad graafiku osakaalu teksti kohandamiseks. proporcion_grafico()
, väärtuste skaala sõltuvalt nende vahemikust escala()
ja parandustegur mõõtmiste jaoks, mis on teada absoluutväärtuses, näiteks mõõtmised viidetes medida_grafico()
.
Selle koodi lugemine peaks aitama selgitada konteksti, milles selline rakendus töötab, mis joonistab graafikat reaalajas ja peab olema paindlik, et seda saaks esitada erinevates graafilistes kontekstides (vähemalt erinevad suurused ja proportsioonid). Kõigepealt tuleb objektid genereerida SVG, kas "käsitsi" koodis HTML, kas koodi kaudu JavaScript ja igal juhul tuleb hiljem hankida viited nendele objektidele, et nendega manipuleerida JavaScript et saaks joonestada uusi graafikuid ja kohandada juba koostatud graafiku esitust vastavalt selle esitamise meediumi muutustele.
Veel üks viide, mis aitab graafikut hõlpsasti tõlgendada, on punktid, mis esindavad konkreetseid väärtusi (joone sõlmed). Selles näites, kus esindame ühte suurusjärku, ei ole sümboli valik kriitiline, kuid kui korrelatsiooni otsimiseks asetatakse peale mitu erinevat väärtust, on lisaks muude ressursside (nt värvi) kasutamisele huvitav eristada. , joonistades erinevaid sümboleid. Joonesõlme jaoks kasutatava graafika suurust ja proportsioone tuleb muuta, nagu see juhtub näiteks tekstide puhul, nii et selle mõõtmed oleksid absoluutsed ja et selle proportsioonid säiliksid isegi siis, kui selles sisalduva kasti omad muutuvad.
Eelmises näites nägime juba, kuidas arvutada erinevaid koefitsiente, et skaleerida ja korrigeerida joonise osakaalu; Mis puutub graafiku sõlmede või tippude sümbolite haldamise elluviimisse, siis võib lahenduseks olla objektide salvestamine SVG vektorisse ja muutke selle asukohta, kui graafikut värskendatakse uue väärtuse lugemisega või kui seda konteineri suurust muutes ümber joonistatakse. Esimesel juhul tuleks muuta selle asukohta ja teisel juhul selle proportsiooni kinnisvaraga transform
ja väärtus scale
. Järgmine kood on funktsiooni modifikatsioon actualizar_grafico()
et hõlmata graafitipu sümbolite ümberpaigutamist.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
function actualizar_grafico_puntos
(
grafico, // Objeto SVG con el que se dibuja la gráfico
coordenada, // Matriz con las coordenadas del trazado formada por pares [tiempo,valor] ordenados primero el más antiguo (tiempo menor) último el más nuevo
puntos, // Matriz con los objetos SVG que se representan en los nodos de la línea (los valores reales)
tiempo_total_representado, // Tiempo total representado por la gráfico (en milisegundos)
valor_maximo, // Valor máximo aceptable antes de emitir una alarma
valor_minimo, // Valor mínimo aceptable antes de emitir una alarma
margen_valor, // Cantidad extra que se representa sobre/bajo el valor máximo/mínimo
parametro_cerrado, // Valor booleano que indica si el trazado se cierra o no (por defecto false)
parametro_ancho_caja, // Ancho de la caja que contiene la gráfico (por defecto 100.0)
parametro_alto_caja // Alto de la caja que contiene la gráfico (por defecto 100.0)
)
{
var cerrado=parametro_cerrado||false; // Valor booleano que indica si el trazado se cierra o no (por defecto false)
var ancho_caja=parametro_ancho_caja||100.0; // Ancho de la caja que contiene la gráfico (por defecto 100.0)
var alto_caja=parametro_alto_caja||100.0; // Alto de la caja que contiene la gráfico (por defecto 100.0)
var coordenadas_trazado=“M “; // Cadena de texto que representa la propiedad “d” del trazado SVG
var desplazamiento=[]; // Desplazamientos X e Y para posicionar el tiempo y el valor representado dentro del rango del gráfico
var escala=[]; // Coeficientes X e Y para calcular el tamaño al representar el gráfico
var sin_recortar=true; // False si la gráfico se sale de la caja (si se sale, si recorta, se hace false para no seguir dibujando puntos)
var contador_valor=coordenada.length–1; // Variable para recorrer los valores (índice)
var posicion=[]; // Variable intermedia (para hacer más legible el código) con la que calcular la posición horizontal y vertical de un punto del trazado
escala[0]=ancho_caja/tiempo_total_representado; // Coeficiente que multiplica a los valores horizontales (tiempo) para calcular las coordenadas X
escala[1]=alto_caja/(Math.abs(valor_maximo–valor_minimo)+margen_valor*2); // Coeficiente que multiplica a los valores (vertical) para calcular las coordenadas Y
desplazamiento[0]=coordenada[coordenada.length–1][0]–tiempo_total_representado; // Valor desde el que se empieza a contar el tiempo: el valor mayor (último) menos el rango de tiempo representado
desplazamiento[1]=margen_valor–valor_minimo; // Valor menor mostrado (al menor se le añade un margen para visualizar el principio de los valores fuera del rango permitido)
if(cerrado) // Si se dibuja un path (trazado) cerrado…
{
coordenadas_trazado+=ancho_caja+“,”+alto_caja+” L “; // …se empieza por la parte inferior de la caja
}
while(contador_valor>=0&&sin_recortar) // Mientras queden valores por representar y no se haya llegado al borde izquierdo del gráfico…
{
posicion[0]=(coordenada[contador_valor][0]–desplazamiento[0])*escala[0]; // Calcular la X restando al tiempo el desplazamiento y convirtiéndolo a la escala del gráfico con el coeficiente horizontal
posicion[1]=alto_caja–(coordenada[contador_valor][1]+desplazamiento[1])*escala[1]; // Calcular la Y restando del alto de la caja (la Y crece hacia abajo en SVG)
punto[contador_valor].setAttribute(“cx”,posicion[0]);
punto[contador_valor].setAttribute(“cy”,posicion[1]);
coordenadas_trazado+=posicion[0]+“,”+posicion[1]; // Formar la coordenada con la X y la Y
if(posicion[0]>0) // Si no se ha rebasado el margen izquierdo…
{
coordenadas_trazado+=contador_valor>0?” L “:“”; // …y quedan valores que represntar, añadir una nueva línea (código L) para el próximo
}
else // Si se ha rebasado el margen izquierdo…
{
sin_recortar=false; // …abandonar el modo sin recorte (lo que terminará de calcular coordenadas)
}
contador_valor—; // Pasar al siguiente valor
}
if(cerrado) // Si se dibuja un trazado (path) cerrado…
{
coordenadas_trazado+=” L “+posicion[0]+“,”+alto_caja+” Z”; // …se termina por la parte inferior de la caja y se añade Z para cerrarlo en SVG
}
grafico.setAttribute(“d”,coordenadas_trazado); // Cambiar las coordenadas del trazado (propiedad “d”) por las que se han calculado
for(;contador_valor>=0;contador_valor—)
{
punto[contador_valor].setAttribute(“cx”,–10000);
punto[contador_valor].setAttribute(“cy”,0);
}
}
|
Funktsioonis tehtud muudatused actualizar_grafico()
uue funktsiooni saamiseks actualizar_grafico_puntos()
Need on need, mis on eelmise näite koodis esile tõstetud. Esiteks võtame real 5 objektide vektori SVG parameetrina. See vektor sisaldab sümboleid, mis tuleb graafiku uutes sõlmedes ümber paigutada.
Ridadele 39 ja 40 määratakse keskpunkti uued koordinaadid, cx
y cy
, esindatud väärtustele. Kui sümbol ei põhine keskkohal, on tõenäoliselt vaja lisada nihe cx
pool laiust ja sisse cy
poole kõrgusega, et need täpselt graafiku sõlme ümber paigutada.
Ridadel 57 kuni 61 paigutatakse punktid, mis vastavad koordinaatidele, mida ei joonistata, kuna need on vasaku servaga ära lõigatud, graafikust väljapoole. Koordinaat cy
nullini ja sellest cx
mis tahes negatiivsele arvule (suurem kui punkt ise), nii et seda ei kuvata, kui seda lõigatakse, nagu graafiku vasakpoolne osa, akna poolt SVG.
Halda diagrammi objektist JavaScriptiga
Kõik seni selgitatud toimingud saab integreerida objekti, et hallata graafikut uuele versioonile tüüpilisema stiiliga. JavaScript. Sellel teostusalternatiivil on lisaeelis, kuna see lihtsustab mitme erineva väärtusega graafiku lisamist samale veebilehele.
Enne juurutamise üle arutlemist vaatame üle levinumad viisid objektide loomiseks JavaScript ja mõned funktsioonide iseärasused, mis mõjutavad IoT sensorigraafika joonistamise ettepanekut.
Juba selgitati, et uus viis objektide loomiseks aastal JavaScript (saadaval alates versioonist 5 ECMAScript) koosneb kasutamisest Object.create
, mida peaks kasutama "klassikalise" asemel new
, mis muidugi töötab endiselt õigesti, kuigi selle eesmärk on pigem keelestiili simuleerimine klassipõhiste objektidega (JavaScript lähtub objektide loomisel prototüüpidest) kui töötav alternatiiv.
1
2
3
4
5
6
7
8
9
10
|
<!DOCTYPE html>
<html lang=“es”>
<head>
<meta charset=“utf-8”>
<title>Crear objetos con new o con Objetct.create</title>
<script type=“text/javascript” src=“https://polaridad.es/javascript-grafico-svg-sensor-internet-de-las-cosas-iot/crear_objetos.js”></script>
</head>
<body onload=“empezar();”>
</body>
</html>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
function Objeto_clasico(primero,segundo)
{
this.primero=primero||1;
this.segundo=segundo||2;
this.hacer_algo=function()
{
console.log(“El objeto clásico le saluda (primero=”+this.primero+” y segundo=”+this.segundo+“)”);
}
}
var Objeto_ES5=
{
primero:10,
segundo:20,
hacer_algo:
function()
{
console.log(“El objeto ES5 le saluda (primero=”+this.primero+” y segundo=”+this.segundo+“)”);
}
}
var objeto_clasico=new Objeto_clasico();
var objeto_ES5=Object.create(Objeto_ES5);
function empezar()
{
console.log(“Objeto clásico (“+objeto_clasico.primero+“,”+objeto_clasico.segundo+“)”);
console.log(“Objeto ES5 (“+objeto_ES5.primero+“,”+objeto_ES5.segundo+“)”);
objeto_clasico.hacer_algo();
objeto_ES5.hacer_algo();
}
|
Eelmine kood võimaldab teil meeles pidada erinevusi objektide loomise vahel Object.create
koos new
. Selle eesmärk on ka rõhutada, et kuigi funktsioon, millega objekt on loodud new
võib asuda koodis suvalises kohas, peab objekt juba olemas olema, enne kui sellega saab instantseerida Object.create
(ES5_Object objekt ei ole funktsioon).
Ridadel 3 ja 4, et määrata atribuutidele vaikeväärtus funktsioonis, millega objekti luuakse new
, määratakse iga omadus vastava argumendi väärtusele või (||
), kui argumente pole edastatud, st kui need on määratlemata (undefined
), kuna seda asjaolu hinnatakse false
, määratakse vaikeväärtus.
Kontekst, milles funktsiooni täidetakse JavaScript tõstatab kaks probleemi, mida on oluline meeles pidada ja mis võivad selle programmeerimiskeele kasutamisel pärast teistega koostööd teha ka segadust tekitada, näiteks C o C + +, meie puhul. Kontekst sisaldab funktsiooni ulatuses määratletud muutujaid (ja globaalseid), mis muide tõstatab huvitava kontseptsiooni, "sulgumised", mis kehtestavad kogu programmeerimisstiili. JavaScript. Nagu öeldud, võis seda eeldada this
, mis viitab objektile, kui seda kasutatakse seda määratlevas koodis, säilitatakse täitmiskontekst, milles see on määratletud, kuid see, mida see kasutab, on kontekst, millest funktsioon kutsutakse. See käitumine on enamikul juhtudel läbipaistev, kuid segadust võib tekitada kahel juhul: teise funktsiooni sees määratletud funktsioon ja objekti sündmusest välja kutsutud meetod. window
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
var primero=“Primero global”;
var segundo=“Segundo global”;
var Contexto=
{
primero:“Primero en contexto”,
segundo:“Segundo en contexto”,
probar:
function()
{
console.log(“Primero en contexto: “+this.primero);
console.log(“Segundo en contexto: “+this.segundo);
function probar_dentro()
{
console.log(“Primero dentro: “+this.primero);
console.log(“Segundo dentro: “+this.segundo);
}
probar_dentro();
}
}
var probador=Object.create(Contexto);
probador.probar();
/*
Primero en contexto: Primero en contexto
Segundo en contexto: Segundo en contexto
Primero dentro: Primero global
Segundo dentro: Segundo global
*/
|
Eelmise koodi täitmisel kuvatakse konsoolis lõpus olev kommenteeritud tekst. Kaks märgitud joont peegeldavad käitumist, mis võib segadust tekitada: funktsiooni täitmise kontekst probar_dentro()
ei probar()
, nagu arvata võib, aga window
, mis näitab globaalseid muutujaid, mitte samanimelisi omadusi. Kui te seda käitumist ei soovi, looge lihtsalt kõrgeima taseme funktsioonis muutuja ja määrake see this
, nagu järgmises koodis.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
var primero=“Primero global”;
var segundo=“Segundo global”;
var Contexto=
{
primero:“Primero en contexto”,
segundo:“Segundo en contexto”,
probar:
function()
{
var esto=this;
console.log(“Primero en contexto: “+esto.primero);
console.log(“Segundo en contexto: “+esto.segundo);
function probar_dentro()
{
console.log(“Primero dentro: “+esto.primero);
console.log(“Segundo dentro: “+esto.segundo);
}
probar_dentro();
}
}
var probador=Object.create(Contexto);
probador.probar();
/*
Primero en contexto: Primero en contexto
Segundo en contexto: Segundo en contexto
Primero dentro: Primero en contexto
Segundo dentro: Segundo en contexto
*/
|
Täitmise konteksti juhtimiseks, kui meetodit sündmusest kutsutakse window
, näiteks brauseriakna suurust muutes, mis on teine eripära JavaScript: võimalus programmeerida "funktsioonide tehaseid", st funktsioone, mis genereerivad muid funktsioone, tagastades need koos return
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
var Contexto=
{
prueba:“objeto”, // La propiedad prueba es de los objetos Contexto
llamar:
function()
{
esto=this;
return function()
{
console.log(“H + “+(Date.now()–hora)+” Contexto: “+esto.prueba);
};
}
}
var prueba=“global”; // Esta variable prueba es global (window.prueba)
var hora=Date.now();
var probador=Object.create(Contexto);
var cosa=probador.llamar();
var pesadez=setInterval(cosa,3000);
setTimeout(function(){clearInterval(pesadez)},30100); // Desactivar la llamada periódica
|
Ülaltoodud näitekoodis meetod llamar()
objektidest Contexto
See ei tee tööd, vaid tagastab anonüümse funktsiooni, mis selle eest hoolitseb. Kontrollimaks, et kõik toimib ootuspäraselt, on olemas globaalne muutuja, millel on sama nimi kui atribuudil, mida funktsioon konsoolis kuvab; Kui kontekst on õige, kuvatakse atribuudi väärtus, mitte globaalse muutuja väärtus.
JavaScript Proovige parandada semikoolonmärke, mille me lausete lõpust välja jätame. See võimaldab pingevaba kirjutamisstiili, kuid on kahe teraga mõõk, mida tuleb hoolikalt käsitleda. Enamikul juhtudel võite mitmerealistes avaldistes tekitatud soovimatute mõjude vältimiseks kasutada sulgusid või eelneda sellele, kuidas JavaScript tõlgendab koodi; Sellepärast sisaldab näite rida 8 function
taga return
, kui ma oleksin kasutanud teist rida, oleks tähendus väga erinev. Minu arvates on kõige loetavam lahendus kasutada vahemuutujat (välistavat) nagu järgmises versioonis; Ilmselgelt, kui käitumisest aru saadakse, vastab otsus programmeerijale.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
var Contexto=
{
prueba:“objeto”, // La propiedad prueba es de los objetos Contexto
llamar:
function()
{
esto=this;
var variable_auxiliar=
function()
{
console.log(“H + “+(Date.now()–hora)+” Contexto: “+esto.prueba);
};
return variable_auxiliar;
}
}
var prueba=“global”; // Esta variable prueba es global (window.prueba)
var hora=Date.now();
var probador=Object.create(Contexto);
var cosa=probador.llamar();
var pesadez=setInterval(cosa,3000);
setTimeout(function(){clearInterval(pesadez)},30100);
|
Samas tähenduses avaldise kui funktsiooni hindamine, st funktsiooni tagastamine, mitte väärtuse, mille funktsioon tagastab; viimase näite real 21 (see oli eelmise näite real 19) see peatub clearInterval
funktsioon, mida kutsutakse koos setInterval
. Et see toimiks 30 sekundit, lükatakse peatus edasi setTimeout
, mis omakorda vajab esimese argumendina funktsiooni; täitmise parameetrina edastamiseks clearInterval
muutujaga, mis sisaldab perioodilist kõnet (ja mitte funktsiooni clearInterval
) on see, mille jaoks luuakse viimasel real olev anonüümne funktsioon.
Valik, kas kirjutada kood integreerides funktsiooni definitsiooni, kompaktsemalt (nagu real 21) või kasutada abimuutujat, mis on minu arvates paremini loetav (nagu ridadel 19 ja 20), varieerub jõudluses vähe ning sõltub rohkem stiilist ja loetavusest. hooldus.
Koodi testimiseks saate enne andmete serverisse omamist kasutada soovitud vahemikus juhuslike väärtuste generaatorit või koostada kontrollitud väärtustega tabeleid, mis simuleerivad soovitud tingimustes töötamist. Järgmises näites kasutatakse lihtsat andmegeneraatorit kogu vahemikus, mistõttu näivad need pisut liialdatud.
Testimiseks saate laadige alla näite täielik kood sisse kirjutatud veebilehe poolt moodustatud HTML, stiil CSS ja kood JavaScript. Viimane on kõige asjakohasem, kuna muud komponendid on vaid minimaalselt toetatud, väga lihtsustatud ja on vastavate jaotiste artiklites palju rohkem välja töötatud.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
<!DOCTYPE html>
<html lang=“es”>
<head>
<meta charset=“utf-8”>
<title>Temperatura</title>
<script type=“text/javascript” src=“https://polaridad.es/javascript-grafico-svg-sensor-internet-de-las-cosas-iot/grafico.js”></script>
<link rel=“stylesheet” href=“estilo.css” type=“text/css” media=“all”>
</head>
<body onload=“iniciar_grafico(‘grafico’,’valor’,’fecha’);”>
<div id=“temperatura”>
<div id=“ultimo_valor”>
<div id=“fecha”></div>
<div id=“valor”></div>
</div>
<div id=“grafico”></div>
</div>
</body>
</html>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
body
{
margin:0px 0px 0px 0px;
}
#ultimo_valor
{
box–sizing:border–box;
width:100%;
height:40px;
padding:8px 0px 8px 14px;
font–family:monospaced;
font–size:18px;
color:#205587;
background–color:#86A7D0;
}
#fecha
{
float:left;
margin–right:15px;
}
#valor
{
float:left;
}
#grafico
{
width:100%;
height:200px;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
|
var Grafico=
{
contenedor_svg:void(0), // Objeto SVG con el que se dibuja el gráfico. Se inicializa con void(0) para asegurarse de que es === undefined al principio
contenedor_html:void(0), // Objeto HTML que contiene al objeto SVG con el gráfico (seguramente un div). Se inicializa con void(0) para asegurarse de que es === undefined al principio
contenedor_valor:void(0), // Objeto HTML en el que se muestra el último valor cargado del servidor
contenedor_fecha:void(0), // Objeto HTML para mostrar la fecha del último valor
pagina_servidor:“ultimo_valor_sensor.php”, // página en la que se consultan los datos
consulta:“fr1”, // Valor del parámetro con el que se consulta el servidor. La URL sería algo como http://servidoriot.com/ultimo_valor_sensor.php?zona=fr1
NS:“http://www.w3.org/2000/svg”, // Nombre del espacio de nombres (name space NS)
MINIMO:0, // Índice del menor valor admisible en el gráfico SVG. Los valores menores se saldrán del gráfico salvo por un margen que permite tener una idea de la tendencia
OPTIMO:1, // Índice del mejor valor del parámetro medido. Valor deseado para el parámetro monitorizado. Sirve para tener una idea rápida de cómo de correcto es el estado del sistema
MAXIMO:2, // Índice del mayor valor admisible en el gráfico SVG. Los valores mayores se saldrán del gráfico salvo por un margen que permite tener una idea de la tendencia
maximo_puntos:0, // Número máximo de vértices representados (pueden dibujarse menos si se recortan por la parte izquierda)
valor:[], // Últimos valores cargados del servidor
trazado:[], // Trazados representados (en principio se trata de representar uno con relleno y otro con línea)
cerrado:true, // Cuando vale true se dibuja el perfil y el área (la línea del gráfico y una zona rellena debajo). Cuando vale false solo se dibuja la línea
simbolo:[], // Objetos SVG utilizados para marcar los vértices de la línea (círculos)
linea_referencia:[], // Líneas horizontales en los valores de referencia
texto_referencia:[], // Objetos texto que rotulan los valores de referencia
fondo_referencia:[], // Rectángulos bajo los textos de los valores de referencia
medida_caja_svg:[100.0,100.0], // Ancho,Ancho del objeto SVG (aunque al dibujarlo con el código HTML tomará otras dimensiones ya que se dimensiona al 100% de su contenedor
correccion_caja_svg:[1.0,1.0], // Coeficientes para calcular la medida en el gráfico de un objeto del que se sabe el valor absoluto (Se usa el píxel como unidad)
tiempo_representado:0, // Milisegundos visibles en el gráfico empezando en el valor mayor (fecha y hora del último valor monitorizado)
valor_referencia:[0,0,0], // Valores de referencia [mínimo,óptimo,máximo]
margen_valor:0, // Zona por encima del valor mayor y por debajo del valor menor que se representa para tener una idea aproximada de la tendencia cuando los datos monitorizados rebasen los valores máximo y/o mínimo
escala_valor:[1.0,1.0], // Coeficientes que multiplican el valor monitorizado (y almacenado en el servidor) para calcular el representado según las dimensiones del gráfico
desplazamiento_valor:[0.0,0.0], // Desplazamiento que se suma al tiempo (X) y al valor (Y) para representarlo en el rango especificado para el gráfico
area_bajo_linea:true, // True para dibujar una zona rellena además del perfil (línea) del gráfico
medida_simbolo:[5,5], // Valor absoluto (en píxeles) del ancho y el alto del dibujo que se hace en los vértices de la línea del gráfico
tipografia:“sans-serif”, // Tipo de letra usado para rotular el gráfico (se usa solamente una tipografía por uniformidad)
altura_texto:10.0, // Altura de los textos en valor absoluto (píxeles). No todos los navegadores soportan todos los valores intermedios, será necesario coordinarlo con los valores que estén relacionados
escala_horizontal_texto:1, // Transformación que se aplica al texto para corregir la que implica la proporción del gráfico
color_fondo:“”, // Color de fondo del contenedor HTML del objeto SVG (Si es una cadena vacía no se cambia)
color_simbolos:“#000000”, // Color de los símbolos que se dibujan en los vértices de la línea del gráfico
color_referencia:[“#000000”,“#000000”,“#000000”], // Color de la referencia que indica el valor [mínimo,óptimo,máximo]
color_tipografia:“#FFFFFF”, // Color del tipo de letra con que se rotulan las referencias
grosor_trazado:4, // Grosor de la línea del gráfico
color_trazado:“#000000”, // Color de la línea del gráfico
color_relleno:“#000000”, // Color del relleno del gráfico
opacidad_relleno:1.0, // Opacidad del relleno del gráfico
grosor_referencia:0.5, // Grosor de la línea que se dibuja como referencia en valor absoluto (píxeles)
opacidad_referencia:1.0, // Opacidad de la línea de referencia. Si se dibuja sobre el gráfico con cierta transparencia permite ver el dibujo bajo ella
relleno_fondo_referencia:7.0, // Margen entre el fondo de la referencia y el texto medido en valor absoluto (la línea empieza en el margen izquierdo y recorre todo el gráfico)
margen_fondo_referencia:10.0, // Separación de la referencia y el borde izquierdo del gráfico medido en valor absoluto (la línea empieza en el margen izquierdo y recorre todo el gráfico)
ancho_fondo_referencia:50.0, // Medida horizontal del rectángulo que hace de fondo al texto de la referencia medido en valor absoluto
texto_valor:[“temperatura: “,” °C”], // Prefijo y sufico con los que se rotula el valor monitorizado
texto_hora:[“hora “,“”], // Prefijo y sufijo con los que se rotula la hora (cuando solamente se rotula la hora)
texto_fecha:[“”,“”], // Prefijo y sufijo con los que se rotula la fecha (cuando solamente se rotula la fecha)
texto_fecha_hora:[“el “,” a las “,” | “], // Prefijo con el que se rotula la hora, separador de fecha y hora y sufjo de la hora cuando se rotula la fecha y la hora
HORA:0, // Constante que representa la hora para el modo de la fecha/hora
FECHA:1, // Constante que representa la fehca para el modo de la fecha/hora
FECHA_Y_HORA:2, // Constante que representa rotular la fecha y la hora (para el modo de fecha/hora)
modo_fecha:2, // 0->hora, 1-> fecha 2-> fecha y hora
repetir:null, // Función llamada por setInterval
nueva_proporcion: // Calcular la nueva proporción (al iniciar y al redimensionar el contenedor del gráfico) para transformar el texto
function()
{
if(this.contenedor_svg!==undefined) // Se entiende que si no es undefined se ha asignado un objeto
{
if(this.contenedor_svg.nodeName===“svg”) // Si el objeto asignado es un SVG
{
this.escala_horizontal_texto=parseFloat(getComputedStyle(this.contenedor_svg).height)/parseFloat(getComputedStyle(this.contenedor_svg).width); // La escala debe calcularse cada vez ya que no se sabe si se ha redimensionado el objeto HTML que contiene al objeto SVG y que le da el tamaño
}
}
},
nueva_correccion_caja_svg:
function()
{
if(this.contenedor_svg!==undefined) // Se entiende que si no es undefined se ha asignado un objeto
{
if(this.contenedor_svg.nodeName.toLowerCase()===“svg”) // Si el objeto asignado es un SVG
{
this.correccion_caja_svg[0]=this.medida_caja_svg[0]/parseFloat(getComputedStyle(this.contenedor_svg).width);
this.correccion_caja_svg[1]=this.medida_caja_svg[1]/parseFloat(getComputedStyle(this.contenedor_svg).height);
}
}
},
nueva_escala:
function()
{
if(this.tiempo_representado>0) // Antes de inicializar el objeto el tiempo representado es cero
{
this.escala_valor[0]=this.medida_caja_svg[0]/this.tiempo_representado; // Coeficiente que multiplica a los valores horizontales (tiempo) para calcular las coordenadas X
this.escala_valor[1]=this.medida_caja_svg[1]/(Math.abs(this.valor_referencia[this.MAXIMO]–this.valor_referencia[this.MINIMO])+this.margen_valor*2); // Coeficiente que multiplica a los valores (vertical) para calcular las coordenadas Y
}
},
nuevo_desplazamiento:
function()
{
if(this.tiempo_representado>0) // Antes de inicializar el objeto el tiempo representado es cero
{
this.desplazamiento_valor[0]=this.valor[this.valor.length–1][0]–this.tiempo_representado; // Valor desde el que se empieza a contar el tiempo: el valor mayor (último) menos el rango de tiempo representado
this.desplazamiento_valor[1]=this.margen_valor–this.valor_referencia[this.MINIMO]; // Valor menor mostrado (al menor se le añade un margen para visualizar el principio de los valores fuera del rango permitido)
}
},
crear_svg: // Crear el objeto SVG dentro del objeto HTML
function()
{
if(this.contenedor_html!==null&&this.contenedor_html!==undefined) // Ya se ha asignado el objeto HTML
{
if(this.contenedor_html.nodeType===1) // Es un objeto HTML válido
{
// Color de fondo del objeto HTML
if(this.color_fondo!==“”)
{
this.contenedor_html.style.backgroundColor=this.color_fondo;
}
// Contenedor SVG
this.contenedor_svg=document.createElementNS(this.NS,“svg”); // Crear un objeto SVG
this.contenedor_svg.setAttribute(“width”,“100%”); // Ancho del objeto SVG
this.contenedor_svg.setAttribute(“height”,“100%”); // Alto del objeto SVG
this.contenedor_svg.setAttribute(“viewBox”,“0 0 “+this.medida_caja_svg[0]+” “+this.medida_caja_svg[1]); // Zona del SVG que se muestra
this.contenedor_svg.setAttribute(“preserveAspectRatio”,“none”); // No preservar la proporción para ocupar todo el objeto HTML que hace de contenedor
this.contenedor_html.appendChild(this.contenedor_svg); // Añadir al contenedor HTML el objeto SVG (que será el contenedor del gráfico)
// Trazado
this.trazado[0]=document.createElementNS(this.NS,“path”); // Crear el trazado que soporta el relleno
this.trazado[0].style.fill=this.color_relleno;
this.trazado[0].style.fillOpacity=this.opacidad_relleno;
this.trazado[0].style.stroke=“none”;
this.contenedor_svg.appendChild(this.trazado[0]); // Añadir el relleno al SVG
this.trazado[1]=document.createElementNS(this.NS,“path”); // Crear el trazado que soporta el perfil
this.trazado[1].setAttribute(“vector-effect”,“non-scaling-stroke”); // No mantener la proporción en el trazado (no deformarlo)
this.trazado[1].style.fill=“none”;
this.trazado[1].style.stroke=this.color_trazado;
this.trazado[1].style.strokeWidth=this.grosor_trazado;
//this.trazado[1].style.strokeOpacity=1.0; // La opacidad por defecto es 1.0
this.contenedor_svg.appendChild(this.trazado[1]); // Añadir el perfil al SVG
// Símbolos para los vértices
var ahora=Date.now()–30000; // Fecha y hora actual menos 30 segundos
for(var contador_vertices=0;contador_vertices<this.maximo_puntos;contador_vertices++)
{
this.valor[contador_vertices]=[];
this.valor[contador_vertices][0]=ahora; // Inicializar los valores a la fecha y hora actual menos 30 segundos
this.valor[contador_vertices][1]=this.valor_referencia[this.OPTIMO]; // Inicializar los valores al óptimo
this.simbolo[contador_vertices]=document.createElementNS(this.NS,“ellipse”); // Crear una elipse (círculo) para cada vértice
this.simbolo[contador_vertices].style.fill=this.color_simbolos;
this.simbolo[contador_vertices].style.fillOpacity=1.0;
this.simbolo[contador_vertices].style.stroke=“none”;
this.contenedor_svg.appendChild(this.simbolo[contador_vertices]); // Añadir el símbolo al SVG
}
//this.nuevo_desplazamiento(); // Necesario si se asignaran las alturas de las referencias
for(var contador_referencia=0;contador_referencia<this.valor_referencia.length;contador_referencia++)
{
// Línea de referencia
//var posicion_corregida=this.medida_caja_svg[1]-(this.valor_referencia[contador_referencia]+this.desplazamiento_valor[1])*this.escala_valor[1]; // Necesario si se asignaran las alturas de las referencias
this.linea_referencia[contador_referencia]=document.createElementNS(this.NS,“line”); // Crear la línea que representa el valor mínimo
this.linea_referencia[contador_referencia].style.stroke=this.color_referencia[contador_referencia];
this.linea_referencia[contador_referencia].style.strokeWidth=this.grosor_referencia;
this.linea_referencia[contador_referencia].style.strokeOpacity=this.opacidad_referencia;
this.linea_referencia[contador_referencia].setAttribute(“x1”,0.0); // Las líneas de referencia empiezan en el borde izquierdo…
this.linea_referencia[contador_referencia].setAttribute(“x2”,this.medida_caja_svg[0]); // …y terminan en el derecho
//this.linea_referencia[contador_referencia].setAttribute(“y1”,posicion_corregida); // Ambos extremos a la altura correspondiente a la referencia [mínimo,óptimo,máximo]
//this.linea_referencia[contador_referencia].setAttribute(“y2”,posicion_corregida); // Ambos extremos a la altura correspondiente a la referencia [mínimo,óptimo,máximo]
this.contenedor_svg.appendChild(this.linea_referencia[contador_referencia]);
// Rectángulo de fondo del texto que indica el valor de referencia
this.fondo_referencia[contador_referencia]=document.createElementNS(this.NS,‘rect’);
this.fondo_referencia[contador_referencia].style.fill=this.color_referencia[contador_referencia];
this.fondo_referencia[contador_referencia].style.fillOpacity=1.0;
this.fondo_referencia[contador_referencia].style.stroke=“none”;
this.contenedor_svg.appendChild(this.fondo_referencia[contador_referencia]);
// Texto de referencia
this.texto_referencia[contador_referencia]=document.createElementNS(this.NS,“text”); // Crear el texto para rotular la referencia
this.texto_referencia[contador_referencia].setAttribute(“font-family”,this.tipografia); // Asignar el tipo de letra
this.texto_referencia[contador_referencia].setAttribute(“fill”,this.color_tipografia); // Asignar el color
//this.texto_referencia[contador_referencia].textContent=””+(this.valor_referencia[contador_referencia]>=0?”+”:””)+this.valor_referencia[contador_referencia]; // Texto que se rotula (los valores máximo, óptimo y mínimo ya deben estar asignados)
this.contenedor_svg.appendChild(this.texto_referencia[contador_referencia]);
}
}
}
},
ajustar_prporcion:
function()
{
this.nueva_proporcion();
this.nueva_correccion_caja_svg();
var posicion_corregida;
for(var contador_vertices=0;contador_vertices<this.simbolo.length;contador_vertices++)
{
this.simbolo[contador_vertices].setAttribute(“rx”,this.medida_simbolo[0]*this.correccion_caja_svg[0]);
this.simbolo[contador_vertices].setAttribute(“ry”,this.medida_simbolo[1]*this.correccion_caja_svg[1]);
}
for(var contador_referencia=0;contador_referencia<this.valor_referencia.length;contador_referencia++)
{
posicion_corregida=this.medida_caja_svg[1]–(this.valor_referencia[contador_referencia]+this.desplazamiento_valor[1])*this.escala_valor[1];
this.fondo_referencia[contador_referencia].setAttribute(“x”,this.margen_fondo_referencia*this.correccion_caja_svg[0]);
this.fondo_referencia[contador_referencia].setAttribute(“y”,posicion_corregida–(this.altura_texto+this.relleno_fondo_referencia*2.0)*this.correccion_caja_svg[1]/2.0);
this.fondo_referencia[contador_referencia].setAttribute(“width”,this.ancho_fondo_referencia*this.correccion_caja_svg[0]);
this.fondo_referencia[contador_referencia].setAttribute(“height”,(this.altura_texto+this.relleno_fondo_referencia*2.0)*this.correccion_caja_svg[1]);
this.linea_referencia[contador_referencia].setAttribute(“y1”,posicion_corregida);
this.linea_referencia[contador_referencia].setAttribute(“y2”,posicion_corregida);
this.texto_referencia[contador_referencia].setAttribute(“transform”,“scale(“+this.escala_horizontal_texto+“,1.0)”);
this.texto_referencia[contador_referencia].setAttribute(“font-size”,this.altura_texto*this.correccion_caja_svg[1]);
this.texto_referencia[contador_referencia].setAttribute(“x”,(this.margen_fondo_referencia+this.relleno_fondo_referencia)*this.correccion_caja_svg[0]/this.escala_horizontal_texto);
this.texto_referencia[contador_referencia].setAttribute(“y”,posicion_corregida+this.altura_texto/2.0*this.correccion_caja_svg[1]);
this.texto_referencia[contador_referencia].textContent=(this.valor_referencia[contador_referencia]>=0?“+”:“”)+this.valor_referencia[contador_referencia]; // Texto que se rotula
}
},
rotar_valores:
function()
{
for(var contador_valor=0;contador_valor<this.valor.length–1;contador_valor++)
{
this.valor[contador_valor][0]=this.valor[contador_valor+1][0];
this.valor[contador_valor][1]=this.valor[contador_valor+1][1];
}
},
nuevo_valor_aleatorio:
function()
{
this.rotar_valores();
this.valor[this.valor.length–1][0]=this.valor[this.valor.length–2][0]+1000+Math.random()*1000; // El nuevo tiempo es el anterior más un segundo más un valor entre 0 y un segundo
this.valor[this.valor.length–1][1]=Math.random()*Math.abs(this.valor_referencia[this.MAXIMO]–this.valor_referencia[this.MINIMO])+this.valor_referencia[this.MINIMO]; // Un valor aleatorio entre el máximo y el mínimo
this.nuevo_desplazamiento(); // Cada nuevo valor cambia el desplazamiento en horizontal
this.dibujar_nuevo_valor(true);
this.dibujar_nuevo_valor(false);
this.rotular_nuevo_valor();
this.ritular_nueva_fecha();
},
cargar_nuevo_valor:
function()
{
var consulta=‘zona=”+this.consulta;
var resultado;
var ajax;
if(window.XMLHttpRequest)
{
ajax=new XMLHttpRequest(); // ajax=Object.create(XMLHttpRequest);
}
else // Versiones antiguas de MS Internet Explorer
{
ajax=new ActiveXObject(“Microsoft.XMLHTTP”);
}
ajax.onreadystatechange=
function()
{
if(ajax.readyState==4&&ajax.status==200&&ajax.responseType==“json”)
{
resultado=JSON.parse(ajax.responseText);
if(resultado.fecha>objeto_grafico.fecha[objeto_grafico.fecha.length–1])
{
this.rotar_valores();
this.valor[this.valor.length–1][0]=resultado.fecha;
this.valor[this.valor.length–1][1]=resultado.temperatura;
this.nuevo_desplazamiento(); // Cada nuevo valor cambia el desplazamiento en horizontal
this.dibujar_nuevo_valor(true);
this.dibujar_nuevo_valor(false);
this.rotular_nuevo_valor();
this.ritular_nueva_fecha();
}
}
}
ajax.open(“POST”,this.pagina_servidor);
ajax.setRequestHeader(“Method”,“POST “+this.pagina_servidor+” HTTP/1.1″);
ajax.setRequestHeader(“Content-type”,“application/x-www-form-urlencoded”);
ajax.setRequestHeader(“Content-length”,consulta.length);
ajax.setRequestHeader(“Connection”,“close”);
ajax.send(consulta);
},
rotular_nuevo_valor:
function()
{
var valor_redondeado=Math.round(this.valor[this.valor.length–1][1]*100.0)/100.0;
this.contenedor_valor.innerHTML=this.texto_valor[0]+valor_redondeado+this.texto_valor[1];
},
ritular_nueva_fecha:
function()
{
var fecha_lectura=new Date(this.valor[this.valor.length–1][0]);
var texto_fecha=this.texto_hora[0];
texto_fecha+=(fecha_lectura.getHours()<10?“0”:“”)+fecha_lectura.getHours();
texto_fecha+=“:”;
texto_fecha+=(fecha_lectura.getMinutes()<10?“0”:“”)+fecha_lectura.getMinutes();
texto_fecha+=“:”;
texto_fecha+=(fecha_lectura.getSeconds()<10?“0”:“”)+fecha_lectura.getSeconds();
texto_fecha+=this.texto_hora[1];
this.contenedor_fecha.innerHTML=texto_fecha;
},
dibujar_nuevo_valor: // Dibujar el gráfico cuando llega un nuevo valor (que estará almacenado en el vector valor
function(cerrado)
{
// Si cerrado es undefined se evalúa a false, que se toma como valor por defecto
var contador_valor=this.valor.length–1; // Variable para recorrer los valores (índice)
var sin_recortar=true; // False si la gráfico se sale de la caja (si se sale, si recorta, se hace false para no seguir dibujando puntos)
var posicion=[]; // Variable intermedia (para hacer más legible el código) con la que calcular la posición horizontal y vertical de un punto del trazado
var coordenadas_trazado=“M “; // Cadena de texto que representa la propiedad “d” del trazado SVG
if(cerrado) // Si el trazado que se está dibujando está cerrado (no confundir con this.cerrado que determina si se dibujan los dos trazados, la línea y el relleno)
{
coordenadas_trazado+=this.medida_caja_svg[0]+“,”+this.medida_caja_svg[1]+” L “; // …se empieza por la parte inferior de la caja
}
while(contador_valor>=0&&sin_recortar) // Mientras queden valores por representar y no se haya llegado al borde izquierdo del gráfico…
{
posicion[0]=(this.valor[contador_valor][0]–this.desplazamiento_valor[0])*this.escala_valor[0]; // Calcular la X restando al tiempo el desplazamiento y convirtiéndolo a la escala del gráfico con el coeficiente horizontal
posicion[1]=this.medida_caja_svg[1]–(this.valor[contador_valor][1]+this.desplazamiento_valor[1])*this.escala_valor[1]; // Calcular la Y restando del alto de la caja (la Y crece hacia abajo en SVG)
this.simbolo[contador_valor].setAttribute(“cx”,posicion[0]);
this.simbolo[contador_valor].setAttribute(“cy”,posicion[1]);
coordenadas_trazado+=posicion[0]+“,”+posicion[1]; // Formar la coordenada con la X y la Y
if(posicion[0]>0) // Si no se ha rebasado el margen izquierdo…
{
coordenadas_trazado+=contador_valor>0?” L “:“”; // …y quedan valores que representar, añadir una nueva línea (código L) para el próximo
contador_valor—; // Pasar al siguiente valor
}
else // Si se ha rebasado el margen izquierdo…
{
sin_recortar=false; // …abandonar el modo sin recorte (lo que terminará de calcular coordenadas)
}
}
if(cerrado) // Si se dibuja un trazado (path) cerrado…
{
coordenadas_trazado+=” L “+posicion[0]+“,”+this.medida_caja_svg[1]+” Z”; // …se termina por la parte inferior de la caja y se añade Z para cerrarlo en SVG
}
this.trazado[cerrado?0:1].setAttribute(“d”,coordenadas_trazado); // Cambiar las coordenadas del trazado (propiedad “d”) por las que se han calculado
for(;contador_valor>=0;contador_valor—)
{
this.simbolo[contador_valor].setAttribute(“cx”,–10000);
this.simbolo[contador_valor].setAttribute(“cy”,0);
}
}
}
var temperatura_frigorifico;
function iniciar_grafico(nombre_objeto_grafico,nombre_objeto_valor,nombre_objeto_fecha)
{
temperatura_frigorifico=Object.create(Grafico);
temperatura_frigorifico.contenedor_html=document.getElementById(nombre_objeto_grafico);
temperatura_frigorifico.contenedor_valor=document.getElementById(nombre_objeto_valor);
temperatura_frigorifico.contenedor_fecha=document.getElementById(nombre_objeto_fecha);
temperatura_frigorifico.color_fondo=“#A8C3EA”;
temperatura_frigorifico.color_trazado=“#205587”;
temperatura_frigorifico.grosor_trazado=3;
temperatura_frigorifico.color_relleno=“#205587”;
temperatura_frigorifico.opacidad_relleno=0.5;
temperatura_frigorifico.color_simbolos=“#205587”;
temperatura_frigorifico.color_referencia[Grafico.MINIMO]=“#621D87”;
temperatura_frigorifico.color_referencia[Grafico.OPTIMO]=“#1D8762”;
temperatura_frigorifico.color_referencia[Grafico.MAXIMO]=“#871E35”;
temperatura_frigorifico.grosor_referencia=1.5;
temperatura_frigorifico.opacidad_referencia=0.5;
temperatura_frigorifico.tipografia=“monospaced”;
temperatura_frigorifico.color_tipografia=“#A8C3EA”;
temperatura_frigorifico.cerrado=true; // Dibujar una línea y una zona rellena debajo (true por defecto)
temperatura_frigorifico.maximo_puntos=32; // Un espacio de 30 segundos representados con un intervalo mínimo de 1 segundo necesitan como máximo 31 puntos, se añade uno por seguridad (por si algún valor monitorizado estuviera por debajo del segundo)
temperatura_frigorifico.crear_svg();
temperatura_frigorifico.nueva_correccion_caja_svg();
temperatura_frigorifico.tiempo_representado=30000;
temperatura_frigorifico.valor_referencia[Grafico.MINIMO]=–5;
temperatura_frigorifico.valor_referencia[Grafico.OPTIMO]=5;
temperatura_frigorifico.valor_referencia[Grafico.MAXIMO]=10;
temperatura_frigorifico.margen_valor=3;
temperatura_frigorifico.nueva_escala();
temperatura_frigorifico.nuevo_desplazamiento(); // El desplazamiento se (re)calcula cada vez que se añade un valor
temperatura_frigorifico.ajustar_prporcion();
window.addEventListener(“resize”,function(){temperatura_frigorifico.ajustar_prporcion()}); // Versión moderna
temperatura_frigorifico.repetir=setInterval(function(){temperatura_frigorifico.nuevo_valor_aleatorio()},1000);
}
|
Postita kommentaar