Generujte a upravujte SVG grafiku údajov zo senzorov pripojených k internetu vecí pomocou JavaScriptu
V tejto poslednej časti série článkov o kreslení grafiku s údajmi zo senzorov pripojených k internetu vecí, je čas hovoriť o tom, ako generovať alebo upravovať pomocou JavaScript výkresy vo formáte SVG a niektoré prvky HTML ktoré slúžia ako kontajner alebo prezentujú doplnkové informácie ku grafike.
Cieľoví používatelia tohto tutoriálu majú vytvoriť profil elektroniky a počítačového programovania. mikrokontroléry, nemusia byť oboznámení HTML, CSS o SVG; Z tohto dôvodu bol v predchádzajúcich častiach urobený krátky úvod do jazyka alebo zodpovedajúcej technológie. V tejto poslednej časti je prístup trochu odlišný, keďže čitatelia určite vedia programovať, je možné, že pomocou jazyka C + + čo ako JavaScript, zdieľa základnú syntax s C a možno ho použiť ako referenciu na preskočenie väčšiny základných programovacích konceptov a zamerať sa tak na rozdiely a špecifické využitie, ktoré nás zaujíma pri vytváraní senzorovej grafiky v IoT.
Názov naznačuje prvý rozdiel: JavaScript Je to programovací jazyk scenár (pomlčka) a ako taká je interpretovať, nie je potrebné ho kompilovať; kontext, v ktorom sa scenár (napríklad webový prehliadač) prečíta, preloží a vykoná príkazy. Aby som bol presný, vo väčšine prípadov existuje a runtime kompilácia (JIT), ale pre proces písania kódu JavaScript Nás sa to netýka, jednoducho napíšeme kód a môže to fungovať.
Názov obsahuje aj prvý zmätok: JavaScript nemá s ním najmenší vzťah Jáva. Spočiatku, keď bol vyvinutý Netscape pre svoj prehliadač sa najprv nazýval Mocha a potom menej mätúci LiveScript. Po úspešnej implementácii do prehliadačov a ich prekročení bol štandardizovaný ako ECMAScript (Na ECMA-262, verzia 6 v čase písania článku), aby sa stal neutrálnym vzhľadom na prehliadače, ktoré ho implementujú. V súčasnosti existuje aj štandard ISO od verzie 5, 2011 (ISO / IEC 16262: 2011 v čase písania článku)
Premenné, základné dátové typy a objekty v JavaScripte
Na rozdiel od toho, čo sa deje napr C + +, en JavaScript dátový typ nie je zahrnutý pri deklarovaní premennej a tiež typ spojený s premennou nie je fixný, je možné priradiť hodnotu iného typu počas vykonávania programu.
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
|
V predchádzajúcom príklade bola deklarovaná premenná "thing" (bez uvedenia typu údajov), potom sú priradené údaje iného typu a konzultované s typeof
ten typ JavaScript ktoré interpretoval. Ak chcete odladiť kód, môžete ho napísať do inšpekčnej konzoly webového prehliadača (čo neovplyvní prezentáciu webu) pomocou console.log()
.
Na vynútenie prevodu údajov na konkrétny typ, najmä textových na číselné, môžete použiť funkcie ako napr parseInt()
o parseFloat()
ktoré sa prevedú na celé čísla alebo čísla s pohyblivou rádovou čiarkou. Opačnú konverziu je možné vykonať pomocou String()
, aj keď je nepravdepodobné, že to bude potrebné, pretože zvyčajne postačuje automatická konverzia. s parseFloat()
Môžete napríklad získať hodnotu vlastnosti webovej stránky, ako je šírka alebo výška objektu, ktorá zahŕňa jednotky; Týmto spôsobom výraz parseFloat("50px");
ako výsledok vráti 50, číselnú hodnotu.
En JavaScript nie je rozdiel medzi dvojitými a jednoduchými úvodzovkami; Dátový typ v oboch prípadoch je string
a každá z nich môže zahŕňať druhú bez potreby únikových kódov.
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
|
V predchádzajúcom príklade je vidieť, že premenná, keď bola deklarovaná (existuje), ale nebola jej priradená žiadna hodnota, obsahuje nedefinovaný dátový typ (undefined
). Nepriradený objekt má hodnotu null
; To znamená, že objekt existuje, ale bez hodnoty; premenná, ktorá by na ňu odkazovala, by nemala a typeof
undefined
ale object
. Objekt môže byť aj prázdny, to znamená, že nemá hodnotu null, ale nemôže mať žiadne vlastnosti.
na definovať objekt v JavaScript sú uzavreté v zátvorkách ({
y }
) vlastnosti alebo metódy oddelené dvojbodkou (:
) názov vlastnosti hodnota vlastnosti a čiarkou (,
) rôzne vlastnosti. Viac informácií o tomto spôsobe vyjadrenia objektu nájdete v článku na Formát JSON.
Hoci môžete použiť syntax, ktorá by vás mohla viesť k opaku, en JavaScript Neexistujú žiadne triedy, ale prototypyTo znamená, že aby objekt zdedil vlastnosti a metódy, vytvorí sa ďalší objekt (prototyp), ktorý ostatní (deti) používajú ako referenciu. Syntax najbližšie k štýlu JavaScript použiť prototyp je Object.create
aj keď je tiež možné (a niekedy užitočné) použiť new
ako v iných objektovo orientovaných jazykoch.
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));
|
na dotaz, či je jeden objekt inštanciou iného, ak ho použijete ako prototyp, ak zdedíte jeho vlastnosti, skrátka môžete použiť instanceof
(vytvorené s new
) alebo isPrototypeOf
(vytvorené s Object.create
), ktorá sa vyhodnotí ako true, keď objekt používa prototyp, a false, keď nie.
Po vytvorení objektu pomocou iného ako prototypu, teda po vytvorení inštancie objektu, môže byť pridať nové vlastnosti alebo prepísať vlastnosti prototypu pomocou bodkovej syntaxe ako v gato.peso=2.5
.
La polia v JavaScript Sú odlišné od tých, v ktorých pravdepodobne poznáte C. Na začiatok sa deklarujú bez potreby uvádzať ich dĺžku, iba so znakmi otvárania a zatvárania hranatých zátvoriek ([
y ]
), komponenty môžu byť heterogénne (rôzne typy údajov v rovnakom poli) a môžu sa pridávať nové prvky bez obmedzenia. Matrice z JavaScript sú vlastne zoznamy (kolekcie) prvkov, do ktorých odkazované číselným indexom alebo názvom. Pole môže súčasne obsahovať číselné indexy a názvy prvkov, ale je bežné používať objekty (vlastnosti) na využitie druhého typu.
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
|
Ako je možné vidieť v predchádzajúcom príklade, ak chcete vedieť, či premenná zodpovedá inštancii poľa (je to objekt poľa), môžete použiť instanceof
, ako sa už používa pri generických objektoch alebo v novších verziách JavaScript môžete sa uchýliť Array.isArray()
Na prístup k prvkom poľa môžete použiť jeho index (matriz[7]
) alebo názvom vlastnosti s názvom v hranatých zátvorkách (matriz["nombre"]
) alebo s obvyklou bodkovou syntaxou pre objekty (matriz.nombre
). Keďže názov je textový reťazec, na jeho zostavenie možno použiť výraz vrátane premenných. Na precyklenie poľa s vlastnosťami je možné použiť slučku s formátom 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
*/
|
Pre náš cieľ je zaujímavé liečiť objekt Date
, pomocou ktorého môžete reprezentovať a spravovať dátum a čas JavaScript. Objekt je možné vytvoriť bez údajov, takže bude mať aktuálny dátum a čas, alebo ho možno vytvoriť uvedením dátumu ako hodnoty, buď v milisekundách od 1. januára 1970 (ako napr. Unixový alebo POSIXový čas ale vyjadrené v milisekundách namiesto sekúnd) alebo špecifikovaním samostatných hodnôt roka, mesiaca, dňa, hodiny...
Objekt obsahuje kompletný rad metódy dotazovania alebo nastavenia dátumu a času:
-
now()
Vráti aktuálny dátum a čas vyjadrený v milisekundách od 1. januára 1970 -
getTime()
|setTime()
Získa alebo zmení hodnotu času v milisekundách od 1. januára 1970. PoužívanievalueOf()
, čo je metóda prítomná vo väčšine objektov, sa získa aj hodnota zodpovedajúceho objektu Date, ako naprgetTime()
s Unixový alebo POSIXový čas vyjadrené v ms. -
getMilliseconds()
|setMilliseconds()
Používa sa na dotazovanie alebo nastavenie zlomkovej milisekundovej časti objektuDate
na ktorom sa vykonáva. Pri konzultácii sa získaná hodnota pohybuje medzi 0 a 999, ale možno priradiť aj väčšie hodnoty, ktoré sa budú hromadiť v celkovom dátume a čase, takže podobne ako ostatné metódy get slúži na zvýšenie hodnoty objektu.Date
(alebo ju znížte, ak sa použijú záporné hodnoty). -
getSeconds()
|setSeconds()
Vráti alebo zmení hodnotu sekúnd objektuDate
. -
getMinutes()
|setMinutes()
Používa sa na konzultáciu alebo nastavenie zápisu objektuDate
. -
getHours()
|setHours()
Umožňuje konzultovať alebo upravovať hodiny (od 0 do 23) objektuDate
. -
getDay()
Vráti deň v týždni pre dátum vyjadrený ako hodnota od 0 do 6 (nedeľa až sobota). -
getDate()
|setDate()
Vráti alebo zmení deň v mesiaci objektuDate
na ktorom sa aplikuje. -
getMonth()
|setMonth()
Používa sa na konzultáciu alebo úpravu čísla mesiaca objektuDate
. -
getFullYear()
|setFullYear()
Dotazuje alebo nastaví hodnotu roka na objekte obsahujúcom dátum a čas.
Predchádzajúce metódy Date
obsahovať verziu UTC aby bolo možné priamo pracovať s univerzálnym časom bez toho, aby ste museli robiť medzivýpočty. V tomto zmysle napr. getHours()
má verziu getUTCHours()
o getMilliseconds()
alternatíva getUTCMilliseconds()
pracovať alternatívne s oficiálnym (zákonným) alebo univerzálnym časom. s getTimezoneOffset()
Môžete poznať rozdiel, ktorý existuje medzi svetovým časom a miestnym oficiálnym časom.
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;
|
JavaScript funkcie
Ak to čítate, určite viete, ako programovať. mikrokontroléry en C v C + + a poznať pojem funkcie. Hoci základná myšlienka je rovnaká, v JavaScript Spôsob, akým sú definované a používané, je trochu odlišný. Na začiatok už bolo povedané, JavaScript Nepoužíva explicitne dátové typy, takže ich pri definovaní funkcie nemusíte uvádzať. Nasledovať, Nie je povinné, aby funkcia mala názov, môžu byť anonymné. Môžu byť spojené s premennou na ich vyvolanie, ale tiež to nemusí byť potrebné, pretože niekedy je užitočné vyvolať ich okamžite, pre ktoré sa zátvorky a parametre pridajú po definícii funkcie.
Ak chcete definovať funkciu, prefix function
, ak je to možné, napíšte názov, argumenty (parametre odovzdané funkcii) do zátvoriek a kód, ktorý sa vykoná pri vyvolaní funkcie, do zložených zátvoriek.
1
2
3
4
5
|
function doble(numero)
{
var resultado=numero*2;
return resultado;
}
|
Iste, v predchádzajúcom príklade nebola premenná „výsledok“ vôbec potrebná, ale je to dobrá výhovorka na zapamätanie si variabilný rozsah, ktorý funguje tak, ako očakávate: premenná „výsledok“ existuje iba v rámci funkcie „double“. In JavaScript možno tiež použiť let
, namiesto var
, na rozsah premennej na kontext bloku kódu (uzavretý v zložených zátvorkách, {
y }
)
Keď sme v predchádzajúcej časti hovorili o objektoch, niečo zásadné chýbalo: vlastnosti boli definované, ale metódy neboli definované. Podľa očakávania, objektové metódy sú funkcie, nemajú názov a používajú sa (vyvolávajú) z názvu (vlastnosti) priradeného definíciou objektu.
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”);
}
}
|
V predchádzajúcom príklade už existuje metóda „view_temperature“, ktorá zobrazuje hodnotu vlastnosti „current_temperature“ prostredníctvom konzoly. Nie je to veľmi užitočné, ale poskytuje úplnejšiu predstavu o tom, aká je definícia objektu JavaScript.
Na prístup k metódam objektu (funkciám) k jeho vlastnostiam použite this
, ako v predchádzajúcom príklade na riadku 11, pri použití vlastnosti „current_temperature“.
Získajte prístup k modelu objektu dokumentu (DOM) pomocou JavaScriptu
z JavaScript Máte prístup k obsahu webovej stránky, na ktorej beží, ako aj k niektorým aspektom prehliadača, ktorý túto stránku zobrazuje, aj keď nie k systémovým prostriedkom. Štruktúra údajov, ktorá podporuje vlastnosti a metódy, z ktorých sa pristupuje JavaScript časť objektu okna, konkrétne obsah objektu (dokument HTML) zodpovedá objektu document
. Aj keď sa to niekedy používa kvôli prehľadnosti, nie je potrebné predchádzať okno k metódam alebo vlastnostiam, aby sa na ne odkazovalo, stačí použiť napr. document
, nie je potrebné písať názov koreňového objektu ako v window.document
, pokiaľ sa odkazuje na aktuálne okno.
Najpoužívanejšia forma nájsť objekt v dokumente HTML Je to prostredníctvom metódy getElementById()
, ktorému sa ako argument odovzdá id, ktoré bolo uvedené pri vytváraní kódu HTML. Z toho, čo bolo vysvetlené v predchádzajúcich častiach, je ľahké predpokladať, že máte prístup aj ku komponentom vo vnútri objektu document
pomocou bodkovej syntaxe (document.componente
) alebo v zátvorkách s použitím oboch mien (document["componente"]
), najužitočnejšie, ako je číselný index, ťažko použiteľný a nepraktický pri prístupe k obsahu ručne zostavenej webovej stránky.
s JavaScript môžete získať prvok, ktorý obsahuje iný prvok (prvok alebo nadradený uzol) poradenstvo vo vašej nehnuteľnosti parentNode
alebo váš majetok parentElement
, rozdiel je v tom, že nadradený prvok (parentElement
) posledného prvku reťazca DOM Je nulová (null
) a nadradený uzol (parentNode
) je samotný dokument (document
).
na upraviť obsah prvku HTML, napríklad štítku <div>
, Dá sa použiť innerHTML
a ak chcete zmeniť jeho vlastnosti, môžete mu priradiť inú triedu className
alebo individuálne meniť jeho vlastnosti style
. Kontrola štýlu zobrazeného prvkom na webovej stránke nie je nevyhnutne užitočná style
pretože môže závisieť od viacerých faktorov alebo jednoducho neboli explicitne špecifikované. Na kontrolu štýlu prvku, ktorý sa nakoniec zobrazí na webovej stránke, sa používa metóda getComputedStyle.
K prvku dokumentu HTML Môže byť k nemu priradených niekoľko tried, ktoré určujú jeho vzhľad a správanie spravovať zoznam tried objektu z JavaScript môžete sa uchýliť classList
ktorý ponúka metódy add
na pridanie novej triedy do zoznamu, remove
odstrániť to, toggle
nahradiť ho alebo nahliadnuť do obsahu zoznamu tried prvku s item
a contains
, ktorý vráti triedu, ktorá zaberá určitú pozíciu v zozname, a hodnotu true
o false
či je alebo nie je určitá trieda na zozname.
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”)
}
|
V predchádzajúcom príklade sa nachádza s getElementById
objekt, s ktorým chcete manipulovať (prvok <div>
pre jeho id
), pred zmenou vzhľadu sa obsah vymaže priradením s innerHTML
prázdny textový reťazec, je mu priradená nová trieda s className
a jeho štýl je upravený pomocou style
v závislosti od hodnoty obsahu (teploty), prípadne zmena farby prostredníctvom vlastnosti color
. Akonáhle je aspekt stanovený, hodnota sa zapíše pomocou znova innerHTML
.
V druhej časti vyššie uvedeného príkladu (riadky 9 až 19) sa pristupuje k prvku kódu HTML pomocou syntaxe document[]
a majetok id
prvku zmeniť jeho zoznam tried pomocou metódy classList.remove()
a s metódouclassList.add()
, na základe výsledku niekoľkých dotazov, ktoré sa vykonávajú v podmienených vykonaniach, ktoré porovnávajú pomocou classList.contains()
.
Kedy to bude odkazovať na prvok HTML niekoľko krát v celom kóde JavaScript, je to málo efektívnejšie ho priradiť k premennej alebo namiesto názvu použite jeho index, pretože inak by ste použili metódu, ktorú by ste použili JavaScript získať ho zakaždým by vyžadovalo hľadanie jeho názvu, čo by zabralo o niečo viac času, ako keby sa pristupovalo k premennej.
na pridať do dokumentu nové objekty HTML, môžu byť vytvorené najskôr metódou createElement
de document
a neskôr ich začleniť do zvyšku prvkov v bode stromu, ktorý je potrebný appendChild
. Na vytvorenie objektu XML, ako predmety SVG ktoré používame na kreslenie grafu senzorov internetu vecí, môžete použiť createElementNS
(NS pre menný priestor). Ako je vysvetlené, keď hovoríme o formáte SVG, menný priestor, ktorý mu zodpovedá (pre aktuálnu verziu), je http://www.w3.org/2000/svg
, ktorý by mal byť odovzdaný createElementNS
ako argument spolu s typom prvku, svg
, v tomto prípade.
Una alternatíva k innerHTML
na pridanie textu ako obsahu do prvku dokumentu HTML je metóda createTextNode()
objektu document
. S touto alternatívou môžete vytvoriť nový text (ku ktorému sa neskôr pristupuje, ak je priradená k premennej), ktorá je začlenená do stromu objektov s metódou appendChild()
, ako alternatíva k appendChild()
, ktorý pridá nový obsah na koniec toho, čo už existuje v uzle, do ktorého je pridaný, môžete použiť metóda insertBefore()
, ktorý pridá nový objekt pred existujúci objekt. Opotrebenie insertBefore()
namiesto appendChild()
poskytuje spôsob, ktorý slúži napr triediť nové objekty pred existujúcimi keď sa prvok musí nachádzať pred iným (ako v zozname) alebo zakrývať alebo byť zakrytý v grafickej štruktúre, v ktorej sú prvky bližšie k poprediu alebo pozadiu.
Reagujte na udalosti pomocou JavaScriptu
Keď spôsob použite webovú stránku ako kontajner pre grafy senzorov pripojených k internetu vecí bola použitá onload
V označení <body>
aby ste mohli začať kresliť graf. Táto vlastnosť spojená s objektmi kódu HTML, odkazuje na Udalosti JavaScript. Ako už bolo vysvetlené, po načítaní stránky vykoná funkciu. Hoci to bolo spojené s kódom HTML aby to bolo viac na pamäti, mohlo to byť napísané v kóde JavaScript ako body.onload=dibujar;
bytia dibujar
názov funkcie, ktorá sa má spustiť pri načítaní webovej stránky.
V najnovších verziách JavaScript udalosti môžu byť spojené s funkciami pomocou addEventListener
s formátom objeto.addEventListener(evento,función);
alebo pomocou syntaxe objeto.evento=función;
ktorý funguje aj v starších implementáciách. Ak chcete zrušiť prepojenie funkcie spojenej s udalosťou, musíte removeEventListener
ktorý má rovnaký formát ako addEventListener
.
JavaScript Je schopný reagovať na množstvo udalostí, ktoré sa môžu vyskytnúť na webovej stránke. Dokáže napríklad rozpoznať kliknutie na prvok HTML s onmousedown
, alebo po kliknutí na onclick
, keď sa stlačí kláves s onkeydown
pomocou posuvnej lišty onscroll
. Pre náš účel nám to stačí zistiť načítanie stránky pomocou onload
a jeho veľkosť pomocou onresize
. Tieto udalosti spojíme s predmetmi body
y window
del DOM resp. Prvý môže byť priradený v kóde HTML, ako je vidieť, a druhý v kóde JavaScript vnútri funkcie volanej prvým a s formátom window.onresize=redimensionar;
bytia redimensionar
funkcia, ktorá sa zavolá pri každej zmene veľkosti okna.
Spustite po určitom časovom intervale
JavaScript má na to dva zdroje odložená exekúcia: setTimeout
, ktorý vykoná funkciu po časovom intervale a setInterval
ktorý vykoná funkciu v každom určitom časovom intervale. Obe metódy vyžadujú ako parametre (1) vyvolanú funkciu a (2) časový interval vyjadrený v milisekundách. Ak chcete zastaviť ich činnosť, môžete výsledok vrátený týmito funkciami priradiť premenným a odovzdať ich ako argument clearTimeout
ho clearInterval
keď ich nechcete znova vyvolať (alebo keď nechcete, aby boli spustené prvýkrát) setTimeout
o setInterval
resp.
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
}
|
V predchádzajúcom príklade je uvedený spôsob alert
ktorá slúži na zobrazenie výstražného znamenia. Hoci bol v minulosti hojne využívaný, v súčasnosti je v kódexe takmer zakázaný JavaScript kvôli tomu, aké agresívne (dotieravé) je prekryť webovú stránku dialógovým oknom.
V programe napísanom pre a mikrokontrolér z malej série (ako je tá na tanieri). Arduino Uno) je bežné používať globálne premenné, ako v predchádzajúcom príklade v JavaScript, pretože kód je stručný a nie je príliš mätúci, pretože funkcie sú mnohokrát implementované ad hoc a pretože použitie globálnych premenných umožňuje predpovedať využitie pamäte veľmi jednoduchým a intuitívnym spôsobom, čo je rozhodujúce v systémoch s malým množstvom zdrojov. namiesto toho en JavaScript Je bežné znížiť používanie globálnych premenných na minimum. pretože nemusí spěchať s využitím pamäte, pretože beží normálne na a CPU so zdrojmi oveľa lepšími ako zdroje a MCU, pretože je pravdepodobné, že koexistuje s množstvom kódu tretích strán, s ktorým musí pracovať bez zasahovania, a keďže ide o otvorený systém, nemožno predpovedať budúci kontext vykonávania (program mikrokontrolér small úplne určuje svoju činnosť bez pridávania ďalšieho kódu, keď je v prevádzke) a pretože rozmery aplikácií by mohli sťažiť čítanie, ak kód nezapuzdruje svoju činnosť, takže metódy sú čo najviac samostatné.
Matematické operácie s objektom JavaScript Math
V objekte sú zoskupené matematické operácie zložitejších matematických výpočtov Math
. Tento objekt sa používa priamo, nie je potrebné ho inštanciovať, aby sa použili metódy alebo vlastnosti (konštanty), ktoré obsahuje.
Math.abs(n)
Absolútna hodnota parametra nMath.acos(n)
Arkosínus parametra n (výsledok v radiánoch)Math.asin(n)
Arkásína parametra n (výsledok v radiánoch)Math.atan(n)
Arktangens parametra n (výsledok v radiánoch)Math.atan2(n,m)
Arktangens n/m (výsledok v radiánoch)Math.ceil(n)
Zaokrúhlite parameter na najbližšie celé číslo nahorMath.cos(α)
Kosínus parametra α (α v radiánoch)Math.E
číslo e (≃2.718281828459045)Math.exp(n)
e zvýšené na parameter n: enMath.floor(n)
Zaokrúhlite parameter n na najbližšie celé číslo nadolMath.log(n)
Prirodzený logaritmus (základ e) parametra nMath.LN2
Prirodzený logaritmus (základ e) z 2 (≃0.6931471805599453)Math.LN10
Prirodzený logaritmus (základ e) z 10 (≃2.302585092994046)Math.LOG2E
2. základ logaritmus e (≃1.4426950408889634)Math.LOG10E
10. základ logaritmus e (≃0.4342944819032518)Math.max(a,b,c,…)
Najväčšia hodnota zo zoznamu odovzdaných parametrovMath.min(a,b,c,…)
Najmenšia hodnota zo zoznamu odovzdaných parametrovMath.PI
Číslo π (≃3.141592653589793)Math.pow(n,m)
Prvý parameter n zvýšený na druhý parameter m: nmMath.random()
(Takmer) náhodné číslo medzi 0.0 a 1.0Math.round(n)
Zaokrúhlite parameter n na najbližšie celé čísloMath.sin(α)
Sínus parametra α (α v radiánoch)Math.sqrt(n)
Druhá odmocnina parametra nMath.SQRT1_2
Druhá odmocnina z 1/2 (≃0.7071067811865476)Math.SQRT2
Druhá odmocnina z 2 (≃1.4142135623730951)Math.tan(α)
Tangent parametra α (α v radiánoch)
Načítajte dáta zo servera pomocou AJAX
Metóda nakreslenia informácií uložených v IoT pozostáva z občasného načítania údajov zo servera a prekreslenia grafu, ktorým sú znázornené. Na čítanie údajov zo servera sa používa technológia AJAX (Asynchrónny JavaScript a XML) cez objekt XMLHttpRequest
de JavaScript. Vykreslenie dátového grafu sa vykonáva opätovným použitím objektu SVG ktorý je už v kóde HTML a ktorý obsahuje graf, ktorého súradnice sú upravené tak, aby zodpovedali novým načítaným údajom.
V príklade tohto návrhu sa okrem aktualizácie výkresu aktualizuje aj text na webovej stránke, ktorý zobrazuje dátum a hodnotu posledných nameraných údajov pre každý graf.
Na strane servera je databáza, ktorá obsahuje informácie že senzory pripojené k internetu vecí monitorovali. Táto databáza je načítaná požiadavkou na objekt XMLHttpRequest
odpovedanie informáciou zakódovanou v Formát JSON, hoci názov použitej metódy naznačuje príbuznosť s formátom XML.
V prvom návode na polaridad.es na IoT dátové úložisko Môžete vidieť príklad infraštruktúry na správu informácií poskytovaných zariadeniami pripojenými k internetu vecí zo strany servera. V tejto sérii článkov sa ako zdroj používa server apache z ktorého môžete použiť programovací jazyk PHP na prístup k databáze MySQL o mariadb. Na serveroch používaných na podporu internetu vecí je veľmi bežné nájsť databázy MongoDB (NoSQL) a programovací jazyk JavaScript na Node.js ako softvérová infraštruktúra.
Ďalšia funkcia je zodpovedná za vyžiadanie najnovších údajov z jedného zo senzorov zo servera. Pri volaní funkcie sa objekt používa ako argument JavaScript ktorý podporuje vykreslené údaje. Ak ten istý graf predstavuje niekoľko hodnôt, napríklad na vizuálne vyhľadanie korelácie, môže byť server požiadaný, aby vrátil niekoľko súčasne, čo je optimálnejšia metóda vzhľadom na spôsob fungovania servera. HTTP protokol.
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);
}
|
V treťom riadku predchádzajúceho príkladu je pripravený dotaz, ktorý sa odošle na server, v ktorom sa odovzdá argument „zóna“, ktorého hodnotou bude názov alebo kód monitorovaného miesta, pretože informácie o v rovnakej databáze môžu koexistovať rôzne senzory (napríklad teplomery, ktoré merajú teplotu v rôznych miestnostiach). Očakáva sa, že parameter odovzdaný predchádzajúcej funkcii, objekt s údajmi grafu, bude obsahovať vlastnosť s názvom miestnosti ("name_suffix").
Medzi riadkami 7 a 14 predchádzajúceho kódu, objekt XMLHttpRequest
ktorá je uložená v premennej „ajax“. Pred výberom spôsobu vytvorenia objektu musíte hľadať window
ak XMLHttpRequest
nebolo k dispozícii (niečo, čo sa stalo v starých verziách prieskumníka od spoločnosti Microsoft a hoci je to ďaleko pozadu, slúži to ako príklad alternatív na vytvorenie objektu pomocou (natívnejšej) syntaxe) Object.create
o new
, podobne ako v iných objektovo orientovaných jazykoch.
Aby bolo možné okamžite spravovať odpoveď, kód, ktorý ju spracuje, je pripravený v riadkoch 15 až 26 pred odoslaním požiadavky na server.
Spôsob vykonať dotaz HTTP na server pozostáva z otvorte spojenie s open
s uvedením typu a stránky (voliteľne používateľské meno a heslo), pripravte hlavičky protokolu s setRequestHeader
y odošlite žiadosť s send
. Hlavička HTTP Content-length
budete potrebovať poznať dĺžku dotazu (počet znakov), ktorá sa vypočíta pomocou length
.
Keď žiadosť AJAX je pripravený, vykoná sa funkcia spojená s udalosťou onreadystatechange
. Namiesto priradenia funkcie je v predchádzajúcom príklade za behu definovaná anonymná funkcia, ktorá bude riadiť príjem dát prichádzajúcich zo servera. V prvom rade sa na riadku 18 overí, že stav požiadavky je „vybavená“, čo zodpovedá hodnote 4
majetku readyState
, že stav je „OK“. HTTP protokol (kód 200
), ktoré možno získať z nehnuteľnosti status
a že údaje, ktoré prišli, sú Formát JSON, poradenstvo nehnuteľnosti responseType
.
Po overení, že stav odpovede je podľa očakávania, v riadku 20 predchádzajúceho príkladu vytvorí objekt s výsledkom, skonvertuje text JSON. Odpoveď poskytuje dátum, ktorý sa má vrátiť, čo nám umožňuje zistiť, či výsledok, ktorý server odošle, už bol predtým znázornený v grafe, čo je overené v riadku 21. Ak sú údaje nové, v riadku 23 Funkcia, ktorá je zodpovedný za prekreslenie grafu s novou informáciou tzv.
Myšlienkou pri navrhovaní tejto metódy čítania je, že údaje sa budú veľmi často obnovovať. Ak prezentované informácie zodpovedajú dlhodobému horizontu (ako sú teploty dňa alebo týždňa), môže sa implementovať počiatočná požiadavka, ktorá zhromaždí všetky dostupné údaje a potom jedna, podobná tej v príklade, ktorá ich aktualizuje v priebehu dobový korešpondent.
Generujte náhodné údaje na testovanie
Keď bude všetka infraštruktúra servera a klienta pripravená, funkcia podobná tej v predchádzajúcej časti bude mať na starosti čítanie údajov a kreslenie grafu pomocou nich, ale Vo fáze testovania môže byť praktickejšie použiť náhodné čísla v kontrolovanom rozsahu aby ste zistili, či je zapísaný kód správny. Nasledujúca funkcia môže slúžiť ako príklad na získanie údajov pri zostavovaní finálnej aplikácie.
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);
}
|
Namiesto čítania informácií z databázy ich vyššie uvedený príklad generuje náhodne a odovzdáva ich funkcii, ktorá má na starosti kreslenie grafu. Vynájdené dáta sú vektorom tvoreným dátumom vyjadreným ako hodnota v milisekundách, momentom zaznamenania informácie senzora a monitorovanými dátami, ktoré sú medzi maximálnou hodnotou a minimálnou hodnotou.
V tomto príklade môže byť generovanie dátumu oneskorené až o jednu sekundu (1000 milisekúnd) vzhľadom na dátum v čase vynálezu. Ako Math.random()
vygeneruje číslo medzi 0.0 a 1.0, vynásobením číslom 1000 vznikne číslo medzi 0 a 1000, ktoré sa potom prevedie na celé číslo. Rovnakým spôsobom sa hodnota získa vynásobením náhodného čísla rozsahom (maximum mínus minimum) a pripočítaním minima.
Nakreslite graf senzorov internetu vecí pomocou grafu SVG
Keďže sme videli, ako môžeme získať hodnoty, ktoré chceme reprezentovať (v príklade teplota) a ich časové umiestnenie, ktoré možno vyjadriť spolu vo forme súradníc, nižšie uvedený príklad ukazuje funkciu na kreslenie cesty. ktorá spája tieto body a voliteľne farebnú oblasť ohraničenú touto čiarou v hornej časti. Výsledok by bol ako na nasledujúcom obrázku.
Vodorovná os (X) grafu predstavuje čas a zvislá os (Y) hodnoty, ktoré senzory pripojené k IoT monitorovali. Horizontálny interval je niekoľko sekúnd, pretože v tomto návrhu sa graf aktualizuje veľmi často (napríklad každú sekundu), aby poskytoval takmer v reálnom čase informácie o stave senzorov.
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
}
|
V predchádzajúcom kóde sú dva zaujímavé aspekty, po prvé výpočet, ktorý to umožňuje prispôsobiť rozsah hodnôt, ktoré sú zastúpené a po druhé výstavba nehnuteľností d
ktorý označuje súradnice bodov na rozložení (path
).
Aby sa prispôsobil rozsah reprezentovaných hodnôt, presunú sa z minima a upravia sa tak, aby viditeľná veľkosť zodpovedala veľkosti grafu. V prípade času sa posun získa odpočítaním rozsahu, ktorý chcete zobraziť, od najdlhšieho času (dátum a čas najbližšie k aktuálnemu) (v príklade 20 sekúnd). Posun hodnôt teploty je v dolnom rozsahu (jeden stupeň) mínus najnižšia hodnota, takže údaje uvedené nižšie sa najviac podobajú najnižšej povolenej hodnote, ale ponechávajú rezervu, ktorá nám umožňuje oceniť, čo prešlo.
Koeficient, ktorý násobí časové hodnoty na získanie horizontálnych súradníc grafu, sa získa vydelením celkovej šírky grafu (100 jednotiek v príklade) reprezentovaným časovým rozsahom (v príklade 20 sekúnd). Na získanie koeficientu so skalárnymi hodnotami teploty je potrebné pamätať na to, že reprezentovaný rozsah siaha od okraja pod minimálnu hodnotu k okraju nad maximom, v oboch prípadoch o jeden stupeň. Týmto spôsobom je koeficient vertikálnej mierky výsledkom vydelenia výšky grafu (v príklade 100 jednotiek) maximálnou hodnotou mínus minimum plus horný a dolný okraj. Keďže tieto hodnoty sa môžu úplne vyvinúť pri negatívnych teplotách, používame Math.abs()
použiť absolútnu hodnotu rozdielu.
Vlastníctvo d
objektu path
Vytvára sa zreťazením súradníc bodov v texte. Každému páru súradníc predchádza kód SVG L
, ktorý nakreslí čiaru z aktuálnej polohy na absolútnu hodnotu, ktorá je označená súradnicami. Hodnoty X a Y sú oddelené čiarkami a každá operácia SVG je oddelený medzerou od nasledujúceho.
Ak chcete spustiť rozloženie, použite kód M
(presunúť na absolútnu súradnicu). V prípade uzavretého a vyplneného grafu začínate vpravo dole, v prípade otvoreného grafu, ktorý vykresľuje dátový profil, začínate poslednou zobrazenou hodnotou (najnovšou). Na dokončenie uzavretého rozloženia sa použije kód Z
pridaním ako posledného bodu bod, ktorý má rovnakú hodnotu súradnice X ako posledný bod čiary a ako súradnicu Y najmenšiu znázornenú hodnotu.
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
);
}
|
V tomto príklade funkcia dibujar_grafico()
, čo je volanie pri načítaní stránky, získa počiatočné hodnoty na testovanie (nie poslednú hodnotu v reálnom čase) a pripraví rozsah, v ktorom sa budú údaje vykresľovať: 20 sekúnd (20000 15 ms) horizontálne a 5 °C v vertikálne od -10°C do +XNUMX°C s horným a dolným okrajom o jeden stupeň. Uskutočnite dva hovory actualizar_grafico()
, v prvom prechode true
ako argument, ktorý naznačuje, že graf by mal byť zatvorený, aby predstavoval vyplnenú oblasť, a pri druhom volaní prejde false
nakresliť čiaru. V každom prípade objekt path
upravený je ten, ktorý má zodpovedajúci vzhľad, s výplňou a bez okraja v prvom prípade a s určitou hrúbkou čiary a bez výplne v druhom prípade.
Funkcia actualizar_grafico()
pracovať na predmete SVG ktorý používa nasledujúci kód ako kontajner HTML. Objekt SVG obsahuje dve cesty, jednu na kreslenie čiary a druhú na kreslenie vyplnenej oblasti. Pri načítavaní webovej stránky z prvku <body>
predchádzajúca funkcia sa zavolá automaticky, dibujar_grafico()
vďaka akcii 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>
|
Na riadku 10 kódu HTML vyššie je v štýle stanovená šírka (ako príklad) 820 px a výška 150 px (niečo, čo vo finálnej verzii bude vhodné urobiť s triedou a dokumentom CSS). Zdá sa zvláštne, že riadky 13 a 14 definujú veľkosť objektu SVG ako 100% šírka a výška (čo najlepšie zodpovedá rozmerom okna, 100×100). Ako už bolo spomenuté, dôvodom na to je vždy pracovať so známymi rozmermi a prispôsobiť im zobrazené hodnoty. Ďalšími alternatívami by bolo zakaždým vypočítať priestor grafu a potom znova upraviť hodnoty alebo vynútiť pevné rozmery grafu, ktoré bude musieť dokument dodržiavať.
Rozhodol som sa pre graf, ktorého rozmery sa menia podľa kódu HTML, je potrebné zahrnúť nehnuteľnosť vector-effect
s hodnotou non-scaling-stroke
aby sa predišlo deformácii hrúbok čiar, keď graf nezachová zvolené pomery 1:1 na webovej stránke, na ktorej je zobrazený, ako je to v predchádzajúcom návrhu.
Ak chcete „orezať“ graf a zobraziť iba oblasť, ktorú si vyberiete, použite viewBox
. V tomto prípade sme sa rozhodli vidieť časť grafu, ktorá začína na 0,0 (ľavý horný roh) a meria 100x100 dole a vpravo. Časť výkresu umiestnená v súradniciach so zápornými hodnotami alebo väčšími ako 100 sa na webovej stránke nezobrazí, aj keď v objekte existujú SVG
Pridajte nové prvky do výkresu SVG
V predchádzajúcom príklade funkcia actualizar_grafico()
použite rozloženie SVG na ktoré sa mení vlastníctvo d
, čo je to, čo vyjadruje súradnicový reťazec. Alternatívou by bolo vytvorenie celého objektu pri každom prekreslení. Výhodou prvej možnosti je, že grafický vzhľad (napríklad hrúbka alebo farba) je definovaný v kóde HTML, obmedzením je, že objekty musia byť vytvorené predtým.
Ak chcete vytvoriť objekty SVG, použite createElementNS()
, ktorý umožňuje zahrnúť menný priestor. V nižšie uvedenom príklade sa vytvorí nový textový objekt (text
) a je spojená s prvkom SVG ktorý už v kóde existuje HTML webovej stránky. Po vytvorení nového prvku sa priradia jeho vlastnosti setAttribute()
a pridáva sa k SVG s 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]);
|
Upravte pomer prvkov kresby
Ak ste vyskúšali označenie pomocou funkcie v príklade v predchádzajúcej časti, uvidíte, že text sa javí zdeformovaný, keď proporcia objektu na webovej stránke (width
y height
Kódu HTML) sa nerovná oblasti zastúpenej (viewBox
). Na prispôsobenie proporcie je potrebné poznať rozmery objektu SVG pri ktorých môžete konzultovať štýl objektu alebo kontajnera HTML, ak objekt SVG previesť túto nehnuteľnosť. Priradenie vlastníctva transform
na objekty SVG ktoré závisia od proporcie, možno deformáciu korigovať použitím operácie škálovania scale()
v ktorom je koeficient v X odlišný od koeficientu v Y.
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 umožňuje zoskupiť niekoľko objektov do nového kompozitného prvku, ktorý tiež podporuje vlastnostiako jednoduché predmety. Ak chcete použiť rovnakú transformáciu na sériu objektov naraz namiesto každého objektu samostatne, môžete ich zoskupiť podľa tohto zdroja a použiť jednu vlastnosť transform
všetkým z nich.
Ako bolo vysvetlené, keď sa hovorí o formát SVG, prvky skupiny sú uzavreté v rámci štítkov <g>
y </g>
. Pridať z JavaScript prvky do skupiny SVG sa používa, ako je vidieť v predchádzajúcom príklade, appendChild()
po definovaní nového objektu.
Na určenie pôvodu pri aplikácii transformácií možno vlastnosť použiť na objekty SVG transform-origin
, ktorej hodnota sú súradnice X a Y bodu, z ktorého transformácia začína. Ak nie je výslovne uvedená hodnota pre počiatok transformácie (vo webovom prehliadači), použije sa stred súradníc. Bohužiaľ, v čase písania tohto článku nie je špecifikovanie správania transformácií pomocou iného než predvoleného zdroja homogénne medzi prehliadačmi a malo by sa používať opatrne.
Spolu s transformáciou stupnice s scale
Existujú aj iné, napríklad rotácia s rotation
a pohyb s translate
, ktoré ponúkajú a alternatíva k znázorneniu v grafe: namiesto získavania nových súradníc ich môžete reprezentovať v ich vlastnom priestore a transformovať graf tak, aby zodpovedal formátu, v ktorom ich chcete znázorniť.
Pridajte odkazy do grafu
Teraz, keď je hlavná časť grafu vyriešená vykreslením hodnôt s profilom a vyplnenou oblasťou, môže byť doplnená o odkazy, ktoré pomáhajú pri jeho čítaní. Ako príklad začnime nakreslením niektorých horizontálnych odkazov (čiar), ktoré označujú maximálne a minimálne prijateľné hodnoty, ako aj požadovanú hodnotu. Ako bolo vysvetlené, môžete sa rozhodnúť pridať objekty do SVG priamo z JavaScript alebo ich zahrňte ručne do kódu HTML a neskôr ich upraviť pomocou 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();
|
Zdá sa logické označiť tieto horizontálne odkazy textom, ktorý objasňuje hodnotu, ktorú predstavujú. Na zvýraznenie textu môžete použiť obdĺžniky, ktoré budú vyčnievať z pozadia a grafiky. Keďže na texty bude potrebné použiť transformáciu mierky, aby sa deformácia kompenzovala, všetky môžu byť zoskupené do objektu, na ktorý sa mierka aplikuje; Hlavnou výhodou tohto spôsobu je možnosť ich úpravy v jednej operácii, ak sa zmení veľkosť kontajnera grafu (okna prehliadača) a zmení sa pomer, ktorý mierka koriguje.
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();
|
Vo vyššie uvedenom príklade kódu je niekoľko zaujímavých aspektov. Najprv pripomeňte, že konštanty (globálne premenné) boli použité na to, aby bol príklad čitateľnejší pre používateľov prichádzajúcich z programovania. mikrokontroléry en C v C + +. Ako sa ukáže neskôr, optimálny spôsob, ako to naprogramovať JavaScript Išlo by o použitie objektov, ktoré by obsahovali tieto hodnoty a metódy, ktoré by spravovali referencie v tomto príklade alebo grafe vo všeobecnosti v produkčnom systéme.
Na druhej strane, s pokrokom v tom, čo by bol všeobecnejší kód, boli vyvinuté samostatné funkcie, ktoré vypočítavajú rôzne koeficienty, ktoré korigujú podiel grafu na úpravu textu. proporcion_grafico()
, stupnica hodnôt v závislosti od ich rozsahu escala()
a korekčný faktor pre merania, ktoré sú známe v absolútnej hodnote, ako sú merania v referenciách medida_grafico()
.
Čítanie tohto kódu by malo pomôcť objasniť kontext, v ktorom funguje takáto aplikácia, ktorá kreslí grafiku v reálnom čase a musí byť flexibilná, aby mohla byť prezentovaná v rôznych grafických kontextoch (aspoň rôznych veľkostiach a proporciách). V prvom rade je potrebné vygenerovať objekty SVG, buď "ručne" v kóde HTML, buď prostredníctvom kódu JavaScript av každom prípade je potrebné následne získať odkazy na tieto objekty, aby sa s nimi dalo manipulovať JavaScript aby bolo možné kresliť nové grafy a prispôsobiť zobrazenie už nakresleného grafu zmene média, v ktorom je prezentovaný.
Ďalším odkazom, ktorý môže pomôcť ľahko interpretovať graf, sú body, ktoré predstavujú konkrétne hodnoty (uzly čiary). V tomto príklade, v ktorom predstavujeme jednu veličinu, nie je výber symbolu kritický, ale ak sa prekrýva niekoľko rôznych hodnôt, aby sa hľadala korelácia, je zaujímavé rozlišovať okrem použitia iných zdrojov, ako je farba , kreslením rôznych symbolov. Grafika použitá pre uzol čiary musí byť upravená vo veľkosti a proporciách, ako sa to deje napríklad pri textoch, aby jej rozmery boli absolútne a aby sa zachovali jej proporcie, aj keď sa zmenia proporcie rámčeka, ktorý obsahuje.
V predchádzajúcom príklade sme už videli, ako vypočítať rôzne koeficienty na zmenu mierky a opravu proporcie výkresu; Pokiaľ ide o to, ako implementovať správu symbolov uzlov alebo vrcholov grafu, možným riešením môže byť ukladanie objektov SVG do vektora a upravte jeho polohu, keď sa graf aktualizuje načítaním novej hodnoty alebo keď sa prekreslí zmenou veľkosti kontajnera. V prvom prípade by sa musela upraviť jeho poloha a v druhom pomere k nehnuteľnosti transform
a hodnotu scale
. Nasledujúci kód je modifikáciou funkcie actualizar_grafico()
zahrnúť premiestnenie symbolov vrcholov grafu.
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);
}
}
|
Úpravy vykonané vo funkcii actualizar_grafico()
získať novú funkciu actualizar_grafico_puntos()
Sú to tie, ktoré sú zvýraznené v kóde predchádzajúceho príkladu. Najprv v riadku 5 vezmeme vektor objektov SVG ako parameter. Tento vektor bude obsahovať symboly, ktoré je potrebné premiestniť v nových uzloch grafu.
V riadkoch 39 a 40 sú priradené nové súradnice stredu, cx
y cy
na hodnoty, ktoré sú reprezentované. Ak symbol nebol založený na strede, pravdepodobne bude potrebné pridať posun cx
polovičná šírka a v cy
polovičnej výšky, aby ste ich premiestnili presne na uzol grafu.
V riadkoch 57 až 61 sa body, ktoré zodpovedajú súradniciam, ktoré nie sú nakreslené, pretože sú odrezané ľavým okrajom, premiestnia mimo graf. Súradnica z cy
na nulu a to z cx
na akékoľvek záporné číslo (väčšie ako samotný bod), aby sa pri prerezaní, ako je ľavá časť grafu, nezobrazilo oknom SVG.
Spravujte graf z objektu pomocou JavaScriptu
Všetky operácie, ktoré boli doteraz vysvetlené, je možné integrovať do objektu a spravovať graf štýlom, ktorý je viac typický pre nové verzie JavaScript. Táto alternatíva implementácie má ďalšiu výhodu v tom, že zjednodušuje začlenenie niekoľkých grafov rôznych hodnôt na rovnakú webovú stránku.
Pred diskusiou o implementácii si zopakujme najbežnejšie spôsoby vytvárania objektov pomocou JavaScript a niektoré zvláštnosti funkcií, ktoré ovplyvňujú návrh na kreslenie grafiky senzorov IoT.
Už bolo vysvetlené, že nový spôsob vytvárania objektov v JavaScript (k dispozícii od verzie 5 ECMAScript) pozostáva z používania Object.create
, ktorý by si mal zvyknúť používať namiesto „klasického“ new
, ktorý samozrejme stále funguje správne, hoci jeho účelom je skôr simulovať štýl jazykov pomocou objektov založených na triedach (JavaScript zakladá tvorbu objektov na prototypoch) ako fungujúcu alternatívu.
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();
}
|
Predchádzajúci kód vám umožňuje zapamätať si rozdiely medzi vytváraním objektov pomocou Object.create
alebo s new
. Slúži tiež na zdôraznenie toho, že pri funkcii, s ktorou je objekt vytvorený new
môže byť kdekoľvek v kóde, objekt už musí existovať predtým, ako sa s ním môže vytvoriť inštancia Object.create
(Objekt ES5_Object nie je funkcia).
V riadkoch 3 a 4 nastavte predvolenú hodnotu pre vlastnosti vo funkcii, pomocou ktorej sa vytvára objekt new
, každej vlastnosti je priradená hodnota zodpovedajúceho argumentu alebo (||
), ak neboli odovzdané žiadne argumenty, teda ak nie sú definované (undefined
), keďže sa táto okolnosť hodnotí ako false
, je priradená predvolená hodnota.
Kontext, v ktorom sa funkcia vykonáva JavaScript vyvoláva dva problémy, ktoré je dôležité mať na pamäti a ktoré môžu byť tiež mätúce pri používaní tohto programovacieho jazyka po spolupráci s inými, ako napr. C o C + +, v našom prípade. Kontext zahŕňa premenné definované v rámci funkcie (a tie globálne), čo, mimochodom, vyvoláva zaujímavý koncept, „uzávery“, ktoré vytvárajú celý programovací štýl v JavaScript. To znamená, že sa to dalo očakávať this
, ktorý odkazuje na objekt, keď sa používa v rámci kódu, ktorý ho definuje, kontext vykonávania, v ktorom bol definovaný, sa zachová, ale ten, ktorý používa, je kontext, z ktorého sa funkcia volá. Toto správanie je vo väčšine prípadov transparentné, existujú však dve okolnosti, za ktorých môže byť mätúce: funkcia definovaná v inej funkcii a metóda volaná z udalosti objektu. 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
*/
|
Pri vykonávaní predchádzajúceho kódu sa v konzole zobrazí komentovaný text na konci. Dva označené riadky odrážajú správanie, ktoré môže byť mätúce: kontext vykonávania funkcie probar_dentro()
nie probar()
, ako by sa dalo očakávať, ale window
, ktorý zobrazuje globálne premenné a nie vlastnosti s rovnakým názvom. Ak si toto správanie neželáte, jednoducho vytvorte premennú vo funkcii najvyššej úrovne a priraďte ju this
, ako v nasledujúcom kóde.
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
*/
|
Na riadenie kontextu vykonávania, keď sa metóda volá z udalosti window
, napríklad zmenou veľkosti okna prehliadača, ďalšou zvláštnosťou JavaScript: možnosť programovania „tovární na funkcie“, teda funkcií, ktoré generujú iné funkcie a vracajú ich s 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
|
Vo vyššie uvedenom príklade kódu je metóda llamar()
objektov Contexto
Nevykonáva prácu, ale vracia anonymnú funkciu, ktorá sa o to stará. Na overenie, či všetko funguje podľa očakávania, existuje globálna premenná s rovnakým názvom ako vlastnosť, ktorú funkcia zobrazuje v konzole; Ak je kontext správny, zobrazí sa hodnota vlastnosti a nie hodnota globálnej premennej.
JavaScript Skúste opraviť bodkočiarky, ktoré vynechávame na konci viet. To umožňuje uvoľnený štýl písania, ale je to dvojsečná zbraň, s ktorou sa musí zaobchádzať opatrne. Vo väčšine prípadov, aby ste sa vyhli nežiaducim účinkom, ktoré to vytvára vo výrazoch, ktoré zaberajú niekoľko riadkov, môžete použiť zátvorky alebo predpísať spôsob, akým JavaScript bude interpretovať kód; To je dôvod, prečo riadok 8 príkladu obsahuje function
vzadu return
, ak by som použil iný riadok, význam by bol veľmi odlišný. Podľa môjho názoru je najčitateľnejším riešením použitie prechodnej (postradateľnej) premennej ako v nasledujúcej verzii; Je zrejmé, že akonáhle je správanie pochopené, rozhodnutie zodpovedá programátorovi.
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);
|
V rovnakom zmysle ako vyhodnotenie výrazu ako funkcie, teda vrátenie funkcie a nie hodnoty, ktorú funkcia vráti; na riadku 21 posledného príkladu (bol na riadku 19 predchádzajúceho) sa zastaví clearInterval
funkcia volaná pomocou setInterval
. Aby mohol pôsobiť 30 sekúnd, zastavenie sa odloží s setTimeout
, ktorý zase potrebuje funkciu ako prvý argument; doručiť vykonanie ako parameter clearInterval
s premennou, ktorá obsahuje periodické volanie (a nie funkciu clearInterval
) je vytvorená anonymná funkcia v poslednom riadku.
Voľba medzi napísaním kódu integrujúcim definíciu funkcie, kompaktnejším (ako v riadku 21) alebo použitím pomocnej premennej, podľa môjho názoru, čitateľnejším (ako v riadkoch 19 a 20) sa len málo líši vo výkone a závisí viac štýlu a čitateľnosti pre údržbu.
Na otestovanie kódu, skôr ako budete mať dáta na serveri, môžete použiť generátor náhodných hodnôt v požadovanom rozsahu alebo pripraviť tabuľky s riadenými hodnotami, ktoré simulujú prevádzku za požadovaných podmienok. Nasledujúci príklad používa jednoduchý generátor údajov v celom rozsahu, preto sa javia trochu prehnane.
Ak chcete vyskúšať, môžete stiahnite si celý kód príkladu tvorený webovou stránkou napísanou v HTML, štýl CSS a kód JavaScript. Posledne menované je najrelevantnejšie, pretože ostatné komponenty majú len minimálnu podporu, sú veľmi zjednodušené a sú oveľa viac rozvinuté v článkoch v príslušných častiach.
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);
}
|
Pridať komentár