Az IoT-hez JavaScript segítségével csatlakoztatott érzékelők adatainak SVG-grafikáinak létrehozása és módosítása
A rajzról szóló cikksorozat utolsó részében grafikák a dolgok internetéhez csatlakoztatott érzékelők adataival, itt az ideje, hogy beszéljünk arról, hogyan lehet létrehozni vagy módosítani JavaScript rajzok formátumban SVG és néhány elem HTML amelyek tárolóként szolgálnak, vagy amelyek kiegészítő információkat jelenítenek meg a grafikához.
Az oktatóanyag célfelhasználóinak elektronikai és számítógépes programozási profilt kell alkotniuk. mikrovezérlők, lehet, hogy nem ismerik HTML, CSS o SVG; Emiatt az előző részekben rövid bemutatkozás készült a nyelvről vagy a megfelelő technológiáról. Ebben az utolsó részben a megközelítés egy kicsit más, hiszen az olvasók biztosan tudnak programozni, lehetséges, hogy a nyelv használatával C + + hogy, hogyan JavaScript, megosztja az alapvető szintaxist C és referenciaként használható arra, hogy kihagyjuk a legtöbb alapvető programozási koncepciót, és így a különbségekre és arra a konkrét felhasználásra összpontosítunk, amely érdekli a szenzorgrafikák létrehozása az IoT-ben.
A név utal az első különbségre: JavaScript Ez egy programozási nyelv forgatókönyv (kötőjel), és mint ilyen, az értelmezhető, nem kell lefordítani; az a kontextus, amelyben a forgatókönyv (például egy webböngésző) elolvassa, lefordítja és végrehajtja a megbízásokat. Hogy pontosak legyünk, a legtöbb esetben létezik a futásidejű fordítás (JIT), hanem a kódírási folyamathoz JavaScript Ez minket nem érint, egyszerűen megírjuk a kódot és működhet.
A név tartalmazza az első félreértést is: JavaScript a legcsekélyebb kapcsolata sincs vele Jáva. Kezdetben, amikor kidolgozták Netscape böngészőjéhez először Mocha, majd a kevésbé zavaró LiveScript nevet kapta. A böngészőkben való sikeres implementáció után, és azokon túllépve szabványosították a ECMAScript (To ECMA-262, 6-os verzió az írás idején), hogy semlegessé váljon az azt megvalósító böngészők tekintetében. Jelenleg is létezik szabvány ISO 5-es 2011-ös verziótól (ISO / IEC 16262: 2011 a cikk írásakor)
Változók, alapvető adattípusok és objektumok JavaScriptben
Ellentétben azzal, ami pl C + +, en JavaScript az adattípus nem szerepel a változó deklarálásakor és a változóhoz tartozó típus sem fix, lehetőség van más típusú érték hozzárendelésére a program végrehajtása során.
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
|
Az előző példában a "dolog" változót deklaráltuk (az adattípus megjelölése nélkül), majd más típusú adatokat rendelünk hozzá, és lekérdezzük typeof
az a típus JavaScript hogy ő tolmácsolta. A kód hibakereséséhez beírhatja a webböngésző Inspector konzoljába (ami nem befolyásolja a web megjelenítését) console.log()
.
Az adatok meghatározott típussá konvertálásához, különösen a szöveg numerikussá, olyan funkciókat használhat, mint pl parseInt()
o parseFloat()
amelyek rendre egész számokká vagy lebegőpontos számokká konvertálnak. Ezzel az ellenkező átalakítást is meg lehet tenni String()
, bár valószínűleg nem lesz rá szükség, mivel általában elegendő az automatikus átalakítás. Val vel parseFloat()
Például megkaphatja egy weboldal tulajdonság értékét, például egy objektum szélességét vagy magasságát, amely egységeket tartalmaz; Ily módon a kifejezés parseFloat("50px");
eredményként 50-et, egy numerikus értéket ad vissza.
En JavaScript nincs különbség kettős és szimpla idézőjel között; Az adattípus mindkét esetben az string
, és mindegyik tartalmazhatja a másikat anélkül, hogy szükség lenne escape kódokra.
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
|
Az előző példában látható, hogy egy változó, ha deklarálva van (létezik), de nem kapott értéket, meghatározatlan adattípust tartalmaz (undefined
). Egy hozzá nem rendelt objektumnak van értéke null
; Vagyis a tárgy létezik, de érték nélkül; a rá hivatkozó változónak nem lenne a typeof
undefined
de object
. Egy objektum lehet üres is, azaz nem nulla, de nem rendelkezik semmilyen tulajdonsággal.
hogy definiáljon egy objektumot JavaScript zárójelbe zárják ({
y }
) a tulajdonságokat vagy módszereket kettősponttal elválasztva (:
) tulajdonság neve tulajdonság értéke és vesszővel (,
) a különböző tulajdonságokat. Az objektum kifejezésének erről a módjáról további információkat találhat a cikkben JSON formátum.
Bár használhat olyan szintaxist, amely másként gondolkodhat, en JavaScript Nincsenek osztályok, csak prototípusokVagyis ahhoz, hogy egy objektum örökölje a tulajdonságokat és metódusokat, létrejön egy másik objektum (a prototípus), amelyet a többiek (a gyerekek) referenciaként használnak. A stílushoz legközelebb álló szintaxis JavaScript prototípust használni az Object.create
bár az is lehetséges (és néha hasznos is). new
mint más objektumorientált nyelvekben.
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));
|
hogy lekérdezi, ha az egyik objektum egy másik példánya, ha prototípusként használod, ha örökölöd a tulajdonságait, egyszóval használhatod instanceof
(alkalmazva new
) o isPrototypeOf
(alkalmazva Object.create
), amely igazra értékeli, ha az objektum használja a prototípust, és hamisra, ha nem.
Ha egy objektumot egy másik prototípus felhasználásával hoztak létre, vagyis ha egy objektumot példányosítottak, akkor új tulajdonságok hozzáadása vagy prototípus tulajdonságainak felülírása pont szintaxis használatával, mint itt gato.peso=2.5
.
La tömbök be JavaScript Eltérnek azoktól, amelyeket valószínűleg ismer C. Kezdetben hosszuk feltüntetése nélkül deklarálják őket, csak a nyitó és záró szögletes zárójelekkel ([
y ]
), az összetevők lehetnek heterogének (különböző adattípusok ugyanabban a tömbben), és új elemek hozzáadhatók korlátozás nélkül. A mátrixok JavaScript valójában olyan elemek listái (gyűjteményei), amelyekhez számmutatóval vagy névvel hivatkozva. Egy tömb egyidejűleg tartalmazhat numerikus indexeket és elemneveket, de gyakori, hogy objektumokat (tulajdonságokat) használnak a második típus kihasználására.
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
|
Amint az az előző példában látható, annak megtudásához, hogy egy változó megfelel-e egy tömb példányának (ez egy tömbobjektum), használhatja instanceof
, ahogyan azt már általános objektumoknál használták, vagy a legújabb verzióiban JavaScript igénybe veheti Array.isArray()
A tömb elemeinek eléréséhez használhatja az indexét (matriz[7]
) vagy a tulajdonság nevével, a névvel szögletes zárójelben (matriz["nombre"]
) vagy az objektumok szokásos pont szintaxisával (matriz.nombre
). Mivel a név egy szöveges karakterlánc, egy kifejezés, beleértve a változókat is, felhasználható az összeállításához. Tulajdonságokkal rendelkező tömbön való hurkoláshoz használhat egy ciklust a formátummal 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
*/
|
Célunk szempontjából érdekes kezelni a tárgy Date
, amellyel megjelenítheti és kezelheti a dátumot és az időt JavaScript. Az objektum adat nélkül is példányosítható, így az aktuális dátumot és időt veszi fel, vagy létre lehet hozni egy dátum értékként történő megadásával, akár ezredmásodpercben 1. január 1970-je óta (pl. Unix idő vagy POSIX idő de másodpercek helyett ezredmásodpercben fejezik ki) vagy külön év, hónap, nap, óra érték megadásával...
Az objektum egy teljes sorozatot tartalmaz módszerek a dátum és az idő lekérdezésére vagy beállítására:
-
now()
Az aktuális dátumot és időt adja vissza ezredmásodpercben 1. január 1970. óta -
getTime()
|setTime()
Lekéri vagy módosítja az időértéket ezredmásodpercben 1. január 1970. óta.valueOf()
, amely a legtöbb objektumban jelen lévő metódus, a megfelelő Date objektum értékét is megkapjuk, mint plgetTime()
a Unix idő vagy POSIX idő ms-ban kifejezve. -
getMilliseconds()
|setMilliseconds()
Az objektum tört ezredmásodperces részének lekérdezésére vagy beállítására szolgálDate
amelyen kivégzik. Ha megvizsgáljuk, a kapott érték 0 és 999 között van, de nagyobb értékek is hozzárendelhetők, amelyek felhalmozódnak a teljes dátumban és időben, így a többi get metódushoz hasonlóan az objektum értékének növelését szolgálja.Date
(vagy csökkentse, ha negatív értékeket használ). -
getSeconds()
|setSeconds()
Visszaadja vagy módosítja az objektum másodperceinek értékétDate
. -
getMinutes()
|setMinutes()
Az objektum perceinek lekérdezésére vagy beállítására szolgálDate
. -
getHours()
|setHours()
Lehetővé teszi az objektum óráinak megtekintését vagy módosítását (0 és 23 között).Date
. -
getDay()
A hét napját adja vissza a dátumhoz, 0 és 6 közötti értékben kifejezve (vasárnaptól szombatig). -
getDate()
|setDate()
Visszaadja vagy módosítja az objektum hónapjának napjátDate
amelyen alkalmazzák. -
getMonth()
|setMonth()
Az objektum hónapszámának lekérdezésére vagy módosítására szolgálDate
. -
getFullYear()
|setFullYear()
Lekérdezi vagy beállítja az év értékét a dátumot és időt tartalmazó objektumon.
A korábbi módszerek Date
verziót is tartalmazzon UTC hogy az univerzális idővel közvetlenül dolgozhassunk anélkül, hogy közbenső számításokat kellene végezni. Ilyen értelemben pl. getHours()
van egy verziója getUTCHours()
o getMilliseconds()
egy alternatíva getUTCMilliseconds()
felváltva a hivatalos (törvényes) vagy egyetemes idővel dolgozni. Val vel getTimezoneOffset()
Tudja, mi a különbség az egyetemes idő és a helyi hivatalos idő között.
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 funkciók
Ha ezt olvasod, biztosan tudod, hogyan kell programozni. mikrovezérlők en C Az in C + + és ismerje a funkció fogalmát. Bár az alapötlet ugyanaz, in JavaScript Meghatározásuk és használatuk módja kissé eltér. Kezdetben már elhangzott, JavaScript Nem használ kifejezetten adattípusokat, így a függvény definiálásakor nem kell feltüntetni. Követni, Egy függvénynek nem kötelező neve, lehetnek névtelenek. Változóhoz társíthatók a meghíváshoz, de előfordulhat, hogy nincs is rá szükség, mert esetenként célszerű azonnal meghívni őket, amihez a zárójeleket és a paramétereket a függvény definíciója után hozzá kell adni.
Függvény meghatározásához az előtagot function
, ha alkalmazható, zárójelben írja be a nevet, az argumentumokat (a függvénynek átadott paramétereket), és a függvény meghívásakor végrehajtandó kódot kapcsos zárójelek közé.
1
2
3
4
5
|
function doble(numero)
{
var resultado=numero*2;
return resultado;
}
|
Természetesen az előző példában az "eredmény" változóra egyáltalán nem volt szükség, de jó ürügy arra, hogy emlékezzünk a változó hatókör, ami a várt módon működik: az "eredmény" változó csak a "double" függvényen belül létezik. Ban ben JavaScript is használható let
helyett var
, egy változó kódblokk-kontextusba való hatókörébe (kapcsos zárójelek közé zárva, {
y }
)
Amikor az előző részben az objektumokról beszéltünk, valami alapvető hiányzott: a tulajdonságok definiáltak, de a metódusok nincsenek meghatározva. Ahogy az várható volt, az objektum metódusok függvények, nincs nevük, és az objektumdefiníció által hozzárendelt (tulajdon)névből használatosak (meghívásuk).
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”);
}
}
|
Az előző példában már létezik egy "view_temperature" metódus, amely a "current_temperature" tulajdonság értékét jeleníti meg a konzolon keresztül. Nem túl hasznos, de teljesebb képet ad arról, hogy mi is az objektum meghatározása JavaScript.
Egy objektum (függvények) metódusainak eléréséhez a tulajdonságaihoz használja a this
, mint az előző példában a 11. sorban, a „current_temperature” tulajdonság használatakor.
Hozzáférés a dokumentumobjektum-modellhez (DOM) JavaScript segítségével
-tól JavaScript Hozzáférhet annak a weboldalnak a tartalmához, amelyen az fut, valamint az oldalt megjelenítő böngésző egyes elemeihez, bár nem a rendszererőforrásokhoz. Az adatstruktúra, amely támogatja az innen elérhető tulajdonságokat és metódusokat JavaScript az ablak objektum része, konkrétan az objektum (a dokumentum) tartalma HTML) az objektumnak felel meg document
. Bár néha az áttekinthetőség kedvéért használják, nem szükséges a metódusok vagy tulajdonságok előtt ablak előtt hivatkozni rájuk, elég pl. document
, nem kell a gyökérobjektum nevét úgy beírni, mint a window.document
, mindaddig, amíg az aktuális ablakra hivatkozik.
A leggyakrabban használt formája keressen egy objektumot a dokumentumban HTML A módszeren keresztül történik getElementById()
, amelyhez a kód létrehozásakor jelzett azonosító argumentumként kerül átadásra HTML. Az előző részekben leírtak alapján könnyen feltételezhető, hogy az objektumon belüli összetevőket is elérheti document
pont szintaxis használatával (document.componente
) vagy zárójelben használja mindkét nevet (document["componente"]
), a leghasznosabb, például a numerikus index, amely nehezen használható és nem praktikus egy kézzel összeállított weboldal tartalmának elérésekor.
a JavaScript tudsz lekérni azt az elemet, amely egy másik elemet tartalmaz (elem vagy szülő csomópont) ingatlanának tanácsadása parentNode
vagy a tulajdonát parentElement
, a különbség az, hogy a szülő elem (parentElement
) a karakterlánc utolsó eleme DOM Ez null (null
) és a szülőcsomópont (parentNode
) maga a dokumentum (document
).
hogy módosítani egy elem tartalmát HTML, például egy címkét <div>
, Használható innerHTML
és tulajdonságainak megváltoztatásához választhat, hogy egy másik osztályt rendel hozzá className
vagy egyedileg módosíthatja a tulajdonságait style
. A weboldal elemei által megjelenített stílus megtekintése nem feltétlenül hasznos style
mivel ez több tényezőtől is függhet, vagy egyszerűen nem határozták meg kifejezetten. A weboldalon végül megjelenő elem stílusának ellenőrzéséhez a getComputedStyle metódust használjuk.
Egy dokumentumelemhez HTML Több osztály is hozzárendelhető hozzá, hogy meghatározzuk megjelenését és viselkedését innen kezelheti egy objektum osztálylistáját JavaScript igénybe veheti classList
amely a módszereket kínálja add
új osztály hozzáadásához a listához, remove
eltávolítani, toggle
lecserélni, vagy megnézni egy elem osztálylistájának tartalmát item
és contains
, amely visszaadja a listában egy bizonyos pozíciót elfoglaló osztályt és egy értéket true
o false
hogy egy bizonyos osztály szerepel-e a listán vagy sem.
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”)
}
|
Az előző példában a következővel található: getElementById
a kezelni kívánt objektum (egy elem <div>
az ő számára id
), a megjelenés megváltoztatása előtt a tartalom törlésre kerül a -val történő hozzárendeléssel innerHTML
üres szöveges karakterláncot, akkor új osztályt rendel hozzá className
stílusa pedig módosul style
a tartalom (hőmérséklet) értékétől függően színváltoztatás, adott esetben az ingatlanon keresztül color
. A szempont létrehozása után az érték újra a használatával kerül kiírásra innerHTML
.
A fenti példa második részében (9-19. sorok) egy kódelem érhető el HTML a szintaxist használva document[]
és az ingatlan id
az elem osztálylistájának módosításához a metódussal classList.remove()
és a módszerrelclassList.add()
, több lekérdezés eredménye alapján, amelyeket feltételes végrehajtásban hajtanak végre, és ezeket összehasonlítják classList.contains()
.
Mikor fog elemre hivatkozik HTML számos alkalommal a kódban JavaScript, ez egy kicsit hatékonyabb hozzárendelni egy változóhoz vagy használja az indexét a név helyett, mivel ellenkező esetben az Ön által használt módszer JavaScript minden alkalommal meg kell keresni a nevét, ami kicsit több időt vesz igénybe, mintha egy változót elérnénk.
hogy új objektumok hozzáadása a dokumentumhoz HTML, először a módszerrel hozhatók létre createElement
de document
és később beépítik őket a többi elembe a fa azon pontján, amelyre szükség van appendChild
. Objektum létrehozásához XML, mint a tárgyak SVG amelyet az IoT-érzékelők grafikonjának megrajzolásához használunk, használhatja createElementNS
(NS for névtér). Ahogyan a formátumról beszélünk SVG, a neki megfelelő névtér (az aktuális verzióhoz). http://www.w3.org/2000/svg
, amelyet át kell adni createElementNS
argumentumként az elem típusával együtt, svg
, ebben az esetben.
egy alternatívája innerHTML
hogy szöveget adjunk tartalomként egy dokumentumelemhez HTML a módszer createTextNode()
az objektum document
. Ezzel az alternatívával megteheti új szöveget létrehozni (amely később elérhető, ha változóhoz van rendelve), amely a metódussal beépül az objektumfába appendChild()
. Hogyan alternatívája appendChild()
, amely hozzáadja az új tartalmat annak a csomópontnak a végéhez, amely már létezik abban a csomópontban, amelyhez hozzáadta, használhatja a módszer, a metódus insertBefore()
, amely egy új objektumot ad egy meglévő elé. Viselet insertBefore()
helyett appendChild()
olyan módszert biztosít, amely például arra szolgál rendezze az új objektumokat a meglévők elé amikor egy elemnek egy másik előtt kell lennie (mint egy listában), vagy fednie kell vagy le kell fednie egy olyan grafikus struktúrát, amelyben az előtérhez vagy a háttérhez közelebbi elemek vannak.
Reagálj az eseményekre JavaScript segítségével
Amikor az utat használjon egy weboldalt tárolóként az IoT-hez kapcsolódó szenzorgrafikonokhoz azt használták onload
A címkén <body>
hogy elkezdje rajzolni a grafikont. Ez a kódobjektumokhoz társított tulajdonság HTML, utal a Események JavaScript. Ahogy már kifejtettük, az oldal betöltésekor végrehajt egy funkciót. Bár a kódhoz társították HTML hogy jobban észben tartsuk, a kódba bele lehetett volna írni JavaScript mint body.onload=dibujar;
lét dibujar
annak a függvénynek a neve, amelyet a weboldal betöltésekor el kell indítani.
A legújabb verziókban JavaScript Az események a függvényekkel társíthatók addEventListener
a formátummal objeto.addEventListener(evento,función);
vagy a szintaxis használatával objeto.evento=función;
amely régebbi megvalósításokban is működik. Az eseményhez társított funkció leválasztásához meg kell tennie removeEventListener
amelynek formátuma megegyezik addEventListener
.
JavaScript Képes reagálni a weboldalon előforduló események sokaságára. Például képes érzékelni, ha egy elemre kattintanak HTML a onmousedown
, vagy ha rákattint onclick
, ha egy billentyűt lenyomnak a gombbal onkeydown
, a görgetősáv használatával onscroll
. Célunknak ez elég nekünk oldalbetöltés észlelése onload
és átméretezése -val onresize
. Ezeket az eseményeket társítjuk a tárgyakkal body
y window
del DOM illetőleg. Az első hozzárendelhető a kódban HTML, amint látható és a második a kódon belül JavaScript az első által meghívott függvényen belül és a formátummal window.onresize=redimensionar;
lét redimensionar
a függvény, amely minden alkalommal meghívásra kerül, amikor az ablak mérete megváltozik.
Fuss egy időintervallum után
JavaScript két forrása van halasztott végrehajtás: setTimeout
, amely egy időintervallum után végrehajt egy függvényt és setInterval
amely bizonyos időintervallumonként végrehajt egy függvényt. Mindkét módszer paraméterként megköveteli (1) a meghívott függvényt és (2) az ezredmásodpercben kifejezett időintervallumot. Működésük leállításához a függvények által visszaadott eredményt hozzárendelheti a változókhoz, és argumentumként átadhatja őket clearTimeout
vagy clearInterval
amikor nem akarja újra meghívni őket (vagy ha nem akarja, hogy először hajtsák végre őket) setTimeout
o setInterval
volt.
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
}
|
Az előző példában a módszert mutatjuk be alert
amely figyelmeztető tábla megjelenítésére szolgál. Bár korábban széles körben használták, jelenleg szinte ki van tiltva a kódból JavaScript mert mennyire agresszív (tolakodó) a weblapot egy párbeszédpanel borítani.
A számára írt programban mikrovezérlő egy kis sorozatból (mint amilyen a tányéron van). Arduino Uno) általános a globális változók használata, mint az előző példában JavaScript, mivel a kód rövid és nem különösebben zavaró, mert sokszor ad hoc módon valósulnak meg a funkciók, és mert a globális változók használata nagyon egyszerű és intuitív módon teszi lehetővé a memóriahasználat előrejelzését, ami kritikus a kevés erőforrással rendelkező rendszerekben. . Helyette, en JavaScript Gyakori, hogy a globális változók használatát a lehető legkisebbre csökkentik. mert nem kell siettetni a memóriahasználatot, mivel rendesen fut a CPU erőforrásaival, amelyek messze felülmúlják a MCU, mert valószínűleg sok harmadik féltől származó kóddal együtt létezik, amelyekkel beavatkozás nélkül kell működnie, és mivel nyílt rendszerről van szó, a jövőbeni végrehajtási környezet nem jósolható meg (a mikrovezérlő Small teljesen meghatározza a működését anélkül, hogy a működés után további kódot adna hozzá), és mivel az alkalmazások méretei megnehezíthetik az olvasást, ha a kód nem zárja be a működését, így a módszerek a lehető legönállóbbakká válnak.
Matematikai műveletek a JavaScript Math objektummal
A bonyolultabb matematikai számítások matematikai műveletei az objektumban vannak csoportosítva Math
. Ezt az objektumot közvetlenül használjuk, nem szükséges példányosítása a benne foglalt metódusok vagy tulajdonságok (konstansok) használatához.
Math.abs(n)
Az n paraméter abszolút értékeMath.acos(n)
Az n paraméter arkoszinusza (eredmény radiánban)Math.asin(n)
Az n paraméter arcszinusza (eredmény radiánban)Math.atan(n)
Az n paraméter arktangense (eredmény radiánban)Math.atan2(n,m)
n/m arktangens (az eredmény radiánban)Math.ceil(n)
Kerekítse fel a paramétert a legközelebbi egész számraMath.cos(α)
Az α paraméter koszinusza (α radiánban)Math.E
e-szám (≃2.718281828459045)Math.exp(n)
e az n paraméterre emelve: enMath.floor(n)
Kerekítse le az n paramétert a legközelebbi egész számraMath.log(n)
Az n paraméter természetes logaritmusa (e bázisa).Math.LN2
2-es természetes logaritmus (e bázis) (≃0.6931471805599453)Math.LN10
10-es természetes logaritmus (e bázis) (≃2.302585092994046)Math.LOG2E
e 2. alapú logaritmusa (≃1.4426950408889634)Math.LOG10E
e 10. alapú logaritmusa (≃0.4342944819032518)Math.max(a,b,c,…)
Az átadott paraméterek listájának legnagyobb értékeMath.min(a,b,c,…)
Az átadott paraméterek listájának legkisebb értékeMath.PI
π szám (≃3.141592653589793)Math.pow(n,m)
Az első n paraméter a második m paraméterre emelve: nmMath.random()
(Majdnem) véletlen szám 0.0 és 1.0 közöttMath.round(n)
Az n paramétert a legközelebbi egész számra kerekítseMath.sin(α)
Az α paraméter szinusza (α radiánban)Math.sqrt(n)
Az n paraméter négyzetgyökeMath.SQRT1_2
1/2 négyzetgyöke (≃0.7071067811865476)Math.SQRT2
2 négyzetgyöke (≃1.4142135623730951)Math.tan(α)
Az α paraméter tangense (α radiánban)
Adatok betöltése a szerverről AJAX-szal
Az IoT-ben tárolt információk megrajzolásának módszere abból áll, hogy időről időre betöltik az adatokat a szerverről, és újrarajzolják azt a grafikont, amellyel ábrázolják őket. A szerverről származó adatok olvasásához technológiát használnak AJAX (aszinkron JavaScript és XML) tárgyon keresztül XMLHttpRequest
de JavaScript. Az adatgráf ábrázolása egy objektum újrafelhasználásával történik SVG ami már benne van a kódban HTML és amely egy diagramot tartalmaz, amelynek koordinátáit úgy módosítjuk, hogy azok megfeleljenek az újonnan betöltött adatoknak.
A javaslat példájában a rajz frissítése mellett egy olyan szöveg is frissül a weboldalon, amely minden grafikonhoz mutatja az utolsó mért adat dátumát és értékét.
A szerver oldalon van egy adatbázis, amely tartalmazza az információkat hogy az IoT-hez csatlakoztatott érzékelők figyelték. Ezt az adatbázist az objektumkérés olvassa be XMLHttpRequest
a kódolt információval válaszol JSON formátum, bár az alkalmazott módszer neve a formátummal való kapcsolatra utal XML.
Az első polaridad.es oktatóanyagban a IoT adattárolás Láthat egy példát egy olyan infrastruktúrára, amely szerveroldalról kezeli a tárgyak internetéhez csatlakoztatott eszközök által szolgáltatott információkat. Ebben a cikksorozatban egy szervert használunk erőforrásként Apache amelyből használhatja a programozási nyelvet PHP adatbázis eléréséhez MySQL o MariaDB. Az IoT támogatására használt szervereken nagyon gyakori az adatbázisok keresése MongoDB (NoSQL) és a programozási nyelv JavaScript tovább node.js mint szoftver infrastruktúra.
A következő funkció a legfrissebb adatok lekéréséért felel az egyik érzékelőtől a szervertől. A függvényhívásban az objektumot argumentumként használják JavaScript amely támogatja a rajzolt adatokat. Ha ugyanaz a gráf több értéket ábrázol, például egy összefüggés vizuális keresése érdekében, akkor kérhető a szerver, hogy egyszerre több értéket adjon vissza, ami a szerver működése miatt optimálisabb módszer. HTTP protokoll.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
function consultar_ultimo_valor_sensores(objeto_grafico)
{
var consulta=‘zona=”+objeto_grafico.sufijo_nombre;
var pagina=“ultimo_valor_sensor.php”;
var resultado;
var ajax;
if(window.XMLHttpRequest)
{
ajax=new XMLHttpRequest(); // ajax=Object.create(XMLHttpRequest);
}
else // Versiones antiguas de MS Internet Explorer
{
ajax=new ActiveXObject(“Microsoft.XMLHTTP”);
}
ajax.onreadystatechange=
function()
{
if(ajax.readyState==4&&ajax.status==200&&ajax.responseType==“json”)
{
resultado=JSON.parse(ajax.responseText);
if(resultado.fecha>objeto_grafico.fecha[objeto_grafico.fecha.length–1])
{
// Normalmente se gestionará la respuesta utilizando el objeto
redibujar_grafico(objeto_grafico,resultado);
// Si los datos son sencillos y tienen una estructura clara puede ser más práctico usarla directamente
// redibujar_grafico(objeto_grafico,[resultado.fecha,resultado.temperatura]);
}
}
}
ajax.open(“POST”,pagina);
ajax.setRequestHeader(“Method”,“POST “+pagina+” HTTP/1.1″);
ajax.setRequestHeader(“Content-type”,“application/x-www-form-urlencoded”);
ajax.setRequestHeader(“Content-length”,consulta.length);
ajax.setRequestHeader(“Connection”,“close”);
ajax.send(consulta);
}
|
Az előző példa harmadik sorában készül el a szerver felé irányuló lekérdezés, amelyben a "zóna" argumentum kerül átadásra, melynek értéke a megfigyelt hely neve vagy kódja lesz, mivel a különböző érzékelők (például hőmérők, amelyek különböző helyiségekben mérik a hőmérsékletet). Az előző függvénynek, a diagramadatokat tartalmazó objektumnak átadott paraméternek tartalmaznia kell egy tulajdonságot a szoba nevével ("name_suffix").
Az előző kód 7. és 14. sora között a objektum XMLHttpRequest
amelyet az "ajax" változóban tárolunk. Mielőtt kiválasztaná az objektum létrehozásának módját, keressen window
ha XMLHttpRequest
nem volt elérhető (valami, ami a Microsoft Explorer régi verzióiban történt, és bár messze elmaradt, példaként szolgál az objektum (natívabb) szintaxissal történő létrehozására) Object.create
o new
, hasonlóan a többi objektum-orientált nyelvhez.
A válasz azonnali kezelése érdekében a 15-26. sorokban elkészítjük az azt kezelő kódot, mielőtt a kiszolgáló felé fordulna.
Az út hajtsa végre a lekérdezést HTTP hogy a szerver áll kapcsolatot nyitni a open
típus és oldal jelzése (opcionálisan felhasználónév és jelszó), készítse elő a fejléceket a protokollból setRequestHeader
y küldje el a kérést a send
. A fejléc HTTP Content-length
tudnia kell a lekérdezés hosszát (karakterek számát), amelyet a segítségével számítanak ki length
.
Amikor a kérés AJAX készen áll, az eseményhez tartozó funkció végrehajtásra kerül onreadystatechange
. Funkció hozzárendelése helyett az előző példában egy anonim függvényt definiálunk menet közben, amely a szerverről érkező adatok fogadását fogja kezelni. Először is a 18. sorban ellenőrizzük, hogy a kérés állapota "befejezett", ami megfelel az értéknek. 4
az ingatlan readyState
, hogy az állapot "OK" a HTTP protokoll (kód 200
), amely az ingatlanból beszerezhető status
és hogy a megérkezett adatok az JSON formátum, tanácsadás az ingatlannal responseType
.
Miután ellenőrizte, hogy a válasz állapota a vártnak megfelelő-e, az előző példa 20. sorában objektumot hoz létre az eredménnyel, átalakítva a szöveget JSON. A válasz megadja a visszaküldendő dátumot, ez lehetővé teszi, hogy megnézzük, hogy a szerver által küldött eredmény szerepel-e már korábban a grafikonon, amit a 21. sorban ellenőriztünk. Ha az adatok újak, a 23. sorban Az a függvény, felelős a grafikon újrarajzolásáért az új információkkal ún.
Ennek az olvasási módszernek az a gondolata, hogy az adatokat nagyon gyakran frissítik. Ha a bemutatott információ hosszú távnak felel meg (például egy nap vagy egy hét hőmérséklete), akkor végrehajtható egy kezdeti kérés, amely összegyűjti az összes rendelkezésre álló adatot, majd egy, a példában szereplőhöz hasonló, amely frissíti azokat az időszaki tudósító.
Véletlenszerű adatokat generál a teszteléshez
Amikor az összes szerver és kliens infrastruktúra készen áll, az előző részhez hasonló függvény lesz felelős az adatok beolvasásáért és a grafikon megrajzolásáért, de A tesztelési szakaszban célszerűbb lehet véletlen számokat használni egy ellenőrzött tartományon belül hogy megnézze, helyes-e az írott kód. A következő funkció példaként szolgálhat adatok beszerzésére a végső alkalmazás felépítése során.
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);
}
|
Ahelyett, hogy egy adatbázisból olvasná ki az információkat, a fenti példa véletlenszerűen generálja azokat, és átadja a grafikon megrajzolásáért felelős függvénynek. A kitalált adat egy vektor, amelyet egy ezredmásodpercben kifejezett dátum, a szenzor információ rögzítésének pillanata és a megfigyelt adat alkot, amely egy maximális érték és egy minimális érték között van.
Ebben a példában egy dátum generálásakor az akár egy másodpercig (1000 ezredmásodpercig) késleltethető a feltaláláskori dátumhoz képest. Mint Math.random()
0.0 és 1.0 közötti számot generál, 1000-zel megszorozva 0 és 1000 közötti számot kap, amelyet aztán egész számmá alakít. Ugyanígy az értéket úgy kapjuk meg, hogy a véletlen számot megszorozzuk a tartománnyal (maximum mínusz minimum), és összeadjuk a minimumot.
Rajzolja meg az IoT-érzékelők grafikonját SVG-grafikonnal
Mivel láttuk, hogyan kaphatjuk meg az ábrázolni kívánt értékeket (hőmérséklet, a példában) és azok időbeli elhelyezkedését, amelyek együttesen koordináták formájában fejezhetők ki, az alábbi példa egy útvonal rajzolására szolgáló függvényt mutat be. amely összeköti ezeket a pontokat és opcionálisan egy színes területet, amelyet az a vonal határol a tetején. Az eredmény olyan lenne, mint a következő képen.
A grafikon vízszintes tengelye (X) az időt, a függőleges tengely (Y) pedig azokat az értékeket jelöli, amelyeket az IoT-hez csatlakoztatott érzékelők figyeltek. A vízszintes intervallum néhány másodperc, mivel ebben a javaslatban a grafikont nagyon gyakran (például másodpercenként) frissítik, hogy szinte valós idejű információkat nyújtsanak az érzékelők állapotáról.
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
}
|
Az előző kódban két érdekes szempont van, először is a számítás, amely lehetővé teszi igazítsa a megjelenített értéktartományt másodszor pedig a ingatlanépítés d
amely jelzi a pontok koordinátáit az elrendezésen (path
).
A megjelenített értékek tartományának igazítása érdekében azokat a minimumtól elmozdítjuk, és úgy skálázzuk, hogy a látható nagyság megfeleljen a grafikon méretének.. Idő esetén az eltolást úgy kapjuk meg, hogy kivonjuk a megjeleníteni kívánt tartományt a leghosszabb időből (az aktuálishoz legközelebb eső dátum és idő) (a példában 20 másodperc). A hőmérsékleti értékek eltolása az alsó tartomány (egy fok) mínusz a legalacsonyabb érték, így az alább látható adatok a leginkább hasonlítanak a megengedett legalacsonyabb értékhez, de hagynak egy határt, amely lehetővé teszi számunkra, hogy értékeljük az áthaladást.
Az időértékeket megszorzó együtthatót a grafikon vízszintes koordinátáinak megszerzéséhez úgy kapjuk meg, hogy a grafikon teljes szélességét (a példában 100 egység) elosztjuk a reprezentált időtartománnyal (a példában 20 másodperc). Ahhoz, hogy a skaláris hőmérsékleti értékekkel együtt megkapjuk az együtthatót, emlékeznünk kell arra, hogy a reprezentált tartomány a minimális érték alatti margótól a maximum feletti margóig terjed, mindkét esetben egy fokkal. Ily módon a függőleges skálaegyüttható a grafikon magasságának (a példában 100 egység) elosztásából adódik a maximális értékkel, mínusz a minimum plusz a felső és alsó margó. Mivel ezek az értékek negatív hőmérsékleten teljesen kialakulhatnak, ezért használjuk Math.abs()
hogy a különbség abszolút értékét használjuk.
A tulajdon d
az objektum path
A szövegben lévő pontok koordinátáinak összefűzésével készül. Minden koordinátapárt egy kód előz meg SVG L
, amely vonalat húz az aktuális pozícióból egy abszolút értékre, amelyet a koordináták jeleznek. Az X és Y értékeket vesszővel és minden művelettel választjuk el SVG szóköz választja el a következőtől.
Az elrendezés elindításához használja a kódot M
(mozgás egy abszolút koordinátára). A zárt és kitöltött telek esetén a jobb alsó sarokban, az adatprofilt rajzoló nyitott telek esetében az utoljára ábrázolt értékkel (a legfrissebb) kezdjük. A zárt elrendezés befejezéséhez a kódot használják Z
Utolsó pontként azt adjuk hozzá, amelynek az X koordináta értéke megegyezik az egyenes utolsó pontjával, Y koordinátaként pedig a legkisebb képviselt értéket.
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
);
}
|
Ebben a példában a függvény dibujar_grafico()
, amely az oldalbetöltéskor hívás, megkapja a tesztelendő kezdeti értékeket (nem az utolsó valós idejű értéket), és előkészíti az adatok megjelenítési tartományát: 20 másodperc (20000 ms) vízszintesen és 15°C függőleges -5°C és +10°C között egy fokos felső és alsó margóval. Két hívás kezdeményezése actualizar_grafico()
, az első menetben true
argumentumként, ami azt jelzi, hogy a diagramot be kell zárni, hogy egy kitöltött területet ábrázoljon, és a második hívásnál átmegy false
meghúzni a határt. Minden esetben az objektum path
Módosítva az, amelyik a megfelelő megjelenésű, az első esetben kitöltéssel és szegély nélkül, a másodikban pedig bizonyos vonalvastagsággal és kitöltés nélkül.
A funkció actualizar_grafico()
munka egy tárgyon SVG amely a következő kódot használja tárolóként HTML. A tárgy SVG két útvonalat tartalmaz, az egyik a vonal, a másik pedig a kitöltött terület rajzolására szolgál. A weboldal betöltésekor az elemből <body>
az előző függvény automatikusan meghívásra kerül, dibujar_grafico()
az eseménynek köszönhetően 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>
|
A kód 10. sorában HTML fent a stílusban 820 px szélesség (példaként) és 150 px magasság van beállítva (amit a végső változatban ajánlatos egy osztályhoz és egy dokumentumhoz tenni CSS). Furcsának tűnik, hogy a 13. és 14. sor határozza meg az objektum méretét SVG mint a 100%-os szélesség és magasság (ami a legjobban megfelel az ablakméreteknek, 100×100). Mint már említettük, ennek az az oka, hogy mindig ismert méretekkel dolgozzunk, és ehhez igazítsuk a megjelenített értékeket. A másik alternatíva az lenne, hogy minden alkalommal kiszámítjuk a grafikon terét, majd újra beállítjuk az értékeket, vagy kényszerítjük a grafikon rögzített méreteit, amelyeket a dokumentumnak be kell tartania.
Olyan grafikon mellett döntött, amelynek méretei a kód szerint változnak HTML, szükséges az ingatlan szerepeltetése vector-effect
a bátorsággal non-scaling-stroke
annak megakadályozására, hogy a vonalvastagság deformálódjon, amikor a grafikon nem tartja meg a kiválasztott 1:1 arányt azon a weboldalon, amelyen megjelenik, ahogy az az előző javaslatban is előfordul.
A diagram „kivágásához”, és csak a kiválasztott terület megjelenítéséhez használja a gombot viewBox
. Ebben az esetben úgy döntöttünk, hogy a grafikonnak azt a részét nézzük, amely 0,0-val kezdődik (bal felső sarokban), és mérete 100x100 lefelé és jobbra. A rajz negatív értékű vagy 100-nál nagyobb koordinátákban lévő része nem jelenik meg a weboldalon, még akkor sem, ha az objektumban létezik SVG
Új elemek hozzáadása az SVG-rajzhoz
Az előző példában a függvény actualizar_grafico()
elrendezést használjon SVG amelyre a tulajdonjog megváltozik d
, ami a koordinátaláncot fejezi ki. Az alternatíva az lenne, ha a teljes objektumot minden újrarajzoláskor létrehozná. Az első lehetőség előnye, hogy a grafikus megjelenés (például vastagság vagy szín) a kódban van meghatározva HTML, a korlátozás az, hogy az objektumokat korábban létre kell hozni.
SVG objektumok létrehozásához használja a createElementNS()
, amely lehetővé teszi többek között a névtér. Az alábbi példában egy új szövegobjektum jön létre (text
), és egy elemhez van társítva SVG amely már létezik a kódban HTML a webhelyről. Az új elem létrehozása után a tulajdonságok hozzá vannak rendelve setAttribute()
és hozzáadódik SVG a 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]);
|
Módosítsa a rajzelemek arányát
Ha az előző szakasz példájában szereplő függvény segítségével próbálta meg a címkézést, látni fogja, hogy a szöveg deformáltnak tűnik, amikor az objektum aránya a weboldalon (width
y height
A kódtól HTML) nem egyenlő az ábrázolt területtel (viewBox
). Az arány adaptálásához ismerni kell a tárgy méreteit SVG amelyhez megtekintheti az objektum vagy a tároló stílusát HTML, ha az objektum SVG adja át ezt az ingatlant. Tulajdonjog hozzárendelése transform
tárgyakhoz SVG az aránytól függő alakváltozás korrigálható skálázó művelettel scale()
amelyben az X-beli együttható különbözik az Y-beli együtthatótól.
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 lehetővé teszi több objektum csoportosítását, új összetett elemet alkotva, amely a tulajdonságokat is támogatja, mint az egyszerű tárgyak. Ha ugyanazt a transzformációt egyszerre több objektumsorozatra szeretné alkalmazni ahelyett, hogy minden objektum külön-külön, csoportosítható őket ennek az erőforrásnak megfelelően, és egyetlen tulajdonságot alkalmazhat. transform
mindegyiknek.
Ahogy arról beszélünk SVG formátum, egy csoport elemei a címkék közé vannak zárva <g>
y </g>
. Hozzáadni innen JavaScript elemeket egy csoporthoz SVG használják, amint az az előző példában is látható, appendChild()
az új objektum meghatározása után.
A transzformációk alkalmazásakor eredet megállapításához a tulajdonság objektumokon használható SVG transform-origin
, melynek értéke annak a pontnak az X és Y koordinátája, ahonnan a transzformáció kezdődik. Ha a transzformáció eredetének értéke nincs kifejezetten feltüntetve (a webböngészőben), akkor a koordináták középpontja kerül felhasználásra. Sajnos a cikk írásakor az átalakítások viselkedésének megadása az alapértelmezetttől eltérő forrás használatával nem homogén a böngészők között, ezért óvatosan kell használni.
A skála transzformációval együtt scale
Vannak mások, mint például a forgatás rotation
és a mozgást translate
, amelyek a alternatívája a gráfábrázolásnak: ahelyett, hogy új koordinátákat kapna, ábrázolhatja őket a saját terükben, és átalakíthatja a grafikont, hogy illeszkedjen ahhoz a formátumhoz, amelyben ábrázolni szeretné őket.
Adjon hozzá hivatkozásokat a diagramhoz
Most, hogy a grafikon fő része az értékek profillal és kitöltött területtel való ábrázolásával megoldott, kiegészíthető hivatkozásokkal, amelyek segítik az olvasást. Példaként kezdjük azzal, hogy rajzoljunk néhány vízszintes hivatkozást (vonalat), amelyek megjelölik a maximális és minimális elfogadható értékeket, valamint a kívánt értéket. Amint azt elmagyaráztuk, kiválaszthatja, hogy hozzáadja az objektumokat a SVG egyenesen JavaScript vagy manuálisan belefoglalhatja őket a kódba HTML és módosítsa őket később a segítségével 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();
|
Logikusnak tűnik, hogy ezeket a vízszintes hivatkozásokat olyan szöveggel jelöljük, amely tisztázza az általuk képviselt értéket. A szöveg kiemeléséhez használhat téglalapokat, amelyek kiemelkednek a háttérből és a grafikából. Mivel a szövegeket méretezni kell az alakváltozás kompenzálásához, mindegyik csoportosítható egy objektumba, amelyre a skálát alkalmazni kell; Ennek a módszernek az a fő előnye, hogy egyetlen művelettel módosítható, ha a grafikontárolót (a böngészőablakot) átméretezzük, és a skála által korrigált arányt módosítjuk.
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();
|
A fenti példakódban több érdekes szempont is van. Először is jegyezd meg, hogy konstansokat (globális változókat) használtak arra, hogy a példát olvashatóbbá tegyék a programozásból érkező felhasználók számára. mikrovezérlők en C Az in C + +. Mint később látni fogjuk, a programozás optimális módja JavaScript Ez olyan objektumok használata lenne, amelyek ezeket az értékeket tartalmaznák, és olyan módszereket használnának, amelyek kezelnék a példában szereplő hivatkozásokat vagy általában a grafikont egy éles rendszerben.
Másrészt az általánosabb kód előmozdítása érdekében külön függvényeket fejlesztettek ki, amelyek kiszámítják a különböző együtthatókat, amelyek korrigálják a grafikon arányát a szöveg módosításához. proporcion_grafico()
, az értékek skálája a tartományuktól függően escala()
és korrekciós tényező az abszolút értékben ismert mérésekhez, például a referenciaértékekben végzett mérésekhez medida_grafico()
.
Ennek a kódnak az olvasása segíthet tisztázni a kontextust, amelyben egy ilyen alkalmazás működik, amely valós időben rajzol grafikát, és rugalmasnak kell lennie ahhoz, hogy különféle grafikus kontextusokban (legalábbis különféle méretekben és arányokban) megjelenjen. Mindenekelőtt az objektumokat kell generálni SVG, vagy "manuálisan" a kódban HTML, akár kódon keresztül JavaScript és mindenesetre utólag hivatkozásokat kell szerezni ezekre az objektumokra, hogy manipulálhassuk őket JavaScript hogy új grafikonokat lehessen rajzolni, és egy már megrajzolt gráf ábrázolása adaptálható legyen a bemutatás közegének változásához.
Egy másik hivatkozás, amely segíthet egy grafikon egyszerű értelmezésében, a konkrét értékeket képviselő pontok (a vonal csomópontjai). Ebben a példában, amelyben egyetlen magnitúdót ábrázolunk, a szimbólum kiválasztása nem kritikus, de ha több különböző értéket egymásra rakunk a korreláció keresése érdekében, akkor érdekes megkülönböztetni, amellett, hogy más erőforrásokat, például színt használunk. , különböző szimbólumok rajzolásával. A vonalcsomóponthoz használt grafikát méretben és arányban módosítani kell, mint például a szövegeknél, hogy a méretei abszolútak legyenek, és arányai akkor is megmaradjanak, ha a benne lévő dobozé változna.
Az előző példában már láttuk, hogyan kell kiszámítani a különböző együtthatókat a rajz arányának átméretezéséhez és korrigálásához; A gráf csomópontjainak vagy csúcsainak szimbólumainak kezelését illetően egy lehetséges megoldás lehet az objektumok tárolása. SVG egy vektorba, és módosítsa a pozícióját, amikor a grafikont egy új érték beolvasásával frissítik, vagy amikor a tároló átméretezésével újrarajzolják. Az első esetben a helyzetét, a második esetben az ingatlannal való arányát kellene módosítani transform
és a scale
. A következő kód a funkció módosítása actualizar_grafico()
hogy tartalmazza a gráfcsúcs szimbólumainak áthelyezését.
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);
}
}
|
A funkció módosításai actualizar_grafico()
hogy megkapja az új funkciót actualizar_grafico_puntos()
Ezek azok, amelyek az előző példa kódjában kiemeltek. Először az 5. sorban veszünk egy objektumvektort SVG paraméterként. Ez a vektor fogja tartalmazni azokat a szimbólumokat, amelyeket át kell helyezni a gráf új csomópontjaiban.
A 39. és 40. sorban a középpont új koordinátái vannak hozzárendelve, cx
y cy
, azokhoz az értékekhez, amelyeket képviselnek. Ha a szimbólum nem a középponton alapult, valószínűleg szükség lesz egy eltolás hozzáadására cx
a szélesség fele és be cy
fele magasságú, hogy pontosan áthelyezze őket a gráf csomópontjára.
Az 57-61. sorokban azok a pontok, amelyek megfelelnek azoknak a koordinátáknak, amelyek nincsenek megrajzolva, mert a bal él levágja őket, áthelyeződik a grafikonon kívülre. A koordinátája cy
nullára és annak cx
tetszőleges negatív számra (nagyobb, mint maga a pont), így nem jelenik meg, amikor a grafikon bal oldalához hasonlóan a SVG.
Kezelje a diagramot egy objektumból JavaScript segítségével
Az összes eddig elmagyarázott művelet integrálható egy objektumba, hogy a gráfot az új verziókra jellemzőbb stílusban kezelje. JavaScript. Ennek a megvalósítási alternatívának az a további előnye, hogy leegyszerűsíti több különböző értékű grafikon beépítését ugyanazon a weboldalon.
Mielőtt a megvalósításról beszélnénk, tekintsük át az objektumok létrehozásának leggyakoribb módjait JavaScript és a funkciók néhány sajátossága, amelyek befolyásolják az IoT szenzorgrafika rajzolására vonatkozó javaslatot.
Már elmagyarázták, hogy az objektumok létrehozásának új módja a JavaScript (az 5-ös verzió óta elérhető ECMAScript) használatából áll Object.create
, amelyet meg kell szokni a "klasszikus" helyett new
, ami természetesen továbbra is megfelelően működik, bár célja inkább a nyelvek stílusának szimulálása osztályalapú objektumokkal (JavaScript prototípusokra alapozza az objektumok létrehozását), mint működő alternatíva.
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();
}
|
Az előző kód lehetővé teszi, hogy emlékezzen az objektumok létrehozása közötti különbségekre Object.create
o con new
. Azt is hangsúlyozni szolgálja, hogy míg a funkció, amellyel az objektum létrejön new
bárhol lehet a kódban, az objektumnak már léteznie kell, mielőtt példányosítható vele Object.create
(ES5_Object objektum nem függvény).
A 3. és 4. sorban az objektumot létrehozó függvény tulajdonságainak alapértelmezett értékének beállítása new
, minden tulajdonság a megfelelő argumentum értékéhez van rendelve vagy (||
), ha nem adtak át argumentumot, vagyis ha nem definiáltak (undefined
), mivel ezt a körülményt úgy értékelik false
, az alapértelmezett érték hozzá van rendelve.
A kontextus, amelyben egy függvény végrehajtásra kerül JavaScript két olyan kérdést vet fel, amelyeket fontos szem előtt tartani, és amelyek szintén zavaróak lehetnek a programozási nyelv használatakor, miután másokkal dolgozott együtt, mint pl. C o C + +, a mi esetünkben. A kontextus tartalmazza a függvény hatókörében definiált változókat (és a globálisakat), ami egyébként egy érdekes koncepciót vet fel, a "lezárásokat", amelyek egy teljes programozási stílust hoznak létre a programozásban. JavaScript. Mondjuk erre számítani lehetett this
, amely az objektumra utal, ha az azt definiáló kódon belül használják, a végrehajtási környezet, amelyben meghatározták, megmarad, de az általa használt környezet az, amelyből a függvény meghívódik. Ez a viselkedés a legtöbb esetben transzparens, de két körülmény között zavaró lehet: egy másik függvényen belül definiált függvény és egy objektumeseményből meghívott metódus. 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
*/
|
Az előző kód végrehajtásakor a konzolban megjelenik a végén kommentált szöveg. A két megjelölt vonal olyan viselkedést tükröz, amely zavaró lehet: a függvényvégrehajtási környezetet probar_dentro()
ez nem probar()
, ahogy az várható is volt, de window
, amely a globális változókat mutatja, és nem az azonos nevű tulajdonságokat. Ha nem szeretné ezt a viselkedést, egyszerűen hozzon létre egy változót a legmagasabb szintű függvényben, és rendelje hozzá this
, mint a következő kódban.
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
*/
|
A végrehajtási környezet szabályozása, amikor egy metódust eseményből hívják meg window
, például a böngészőablak átméretezésével, ami egy másik sajátossága JavaScript: "függvénygyárak", azaz olyan függvények programozásának lehetősége, amelyek más függvényeket generálnak, visszaadva azokat 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
|
A fenti példakódban a metódus llamar()
a tárgyak közül Contexto
Nem végzi el a munkát, hanem egy névtelen függvényt ad vissza, amely gondoskodik róla. Annak ellenőrzésére, hogy minden a várt módon működik-e, van egy globális változó, amelynek neve megegyezik a függvény által a konzolban megjelenített tulajdonsággal; Ha a kontextus helyes, akkor a tulajdonság értéke jelenik meg, és nem a globális változóé.
JavaScript Próbálja kijavítani azokat a pontosvesszőket, amelyeket a mondatok végéről kihagyunk. Ez nyugodt írásmódot tesz lehetővé, de kétélű fegyver, amelyet óvatosan kell kezelni. A legtöbb esetben, hogy elkerülje azokat a nemkívánatos hatásokat, amelyeket ez a több sort elfoglaló kifejezésekben okoz, zárójeleket használhat, vagy megelőzheti a JavaScript értelmezni fogja a kódot; Ezért tartalmazza a példa 8. sora function
A hátulján return
, ha egy másik sort használtam volna, a jelentés nagyon más lenne. Véleményem szerint a legolvashatóbb megoldás egy köztes (elhagyható) változó használata, mint a következő verzióban; Nyilvánvalóan, ha a viselkedést megértjük, a döntés megfelel a programozónak.
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);
|
Ugyanabban az értelemben, hogy egy kifejezést függvényként értékelünk, vagyis egy függvényt adunk vissza, és nem a függvény által visszaadott értéket; az utolsó példa 21. sorában (az előző példa 19. sorában volt) ezzel megáll clearInterval
-val meghívott függvény setInterval
. Annak érdekében, hogy 30 másodpercig működjön, a leállítást elhalasztják setTimeout
, amelynek viszont szüksége van egy függvényre első argumentumként; hogy a végrehajtást paraméterként kézbesítse clearInterval
azzal a változóval, amely a periodikus hívást tartalmazza (és nem a függvényt clearInterval
) erre jön létre az utolsó sorban lévő névtelen függvény.
A választás, hogy a kódot a függvénydefiníciót integrálva, tömörebben (mint a 21. sorban) vagy egy segédváltozót használunk, véleményem szerint jobban olvasható (mint a 19. és 20. sorban), a teljesítményben alig változik, és jobban stílustól és olvashatóságtól függ. karbantartás.
A kód teszteléséhez, mielőtt adatok lennének a szerveren, használhat egy véletlenszerű értékek generátort a kívánt tartományban, vagy készíthet táblázatokat ellenőrzött értékekkel, amelyek szimulálják a kívánt körülmények közötti működést. A következő példa egy egyszerű adatgenerátort használ a teljes tartományban, ezért kissé eltúlzottnak tűnnek.
A teszteléshez megteheti töltse le a példa teljes kódját beírt weboldal alkotja HTML, a stílus CSS és a kódot JavaScript. Ez utóbbi a legrelevánsabb, mivel a többi komponens csak minimális támogatást jelent, nagyon leegyszerűsített és sokkal jobban kidolgozott a megfelelő szakaszokban található cikkekben.
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);
}
|
Hozzászólás Comment