Generieren und ändern Sie SVG-Grafiken von Daten von Sensoren, die mit dem IoT verbunden sind, mit JavaScript
In diesem letzten Teil der Artikelserie zum Thema Zeichnen Grafiken mit Daten von Sensoren, die mit dem Internet der Dinge verbunden sind, ist es an der Zeit, darüber zu sprechen, wie man damit generiert oder ändert JavaScript Zeichnungen im Format SVG und einige der Elemente HTML die als Container dienen oder ergänzende Informationen zu den Grafiken darstellen.
Die Zielbenutzer dieses Tutorials sollen ein Elektronik- und Computerprogrammierungsprofil bilden. Mikrocontroller, sie sind möglicherweise nicht damit vertraut HTML, CSS o SVG; Aus diesem Grund wurde in den vorherigen Teilen eine kurze Einführung in die Sprache bzw. die entsprechende Technologie vorgenommen. In diesem letzten Teil ist der Ansatz etwas anders, da die Leser sicherlich wissen, wie man programmiert, es ist möglich, dass man die Sprache verwendet C + + was wie JavaScript, teilt die grundlegende Syntax mit C und es kann als Referenz genommen werden, um die meisten grundlegenden Programmierkonzepte zu überspringen und sich somit auf die Unterschiede und die spezifische Verwendung zu konzentrieren, die uns bei der Erstellung von Sensorgrafiken im IoT interessiert.
Der Name gibt einen Hinweis auf den ersten Unterschied: JavaScript Es ist eine Programmiersprache Skript (Bindestrich) und als solches ist es interpretiertEs besteht keine Notwendigkeit, es zu kompilieren. der Kontext, in dem die Skript (z. B. ein Webbrowser) liest, übersetzt und führt die Bestellungen aus. Um genau zu sein, gibt es in den meisten Fällen eine Laufzeitkompilierung (JIT), aber für den Code-Schreibprozess JavaScript Es betrifft uns nicht, wir schreiben einfach den Code und es kann funktionieren.
Der Name enthält auch die erste Verwirrung: JavaScript hat nicht die geringste Beziehung zu Javac. Ursprünglich, als es entwickelt wurde Netscape Der Browser hieß zuerst Mocha und dann das weniger verwirrende LiveScript. Nach seiner erfolgreichen Implementierung in Browsern und darüber hinaus wurde es standardisiert als ECMAScript (To ECMA-262, Version 6 zum Zeitpunkt des Verfassens dieses Artikels), um gegenüber Browsern, die es implementieren, neutral zu sein. Derzeit gibt es auch einen Standard ISO ab Version 5, 2011 (ISO / IEC 16262: 2011 zum Zeitpunkt des Schreibens des Artikels)
Variablen, grundlegende Datentypen und Objekte in JavaScript
Anders als zum Beispiel in C + +, en JavaScript Datentyp wird bei der Deklaration einer Variablen nicht berücksichtigt Da der einer Variablen zugeordnete Typ nicht festgelegt ist und der Typ nicht festgelegt ist, ist es möglich, während der Ausführung des Programms einen Wert eines anderen Typs zuzuweisen.
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
|
Im vorherigen Beispiel wurde die Variable „thing“ deklariert (ohne Angabe des Datentyps), dann werden Daten eines anderen Typs zugewiesen und diese werden konsultiert typeof
der Typ, der JavaScript das er interpretiert hat. Um den Code zu debuggen, können Sie ihn in die Inspektorkonsole des Webbrowsers schreiben (was sich nicht auf die Darstellung des Webs auswirkt). console.log()
.
Um die Konvertierung von Daten in einen bestimmten Typ, insbesondere von Text in Zahlen, zu erzwingen, können Sie Funktionen wie verwenden parseInt()
o parseFloat()
die in Ganzzahlen bzw. Gleitkommazahlen konvertieren. Die umgekehrte Konvertierung kann mit durchgeführt werden String()
, obwohl dies wahrscheinlich nicht notwendig ist, da die automatische Konvertierung normalerweise ausreicht. Mit parseFloat()
Sie können beispielsweise den Wert einer Webseiteneigenschaft abrufen, z. B. die Breite oder Höhe eines Objekts, das Einheiten enthält. Auf diese Weise ist der Ausdruck parseFloat("50px");
gibt als Ergebnis 50 zurück, einen numerischen Wert.
En JavaScript Es gibt keinen Unterschied zwischen doppelten und einfachen Anführungszeichen; Der Datentyp ist in beiden Fällen string
, und jeder von ihnen kann den anderen einschließen, ohne dass Escape-Codes erforderlich sind.
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
|
Im vorherigen Beispiel ist zu sehen, dass eine Variable, wenn sie deklariert wurde (existiert), aber ihr kein Wert zugewiesen wurde, einen undefinierten Datentyp enthält (undefined
). Ein nicht zugewiesenes Objekt hat den Wert null
; Das heißt, das Objekt existiert, aber ohne Wert; Eine Variable, die darauf verweist, hätte kein typeof
undefined
aber object
. Ein Objekt kann auch leer sein, also nicht null, aber keine Eigenschaften haben.
zu Definieren Sie ein Objekt in JavaScript werden in geschweifte Klammern eingeschlossen ({
y }
) die Eigenschaften oder Methoden, getrennt durch das Doppelpunktzeichen (:
) Eigenschaftsname Eigenschaftswert und durch Komma (,
) die verschiedenen Eigenschaften. Weitere Informationen zu dieser Art, ein Objekt auszudrücken, finden Sie im Artikel zum JSON-Format.
Obwohl Sie eine Syntax verwenden können, die Sie zu einer anderen Meinung verleiten könnte, en JavaScript Es gibt keine Klassen, sondern PrototypenDas heißt, damit ein Objekt Eigenschaften und Methoden erbt, wird ein anderes Objekt erstellt (der Prototyp), das die anderen (die Kinder) als Referenz verwenden. Die Syntax, die dem Stil von am nächsten kommt JavaScript einen Prototypen zu verwenden ist Object.create
obwohl es auch möglich (und manchmal nützlich) ist, es zu verwenden new
wie in anderen objektorientierten Sprachen.
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));
|
zu Abfrage, ob ein Objekt eine Instanz eines anderen ist, wenn Sie es als Prototyp verwenden, wenn Sie seine Eigenschaften erben, kurz gesagt, können Sie es verwenden instanceof
(hergestellt mit new
) O isPrototypeOf
(hergestellt mit Object.create
), die als wahr ausgewertet wird, wenn das Objekt den Prototyp verwendet, und als falsch, wenn dies nicht der Fall ist.
Sobald ein Objekt unter Verwendung eines anderen als Prototyp erstellt wurde, d. h. sobald ein Objekt instanziiert wurde, kann es sein Fügen Sie neue Eigenschaften hinzu oder überschreiben Sie Prototypeigenschaften unter Verwendung der Punktsyntax wie in gato.peso=2.5
.
La Arrays in JavaScript Sie unterscheiden sich von denen, die Sie wahrscheinlich kennen C. Sie werden zunächst ohne Angabe ihrer Länge deklariert, lediglich mit den Zeichen öffnender und schließender eckiger Klammern ([
y ]
), Komponenten können heterogen sein (verschiedene Datentypen im selben Array) und neue Elemente können ohne Einschränkung hinzugefügt werden. Die Matrizen von JavaScript sind eigentlich Listen (Sammlungen) von Elementen, zu denen durch einen numerischen Index oder einen Namen referenziert werden. Ein Array kann gleichzeitig numerische Indizes und Elementnamen enthalten, es ist jedoch üblich, Objekte (Eigenschaften) zu verwenden, um den zweiten Typ auszunutzen.
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
|
Wie im vorherigen Beispiel zu sehen ist, können Sie Folgendes verwenden, um festzustellen, ob eine Variable einer Instanz eines Arrays entspricht (es handelt sich um ein Array-Objekt). instanceof
, wie es bereits mit generischen Objekten oder in neueren Versionen von verwendet wurde JavaScript zurückgegriffen werden kann Array.isArray()
Um auf die Elemente des Arrays zuzugreifen, können Sie seinen Index verwenden (matriz[7]
) oder durch den Eigenschaftsnamen mit dem Namen in eckigen Klammern (matriz["nombre"]
) oder mit der üblichen Punktsyntax für Objekte (matriz.nombre
). Da es sich bei dem Namen um eine Textzeichenfolge handelt, kann zum Verfassen ein Ausdruck einschließlich Variablen verwendet werden. Um ein Array mit Eigenschaften zu durchlaufen, kann eine Schleife mit dem Format verwendet werden 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
*/
|
Es ist für unser Ziel interessant, es zu behandeln Objekt Date
, mit dem Datum und Uhrzeit dargestellt und verwaltet werden können JavaScript. Das Objekt kann ohne Daten instanziiert werden, sodass es das aktuelle Datum und die aktuelle Uhrzeit annimmt, oder es kann durch Angabe eines Datums als Wert erstellt werden, entweder in Millisekunden seit dem 1. Januar 1970 (z. B Unix-Zeit oder POSIX-Zeit aber ausgedrückt in Millisekunden statt Sekunden) oder die Angabe separater Werte für Jahr, Monat, Tag, Stunde...
Das Objekt umfasst eine komplette Serie von Methoden zum Abfragen oder Einstellen von Datum und Uhrzeit:
-
now()
Gibt das aktuelle Datum und die aktuelle Uhrzeit in Millisekunden seit dem 1. Januar 1970 zurück -
getTime()
|setTime()
Ruft den Zeitwert in Millisekunden seit dem 1. Januar 1970 ab bzw. ändert ihn. MitvalueOf()
, eine Methode, die in den meisten Objekten vorhanden ist, wird auch der Wert des entsprechenden Date-Objekts abgerufen, zgetTime()
mit Unix-Zeit oder POSIX-Zeit ausgedrückt in ms. -
getMilliseconds()
|setMilliseconds()
Wird zum Abfragen oder Festlegen des Bruchteils einer Millisekunde des Objekts verwendetDate
auf dem es ausgeführt wird. Bei Rückfrage liegt der erhaltene Wert zwischen 0 und 999, es können jedoch auch größere Werte zugewiesen werden, die sich im Gesamtdatum und der Gesamtzeit summieren, so dass es, wie die übrigen Get-Methoden, dazu dient, den Wert des Objekts zu erhöhenDate
(oder verringern, wenn negative Werte verwendet werden). -
getSeconds()
|setSeconds()
Gibt den Wert der Sekunden des Objekts zurück bzw. ändert ihnDate
. -
getMinutes()
|setMinutes()
Wird verwendet, um die Minuten des Objekts abzufragen oder festzulegenDate
. -
getHours()
|setHours()
Ermöglicht Ihnen, die Stunden (von 0 bis 23) des Objekts abzufragen oder zu ändernDate
. -
getDay()
Gibt den Wochentag für das Datum zurück, ausgedrückt als Wert von 0 bis 6 (Sonntag bis Samstag). -
getDate()
|setDate()
Gibt den Tag des Monats des Objekts zurück oder ändert ihnDate
auf dem es angewendet wird. -
getMonth()
|setMonth()
Wird verwendet, um die Monatsnummer des Objekts abzufragen oder zu ändernDate
. -
getFullYear()
|setFullYear()
Fragt den Jahreswert für das Objekt ab, das Datum und Uhrzeit enthält, oder legt diesen fest.
Die bisherigen Methoden von Date
Fügen Sie eine Version hinzu UTC um direkt mit der Weltzeit arbeiten zu können, ohne Zwischenrechnungen durchführen zu müssen. In diesem Sinne z.B. getHours()
hat eine Version getUTCHours()
o getMilliseconds()
eine Alternative getUTCMilliseconds()
wahlweise mit der offiziellen (gesetzlichen) oder Weltzeit zu arbeiten. Mit getTimezoneOffset()
Sie können den Unterschied kennen, der zwischen der Weltzeit und der lokalen offiziellen Zeit besteht.
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-Funktionen
Wenn Sie dies lesen, wissen Sie sicherlich, wie man programmiert. Mikrocontroller en C oder C + + und kennen den Funktionsbegriff. Obwohl die Grundidee dieselbe ist, in JavaScript Die Art und Weise, wie sie definiert und verwendet werden, ist etwas anders. Zunächst wurde bereits gesagt: JavaScript Da Datentypen nicht explizit verwendet werden, müssen Sie diese beim Definieren der Funktion nicht angeben. Folgen, Es ist nicht zwingend erforderlich, dass eine Funktion einen Namen hat, sie kann anonym sein. Sie können mit einer Variablen verknüpft werden, um sie aufzurufen. Dies ist jedoch möglicherweise auch nicht erforderlich, da es manchmal sinnvoll ist, sie sofort aufzurufen, wobei die Klammern und Parameter nach der Definition der Funktion hinzugefügt werden.
Um eine Funktion zu definieren, Präfix function
Schreiben Sie ggf. den Namen, die Argumente (die an die Funktion übergebenen Parameter) in Klammern und den Code, der ausgeführt wird, wenn die Funktion aufgerufen wird, in geschweifte Klammern.
1
2
3
4
5
|
function doble(numero)
{
var resultado=numero*2;
return resultado;
}
|
Sicherlich wurde die Variable „result“ im vorherigen Beispiel überhaupt nicht benötigt, aber es ist ein guter Vorwand, sich daran zu erinnern Variablenbereich, was wie erwartet funktioniert: Die Variable „result“ existiert nur innerhalb der Funktion „double“. In JavaScript kann auch benutzt werden let
anstelle von var
, um eine Variable auf einen Codeblockkontext zu beschränken (in geschweiften Klammern eingeschlossen), {
y }
)
Als im vorherigen Abschnitt über Objekte gesprochen wurde, fehlte etwas Grundlegendes: Eigenschaften wurden definiert, Methoden jedoch nicht. Wie erwartet, Objektmethoden sind Funktionen, sie haben keinen Namen und werden über den durch die Objektdefinition zugewiesenen (Eigenschafts-)Namen verwendet (aufgerufen).
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”);
}
}
|
Im vorherigen Beispiel gibt es bereits eine Methode, „view_temperature“, die den Wert der Eigenschaft „current_temperature“ über die Konsole anzeigt. Es ist nicht sehr nützlich, vermittelt aber eine umfassendere Vorstellung davon, wie die Definition eines Objekts aussieht JavaScript.
Um auf die Methoden eines Objekts (Funktionen) auf seine Eigenschaften zuzugreifen, verwenden Sie this
, wie im vorherigen Beispiel in Zeile 11, wenn die Eigenschaft „current_temperature“ verwendet wird.
Greifen Sie mit JavaScript auf das Document Object Model (DOM) zu
Bei JavaScript Sie haben Zugriff auf den Inhalt der Webseite, auf der es ausgeführt wird, sowie auf einige Aspekte des Browsers, der diese Seite anzeigt, jedoch nicht auf Systemressourcen. Die Datenstruktur, die die Eigenschaften und Methoden unterstützt, auf die zugegriffen wird JavaScript Teil des Fensterobjekts, insbesondere den Inhalt des Objekts (des Dokuments). HTML) entspricht dem Objekt document
. Obwohl es manchmal aus Gründen der Klarheit verwendet wird, ist es nicht notwendig, window den Methoden oder Eigenschaften voranzustellen, um auf sie zu verweisen. Es reicht beispielsweise aus, „window“ zu verwenden document
, ist es nicht erforderlich, den Namen des Stammobjekts wie in zu schreiben window.document
, solange auf das aktuelle Fenster verwiesen wird.
Die am häufigsten verwendete Form von ein Objekt im Dokument finden HTML Es ist durch die Methode getElementById()
, an den als Argument die ID übergeben wird, die beim Erstellen des Codes angegeben wurde HTML. Aufgrund der Erläuterungen in den vorherigen Abschnitten kann man leicht davon ausgehen, dass Sie auch auf die Komponenten innerhalb des Objekts zugreifen können document
mit Punktsyntax (document.componente
) oder Klammern mit dem Namen (document["componente"]
), die nützlichsten, wie z. B. der numerische Index, schwierig zu verwenden und unpraktisch beim Zugriff auf den Inhalt einer manuell erstellten Webseite.
Mit JavaScript kann Holen Sie sich das Element, das ein anderes Element enthält (Element oder übergeordneter Knoten). Beratung Ihrer Immobilie parentNode
oder Ihr Eigentum parentElement
, der Unterschied besteht darin, dass das übergeordnete Element (parentElement
) des letzten Elements der Zeichenfolge DOM Es ist null (null
) und der übergeordnete Knoten (parentNode
) ist das Dokument selbst (document
).
zu den Inhalt eines Elements ändern HTML, zum Beispiel das eines Etiketts <div>
, Es kann benutzt werden innerHTML
und um seine Eigenschaften zu ändern, können Sie ihm eine andere Klasse zuweisen className
oder ändern Sie seine Eigenschaften individuell mit style
. Es ist nicht unbedingt sinnvoll, den von einem Element auf der Webseite angezeigten Stil zu konsultieren style
da es von mehreren Faktoren abhängen kann oder einfach nicht explizit angegeben wurde. Um den Stil eines Elements zu überprüfen, das letztendlich auf der Webseite angezeigt wird, wird die Methode getComputedStyle verwendet.
Zu einem Dokumentelement HTML Ihm können mehrere Klassen zugewiesen werden, um sein Aussehen und Verhalten zu bestimmen Verwalten Sie die Liste der Klassen eines Objekts von JavaScript zurückgegriffen werden kann classList
das bietet die Methoden add
um eine neue Klasse zur Liste hinzuzufügen, remove
es zu entfernen, toggle
um es zu ersetzen oder den Inhalt der Klassenliste eines Elements zu konsultieren item
und contains
, die die Klasse zurückgibt, die eine bestimmte Position in der Liste einnimmt, und einen Wert true
o false
ob eine bestimmte Klasse auf der Liste steht oder nicht.
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”)
}
|
Im vorherigen Beispiel befindet es sich bei getElementById
das Objekt, das Sie manipulieren möchten (ein Element). <div>
seine id
), vor Änderung des Erscheinungsbildes wird der Inhalt durch Zuweisen mit gelöscht innerHTML
eine leere Textzeichenfolge, wird ihr eine neue Klasse zugewiesen className
und sein Stil wird mit modifiziert style
abhängig vom Wert des Inhalts (Temperatur), ggf. Veränderung der Farbe durch die Eigenschaft color
. Sobald der Aspekt festgelegt ist, wird der Wert erneut mit geschrieben innerHTML
.
Im zweiten Teil des obigen Beispiels (Zeilen 9 bis 19) wird auf ein Codeelement zugegriffen HTML mit der Syntax document[]
und das Grundstück id
des Elements, um seine Klassenliste mit der Methode zu ändern classList.remove()
und mit der MethodeclassList.add()
, basierend auf dem Ergebnis mehrerer Abfragen, die in bedingten Ausführungen durchgeführt werden und anhand derer sie verglichen werden classList.contains()
.
Wann wird es gehen sich auf ein Element beziehen HTML varias Mal im gesamten Code JavaScript, es ist ein bisschen effizienter, es einer Variablen zuzuweisen oder verwenden Sie seinen Index anstelle des Namens, da Sie andernfalls die Methode verwenden würden, die Sie verwenden würden JavaScript Um sie jedes Mal zu erhalten, müsste nach ihrem Namen gesucht werden, was etwas mehr Zeit in Anspruch nimmt, als wenn auf eine Variable zugegriffen würde.
zu Fügen Sie dem Dokument neue Objekte hinzu HTML, können sie zunächst mit der Methode erstellt werden createElement
de document
und integrieren Sie sie später in die übrigen Elemente an der Stelle des Baums, die erforderlich ist appendChild
. Um ein Objekt zu erstellen XML, wie Objekte SVG die wir zum Zeichnen des Diagramms der IoT-Sensoren verwenden, können Sie verwenden createElementNS
(NS für Namensraum). Wie bereits erläutert, als wir über das Format gesprochen haben SVG, der Namespace, der ihm entspricht (für die aktuelle Version). http://www.w3.org/2000/svg
, an die übergeben werden soll createElementNS
als Argument zusammen mit dem Elementtyp, svg
, in diesem Fall.
Eine als Alternative innerHTML
um Text als Inhalt zu einem Dokumentelement hinzuzufügen HTML ist die Methode createTextNode()
Objekt document
. Mit dieser Alternative können Sie neuen Text erstellen (auf den später zugegriffen wird, wenn er einer Variablen zugewiesen wird), der mit der Methode in den Objektbaum eingebunden wird appendChild()
. Als als Alternative appendChild()
, das den neuen Inhalt an das Ende dessen anfügt, was bereits in dem Knoten vorhanden ist, zu dem er hinzugefügt wird, können Sie verwenden die Methode insertBefore()
, wodurch ein neues Objekt vor einem vorhandenen hinzugefügt wird. Tragen insertBefore()
statt appendChild()
stellt eine Methode bereit, die beispielsweise dazu dient Sortieren Sie neue Objekte vor vorhandenen wenn ein Element vor einem anderen stehen muss (z. B. in einer Liste) oder eine grafische Struktur überdecken oder überdecken muss, in der es Elemente gibt, die näher am Vordergrund oder Hintergrund liegen.
Reagieren Sie mit JavaScript auf Ereignisse
Wenn der Weg von Verwenden Sie eine Webseite als Container für IoT-verbundene Sensordiagramme es wurde benutzt onload
Auf dem Etikett <body>
um mit dem Zeichnen des Diagramms zu beginnen. Diese Eigenschaft ist den Codeobjekten zugeordnet HTML, bezieht sich auf Geschehen JavaScript. Wie bereits erläutert, führt es eine Funktion aus, wenn die Seite geladen wurde. Obwohl es mit dem Code in Verbindung gebracht wurde HTML Um es besser im Gedächtnis zu behalten, hätte es in den Code geschrieben werden können JavaScript als body.onload=dibujar;
siendo dibujar
Der Name der Funktion, die beim Laden der Webseite gestartet werden soll.
In den neuesten Versionen von JavaScript Ereignisse können mit Funktionen verknüpft werden addEventListener
mit dem Format objeto.addEventListener(evento,función);
oder die Syntax verwenden objeto.evento=función;
was auch in älteren Implementierungen funktioniert. Um die mit dem Ereignis verknüpfte Funktion aufzuheben, müssen Sie Folgendes tun: removeEventListener
welches das gleiche Format hat wie addEventListener
.
JavaScript Es ist in der Lage, auf eine Vielzahl von Ereignissen zu reagieren, die auf einer Webseite auftreten können. Es kann beispielsweise erkennen, wann auf ein Element geklickt wird HTML mit onmousedown
, oder wenn mit geklickt wird onclick
, wenn eine Taste mit gedrückt wird onkeydown
, indem Sie die Bildlaufleiste mit betätigen onscroll
. Für unseren Zweck reicht es aus, wenn wir es tun Erkennen Sie das Laden der Seite mit onload
und seine Größenänderung mit onresize
. Wir werden diese Ereignisse mit den Objekten verknüpfen body
y window
Restaurants DOM jeweils. Der erste kann im Code zugewiesen werden HTML, wie gesehen und die zweite im Code JavaScript innerhalb der von der ersten aufgerufenen Funktion und mit dem Format window.onresize=redimensionar;
siendo redimensionar
Die Funktion, die jedes Mal aufgerufen wird, wenn sich die Fenstergröße ändert.
Nach einem bestimmten Zeitintervall ausführen
JavaScript hat zwei Ressourcen für aufgeschobene Ausführung: setTimeout
, die eine Funktion nach einem Zeitintervall ausführt und setInterval
die in jedem bestimmten Zeitintervall eine Funktion ausführt. Beide Methoden benötigen als Parameter (1) die aufgerufene Funktion und (2) das in Millisekunden ausgedrückte Zeitintervall. Um ihren Betrieb zu stoppen, können Sie das von diesen Funktionen zurückgegebene Ergebnis Variablen zuweisen und sie als Argument an übergeben clearTimeout
oa clearInterval
wenn Sie sie nicht erneut aufrufen möchten (oder wenn Sie nicht möchten, dass sie zum ersten Mal ausgeführt werden) setTimeout
o setInterval
jeweils.
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
}
|
Im vorherigen Beispiel wird die Methode vorgestellt alert
welches zur Anzeige eines Warnschildes dient. Obwohl es in der Vergangenheit weit verbreitet war, ist es derzeit fast aus dem Code verbannt JavaScript weil es so aggressiv (aufdringlich) ist, die Webseite mit einem Dialogfeld zu überdecken.
In einem Programm, das für a geschrieben wurde Mikrocontroller einer Kleinserie (wie auf dem Teller). Arduino Uno) ist es üblich, globale Variablen zu verwenden, wie im vorherigen Beispiel in JavaScript, da der Code kurz und nicht besonders verwirrend ist, weil die Funktionen häufig ad hoc implementiert werden und weil die Verwendung globaler Variablen eine sehr einfache und intuitive Vorhersage der Speichernutzung ermöglicht, was in Systemen mit wenigen Ressourcen von entscheidender Bedeutung ist. Stattdessen, en JavaScript Es ist üblich, die Verwendung globaler Variablen auf das mögliche Minimum zu reduzieren. weil die Speichernutzung nicht beschleunigt werden muss, da es normal auf einem läuft CPU mit Ressourcen, die denen von a weit überlegen sind MCU, da es wahrscheinlich mit viel Code von Drittanbietern koexistiert, mit dem es ohne Beeinträchtigung arbeiten muss, und da es sich um ein offenes System handelt, kann der zukünftige Ausführungskontext nicht vorhergesagt werden (das Programm von a Mikrocontroller small seine Operation vollständig bestimmt, ohne weiteren Code hinzuzufügen, sobald es in Betrieb ist) und weil die Dimensionen der Anwendungen das Lesen erschweren könnten, wenn der Code seine Operation nicht kapselt und die Methoden so eigenständig wie möglich macht.
Mathematische Operationen mit dem JavaScript Math-Objekt
Die mathematischen Operationen komplizierterer mathematischer Berechnungen werden im Objekt gruppiert Math
. Dieses Objekt wird direkt verwendet. Es ist nicht erforderlich, es zu instanziieren, um die darin enthaltenen Methoden oder Eigenschaften (Konstanten) zu verwenden.
Math.abs(n)
Absolutwert des Parameters nMath.acos(n)
Arkuskosinus des Parameters n (Ergebnis im Bogenmaß)Math.asin(n)
Arkussinus des Parameters n (Ergebnis im Bogenmaß)Math.atan(n)
Arkustangens des Parameters n (Ergebnis im Bogenmaß)Math.atan2(n,m)
Arkustangens von n/m (Ergebnis im Bogenmaß)Math.ceil(n)
Runden Sie den Parameter auf die nächste ganze Zahl aufMath.cos(α)
Kosinus des Parameters α (α im Bogenmaß)Math.E
e-Nummer (≃2.718281828459045)Math.exp(n)
e auf den Parameter n erhöht: enMath.floor(n)
Runden Sie den Parameter n auf die nächste Ganzzahl abMath.log(n)
Natürlicher Logarithmus (Basis e) des Parameters nMath.LN2
Natürlicher Logarithmus (Basis e) von 2 (≃0.6931471805599453)Math.LN10
Natürlicher Logarithmus (Basis e) von 10 (≃2.302585092994046)Math.LOG2E
Logarithmus zur Basis 2 von e (≃1.4426950408889634)Math.LOG10E
Logarithmus zur Basis 10 von e (≃0.4342944819032518)Math.max(a,b,c,…)
Größter Wert der übergebenen ParameterlisteMath.min(a,b,c,…)
Kleinster Wert der übergebenen ParameterlisteMath.PI
Zahl π (≃3.141592653589793)Math.pow(n,m)
Erster Parameter n auf den zweiten Parameter m erhöht: nmMath.random()
(Fast) Zufallszahl zwischen 0.0 und 1.0Math.round(n)
Runden Sie den Parameter n auf die nächste ganze ZahlMath.sin(α)
Sinus des Parameters α (α im Bogenmaß)Math.sqrt(n)
Quadratwurzel des Parameters nMath.SQRT1_2
Quadratwurzel von 1/2 (≃0.7071067811865476)Math.SQRT2
Quadratwurzel aus 2 (≃1.4142135623730951)Math.tan(α)
Tangens des Parameters α (α im Bogenmaß)
Laden Sie Daten vom Server mit AJAX
Die Methode zum Zeichnen der im IoT gespeicherten Informationen besteht darin, die Daten von Zeit zu Zeit vom Server zu laden und das Diagramm, mit dem sie dargestellt werden, neu zu zeichnen. Um Daten vom Server auszulesen, wird Technologie eingesetzt AJAX (Asynchrones JavaScript und XML) durch ein Objekt XMLHttpRequest
de JavaScript. Das Zeichnen des Datendiagramms erfolgt durch Wiederverwendung eines Objekts SVG was bereits im Code steht HTML und das enthält ein Diagramm, dessen Koordinaten geändert werden, damit sie den neu geladenen Daten entsprechen.
Im Beispiel dieses Vorschlags wird zusätzlich zur Aktualisierung der Zeichnung auch ein Text auf der Webseite aktualisiert, der für jedes Diagramm das Datum und den Wert der letzten gemessenen Daten anzeigt.
Auf der Serverseite gibt es eine Datenbank, die die Informationen enthält dass die mit dem IoT verbundenen Sensoren überwacht haben. Diese Datenbank wird von der Objektanforderung gelesen XMLHttpRequest
Antworten mit darin kodierten Informationen JSON-Format, obwohl der Name der verwendeten Methode auf einen Zusammenhang mit dem Format schließen lässt XML.
Im ersten polaridad.es-Tutorial zum IoT-Datenspeicher Sie sehen ein Beispiel einer Infrastruktur zur serverseitigen Verwaltung der Informationen, die von Geräten bereitgestellt werden, die mit dem Internet der Dinge verbunden sind. In dieser Artikelserie wird ein Server als Ressource verwendet Apache von dem aus Sie die Programmiersprache nutzen können PHP um auf eine Datenbank zuzugreifen MySQL o MariaDB. Auf Servern, die zur IoT-Unterstützung eingesetzt werden, findet man häufig Datenbanken MongoDB (NoSQL) und die Programmiersprache JavaScript auf Node.js als Software-Infrastruktur.
Die nächste Funktion ist dafür verantwortlich, die neuesten Daten von einem der Sensoren vom Server anzufordern. Beim Funktionsaufruf wird das Objekt als Argument verwendet JavaScript das die gezeichneten Daten unterstützt. Stellt derselbe Graph mehrere Werte dar, beispielsweise um visuell nach einer Korrelation zu suchen, kann eine Anfrage an den Server gestellt werden, mehrere gleichzeitig zurückzugeben, was aufgrund der Funktionsweise des Servers eine optimalere Methode ist. Protokoll HTTP.
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);
}
|
In der dritten Zeile des vorherigen Beispiels wird die an den Server gerichtete Abfrage vorbereitet, in der das Argument „zone“ übergeben wird, dessen Wert der Name oder Code des überwachten Ortes ist, da Informationen darüber vorliegen Bereich kann in derselben Datenbank koexistieren. Verschiedene Sensoren (z. B. Thermometer, die die Temperatur in verschiedenen Räumen messen). Der an die vorherige Funktion übergebene Parameter, das Objekt mit den Diagrammdaten, soll eine Eigenschaft mit dem Namen des Raums („name_suffix“) enthalten.
Zwischen den Zeilen 7 und 14 des vorherigen Codes Objekt XMLHttpRequest
welches in der Variablen „ajax“ gespeichert ist. Bevor Sie auswählen, wie das Objekt erstellt werden soll, führen Sie eine Suche durch window
wenn XMLHttpRequest
war nicht verfügbar (was in alten Versionen des Microsoft-Explorers passiert ist und obwohl es weit zurückliegt, dient es als Beispiel für Alternativen zum Erstellen des Objekts mithilfe der (nativeren) Syntax. Object.create
o new
, ähnlich wie bei anderen objektorientierten Sprachen.
Um die Antwort sofort verwalten zu können, wird in den Zeilen 15 bis 26 der Code, der sie verarbeitet, vorbereitet, bevor die Anfrage an den Server gestellt wird.
Der Weg von die Abfrage durchführen HTTP zum Server besteht aus eine Verbindung öffnen mit open
Angabe von Typ und Seite (optional Benutzername und Passwort), Bereiten Sie die Überschriften vor des Protokolls mit setRequestHeader
y Senden Sie die Anfrage mit send
. Der Header HTTP Content-length
Sie müssen die Länge der Abfrage (Anzahl der Zeichen) kennen, die anhand berechnet wird length
.
Wenn die Anfrage AJAX bereit ist, wird die mit dem Ereignis verknüpfte Funktion ausgeführt onreadystatechange
. Anstatt eine Funktion zuzuweisen, wird im vorherigen Beispiel spontan eine anonyme Funktion definiert, die den Empfang der vom Server eingehenden Daten verwaltet. Zunächst wird in Zeile 18 überprüft, ob der Status der Anfrage „fertig“ ist, was dem Wert entspricht 4
des Eigentums readyState
, dass der Status „OK“ ist Protokoll HTTP (Code 200
), die bei der Unterkunft erhältlich sind status
und dass die Daten, die angekommen sind, sind JSON-Format, Beratung der Immobilie responseType
.
Sobald überprüft wurde, dass der Status der Antwort wie erwartet ist, in Zeile 20 des vorherigen Beispiels erstellt ein Objekt mit dem Ergebnis und konvertiert den Text JSON. Die Antwort sieht ein zurückzugebendes Datum vor. Dadurch können wir sehen, ob das vom Server gesendete Ergebnis bereits zuvor im Diagramm dargestellt wurde, was in Zeile 21 überprüft wird. Wenn die Daten neu sind, wird in Zeile 23 die Funktion angezeigt ist dafür verantwortlich, das Diagramm mit den neuen Informationen neu zu zeichnen.
Der Gedanke beim Vorschlag dieser Lesemethode besteht darin, dass die Daten sehr häufig aktualisiert werden. Wenn die präsentierten Informationen einem längeren Zeitraum entsprechen (z. B. die Temperaturen eines Tages oder einer Woche), kann eine erste Anfrage implementiert werden, die alle verfügbaren Daten sammelt, und dann eine, ähnlich der im Beispiel, die diese innerhalb dieser aktualisiert der Periodenkorrespondent.
Generieren Sie Zufallsdaten zum Testen
Wenn die gesamte Server- und Client-Infrastruktur bereit ist, ist eine Funktion wie die im vorherigen Abschnitt dafür verantwortlich, die Daten zu lesen und damit das Diagramm zu zeichnen In der Testphase kann es praktischer sein, Zufallszahlen innerhalb eines kontrollierten Bereichs zu verwenden um zu sehen, ob der geschriebene Code korrekt ist. Die folgende Funktion kann als Beispiel zum Abrufen von Daten beim Erstellen der endgültigen Anwendung dienen.
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);
}
|
Anstatt die Informationen aus einer Datenbank zu lesen, werden sie im obigen Beispiel zufällig generiert und an die Funktion übergeben, die für das Zeichnen des Diagramms verantwortlich ist. Die erfundenen Daten sind ein Vektor, der aus einem Datum, ausgedrückt als Wert in Millisekunden, dem Zeitpunkt der Aufzeichnung der Sensorinformationen und den überwachten Daten, die zwischen einem Maximalwert und einem Minimalwert liegen, gebildet wird.
In diesem Beispiel kann die Generierung eines Datums bis zu einer Sekunde (1000 Millisekunden) gegenüber dem Datum zum Zeitpunkt der Erfindung verzögert werden. Als Math.random()
erzeugt eine Zahl zwischen 0.0 und 1.0, ihre Multiplikation mit 1000 ergibt eine Zahl zwischen 0 und 1000, die dann in eine Ganzzahl umgewandelt wird. Auf die gleiche Weise erhält man den Wert, indem man die Zufallszahl mit dem Bereich (Maximum minus Minimum) multipliziert und das Minimum addiert.
Zeichnen Sie das Diagramm der IoT-Sensoren mit einem SVG-Diagramm
Da wir gesehen haben, wie wir die Werte, die wir darstellen möchten (im Beispiel die Temperatur), und ihren zeitlichen Ort erhalten, die zusammen in Form von Koordinaten ausgedrückt werden können, zeigt das folgende Beispiel eine Funktion zum Zeichnen eines Pfads das diese Punkte verbindet, und optional einen farbigen Bereich, der durch diese Linie oben begrenzt wird. Das Ergebnis würde wie das folgende Bild aussehen.
Die horizontale Achse (X) des Diagramms stellt die Zeit dar und die vertikale Achse (Y) die Werte, die die mit dem IoT verbundenen Sensoren überwacht haben. Das horizontale Intervall beträgt einige Sekunden, da in diesem Vorschlag die Grafik sehr häufig (z. B. jede Sekunde) aktualisiert wird, um nahezu Echtzeitinformationen über den Zustand der Sensoren bereitzustellen.
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
}
|
Im vorherigen Code gibt es zwei interessante Aspekte, erstens die Berechnung, die dies ermöglicht Passen Sie den dargestellten Wertebereich an und zweitens die Immobilienbau d
was die Koordinaten der Punkte auf dem Layout angibt (path
).
Um den dargestellten Wertebereich anzupassen, werden diese von einem Minimum aus verschoben und so skaliert, dass die sichtbare Größe der Größe des Diagramms entspricht. Im Fall der Zeit wird der Offset ermittelt, indem der Bereich, den Sie anzeigen möchten, von der längsten Zeit (dem Datum und der Uhrzeit, die der aktuellen am nächsten liegen) (im Beispiel 20 Sekunden) subtrahiert wird. Die Verschiebung der Temperaturwerte entspricht dem unteren Bereich (ein Grad) minus dem niedrigsten Wert, sodass die unten gezeigten Daten dem niedrigsten zulässigen Wert am ähnlichsten sind, jedoch einen Spielraum lassen, der es uns ermöglicht, diejenigen zu schätzen, die dies tun . passieren
Der Koeffizient, der die Zeitwerte multipliziert, um die horizontalen Koordinaten des Diagramms zu erhalten, wird erhalten, indem die Gesamtbreite des Diagramms (im Beispiel 100 Einheiten) durch den dargestellten Zeitbereich (im Beispiel 20 Sekunden) dividiert wird. Um den Koeffizienten mit den skalaren Temperaturwerten zu erhalten, muss berücksichtigt werden, dass der dargestellte Bereich von einer Spanne unter dem Mindestwert bis zu einer Spanne über dem Höchstwert reicht, in beiden Fällen ein Grad. Auf diese Weise ergibt sich der vertikale Skalierungskoeffizient aus der Division der Höhe des Diagramms (im Beispiel 100 Einheiten) durch den Maximalwert minus dem Minimalwert plus dem oberen und unteren Rand. Da sich diese Werte bei Minustemperaturen vollständig entwickeln könnten, verwenden wir Math.abs()
den absoluten Wert der Differenz zu verwenden.
Die Eigenschaft d
Objekt path
Es wird durch die Verkettung der Koordinaten der Punkte in einem Text erstellt. Jedem Koordinatenpaar ist ein Code vorangestellt SVG L
, der eine Linie von der aktuellen Position zu einem durch die Koordinaten angegebenen Absolutwert zeichnet. Die X- und Y-Werte werden durch Kommas und jede Operation getrennt SVG wird durch ein Leerzeichen vom nächsten getrennt.
Um das Layout zu starten, verwenden Sie den Code M
(zu einer absoluten Koordinate bewegen). Beim geschlossenen und gefüllten Plot beginnt man unten rechts, beim offenen Plot, der das Datenprofil zeichnet, beginnt man mit dem zuletzt dargestellten Wert (dem aktuellsten). Um das geschlossene Layout fertigzustellen, wird der Code verwendet Z
Als letzten Punkt wird derjenige hinzugefügt, der den gleichen X-Koordinatenwert wie der letzte Punkt der Linie hat, und als Y-Koordinate der kleinste dargestellte Wert.
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
);
}
|
In diesem Beispiel die Funktion dibujar_grafico()
, der Aufruf beim Laden der Seite, ruft die zu testenden Anfangswerte ab (nicht den letzten Echtzeitwert) und bereitet den Bereich vor, in dem die Daten gerendert werden: 20 Sekunden (20000 ms) horizontal und 15 °C innen vertikal von -5°C bis +10°C mit einem Grad oberen und unteren Rand. Rufen Sie zweimal an actualizar_grafico()
, im ersten Durchgang true
als Argument, das angibt, dass das Diagramm geschlossen werden soll, um einen gefüllten Bereich darzustellen, und beim zweiten Aufruf wird es übergeben false
die Grenze ziehen. Jeweils das Objekt path
„modifiziert“ ist diejenige, die das entsprechende Erscheinungsbild hat, im ersten Fall mit einer Füllung und ohne Rand und im zweiten Fall mit einer bestimmten Linienstärke und ohne Füllung.
Die Funktion actualizar_grafico()
an einem Objekt arbeiten SVG welches den folgenden Code als Container verwendet HTML. Das Objekt SVG enthält zwei Pfade, einen zum Zeichnen der Linie und einen zum Zeichnen des gefüllten Bereichs. Beim Laden der Webseite aus dem Element <body>
die vorherige Funktion wird automatisch aufgerufen, dibujar_grafico()
dank der Veranstaltung 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>
|
In Zeile 10 des Codes HTML Oben ist im Stil beispielsweise eine Breite von 820 px und eine Höhe von 150 px festgelegt (was in der finalen Version bei einer Klasse und einem Dokument sinnvoll sein wird). CSS). Es erscheint seltsam, dass die Zeilen 13 und 14 die Größe des Objekts definieren SVG etwa 100 % Breite und Höhe (was am besten zu den Abmessungen des Fensters passt, 100×100). Wie bereits erwähnt liegt der Grund dafür darin, immer mit bekannten Maßen zu arbeiten und die dargestellten Werte daran anzupassen. Die anderen Alternativen wären, jedes Mal den Raum des Diagramms zu berechnen und dann die Werte neu anzupassen oder feste Abmessungen für das Diagramm zu erzwingen, an die sich das Dokument halten muss.
Ich habe mich für ein Diagramm entschieden, dessen Abmessungen sich je nach Code ändern HTML, ist es notwendig, die Immobilie einzubeziehen vector-effect
mit dem Wert non-scaling-stroke
um zu verhindern, dass die Linienstärke verformt wird, wenn das Diagramm nicht die gewählten 1:1-Proportionen auf der Webseite beibehält, auf der es angezeigt wird, wie es im vorherigen Vorschlag der Fall ist.
Um das Diagramm zu „zuschneiden“ und nur den von Ihnen ausgewählten Bereich anzuzeigen, verwenden Sie viewBox
. In diesem Fall haben wir uns dafür entschieden, den Teil des Diagramms anzuzeigen, der bei 0,0 beginnt (obere linke Ecke) und nach unten und rechts 100 x 100 misst. Der Teil der Zeichnung, der sich in Koordinaten mit negativen Werten oder größer als 100 befindet, wird nicht auf der Webseite angezeigt, selbst wenn er im Objekt vorhanden ist SVG
Fügen Sie der SVG-Zeichnung neue Elemente hinzu
Im vorherigen Beispiel die Funktion actualizar_grafico()
Verwenden Sie ein Layout SVG zu dem der Eigentümer wechselt d
, was die Koordinatenkette ausdrückt. Die Alternative wäre, bei jedem Neuzeichnen das gesamte Objekt zu erstellen. Der Vorteil der ersten Option besteht darin, dass das grafische Erscheinungsbild (z. B. Dicke oder Farbe) im Code definiert wird HTMLDie Einschränkung besteht darin, dass die Objekte zuvor erstellt werden müssen.
Um SVG-Objekte zu erstellen, verwenden Sie createElementNS()
, was das Einbeziehen der ermöglicht Namensraum. Im folgenden Beispiel wird ein neues Textobjekt erstellt (text
) und ist einem Element zugeordnet SVG was bereits im Code vorhanden ist HTML der Website. Sobald das neue Element erstellt ist, werden dessen Eigenschaften mit zugewiesen setAttribute()
und wird ergänzt SVG mit 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]);
|
Ändern Sie die Proportionen der Zeichnungselemente
Wenn Sie versucht haben, mit der Funktion im Beispiel im vorherigen Abschnitt zu beschriften, werden Sie feststellen, dass der Text deformiert erscheint, wenn die Proportionen des Objekts auf der Webseite (width
y height
Von Code HTML) ist nicht gleich dem der dargestellten Fläche (viewBox
). Um die Proportionen anzupassen, ist es notwendig, die Maße des Objekts zu kennen SVG Hierfür können Sie den Stil des Objekts oder des Containers konsultieren HTML, wenn das Objekt SVG dieses Eigentum übertragen. Eigentum zuweisen transform
zu Objekten SVG die vom Anteil abhängen, kann die Verformung durch Anwenden einer Skalierungsoperation korrigiert werden scale()
wobei sich der Koeffizient in X von dem in Y unterscheidet.
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 ermöglicht die Gruppierung mehrerer Objekte zu einem neuen Verbundelement, das auch Eigenschaften unterstützt, wie einfache Objekte. Um dieselbe Transformation auf eine Reihe von Objekten auf einmal anzuwenden, anstatt auf jedes Objekt einzeln, können Sie sie entsprechend dieser Ressource gruppieren und eine einzelne Eigenschaft anwenden transform
an alle.
Wie bereits erläutert, als wir darüber gesprochen haben SVG-Format, werden die Elemente einer Gruppe in die Beschriftungen eingeschlossen <g>
y </g>
. Zum Hinzufügen von JavaScript Elemente zu einer Gruppe SVG wird verwendet, wie im vorherigen Beispiel zu sehen ist, appendChild()
sobald das neue Objekt definiert ist.
Um beim Anwenden von Transformationen einen Ursprung festzulegen, kann die Eigenschaft auf Objekte angewendet werden SVG transform-origin
, dessen Wert die X- und Y-Koordinaten des Punktes sind, von dem aus die Transformation beginnt. Wenn kein Wert für den Ursprung der Transformation angegeben wird (im Webbrowser), wird der Koordinatenmittelpunkt verwendet. Leider ist die Angabe des Verhaltens von Transformationen unter Verwendung einer anderen Quelle als der Standardquelle zum Zeitpunkt des Verfassens dieses Artikels nicht in allen Browsern einheitlich und sollte mit Vorsicht verwendet werden.
Zusammen mit der Skalentransformation mit scale
Es gibt andere, wie zum Beispiel Rotation mit rotation
und die Bewegung mit translate
, die ein Alternative zur grafischen Darstellung: Anstatt neue Koordinaten zu erhalten, können Sie sie in ihrem eigenen Raum darstellen und das Diagramm so transformieren, dass es in das Format passt, in dem Sie sie darstellen möchten.
Fügen Sie Verweise zum Diagramm hinzu
Nachdem nun der Hauptteil des Diagramms durch die Darstellung der Werte mit einem Profil und einer gefüllten Fläche aufgelöst ist, kann es mit Referenzen vervollständigt werden, die das Lesen erleichtern. Als Beispiel beginnen wir mit dem Zeichnen einiger horizontaler Referenzen (Linien), die die maximal und minimal akzeptablen Werte sowie einen gewünschten Wert markieren. Wie erläutert, können Sie die Objekte hinzufügen SVG direkt von JavaScript oder fügen Sie sie manuell in den Code ein HTML und ändern Sie sie später mit 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();
|
Es erscheint logisch, diese horizontalen Verweise mit Text zu kennzeichnen, der den Wert, den sie darstellen, verdeutlicht. Um den Text hervorzuheben, können Sie Rechtecke verwenden, die sich vom Hintergrund und der Grafik abheben. Da die Texte skaliert werden müssen, um die Verformung auszugleichen, können sie alle in einem Objekt gruppiert werden, auf das die Skalierung angewendet wird; Der Hauptvorteil dieser Vorgehensweise besteht darin, dass sie in einem einzigen Vorgang geändert werden können, wenn die Größe des Diagrammcontainers (des Browserfensters) geändert wird und sich das Verhältnis ändert, das durch die Skalierung korrigiert wird.
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();
|
Der obige Beispielcode enthält mehrere interessante Aspekte. Beachten Sie zunächst, dass Konstanten (globale Variablen) verwendet wurden, um das Beispiel für Benutzer, die mit der Programmierung beginnen, lesbarer zu machen. Mikrocontroller en C oder C + +. Wie man später sehen wird, ist die optimale Art und Weise, es einzuprogrammieren JavaScript Es würde Objekte verwenden, die diese Werte und Methoden enthalten würden, die die Referenzen in diesem Beispiel oder das Diagramm im Allgemeinen in einem Produktionssystem verwalten würden.
Andererseits wurden im Zuge der Weiterentwicklung des allgemeineren Codes separate Funktionen entwickelt, die die verschiedenen Koeffizienten berechnen, die die Proportionen des Diagramms korrigieren, um den Text anzupassen proporcion_grafico()
, die Skala der Werte in Abhängigkeit von ihrem Bereich escala()
und einen Korrekturfaktor für Messungen, deren Absolutwert bekannt ist, wie beispielsweise Messungen in Referenzen medida_grafico()
.
Das Lesen dieses Codes sollte helfen, den Kontext zu klären, in dem eine Anwendung wie diese funktioniert, die Grafiken in Echtzeit zeichnet und flexibel sein muss, um in verschiedenen grafischen Kontexten (zumindest in verschiedenen Größen und Proportionen) dargestellt zu werden. Zunächst müssen die Objekte generiert werden SVG, entweder „manuell“ im Code HTML, entweder durch Code JavaScript und in jedem Fall müssen anschließend Verweise auf diese Objekte abgerufen werden, um sie zu manipulieren JavaScript damit neue Diagramme gezeichnet werden können und die Darstellung eines bereits gezeichneten Diagramms an eine Änderung des Mediums, in dem es präsentiert wird, angepasst werden kann.
Eine weitere Referenz, die die Interpretation eines Diagramms erleichtern kann, sind die Punkte, die bestimmte Werte darstellen (die Knoten der Linie). In diesem Beispiel, in dem wir eine einzelne Größe darstellen, ist die Wahl eines Symbols nicht kritisch, aber wenn mehrere verschiedene Werte überlagert werden, um nach Korrelationen zu suchen, ist es interessant, zusätzlich zur Verwendung anderer Ressourcen wie der Farbe zu unterscheiden , indem Sie verschiedene Symbole zeichnen. Die für den Linienknoten verwendeten Grafiken müssen in Größe und Proportion geändert werden, wie dies beispielsweise bei Texten der Fall ist, damit ihre Abmessungen absolut sind und ihre Proportionen auch dann erhalten bleiben, wenn sich die des darin enthaltenen Felds ändern. der Grafik.
Im vorherigen Beispiel haben wir bereits gesehen, wie die verschiedenen Koeffizienten berechnet werden, um die Proportionen der Zeichnung neu zu skalieren und zu korrigieren; Was die Implementierung der Verwaltung der Symbole der Knoten oder Eckpunkte des Diagramms betrifft, könnte eine mögliche Lösung darin bestehen, die Objekte zu speichern SVG in einen Vektor umwandeln und seine Position ändern, wenn das Diagramm durch Lesen eines neuen Werts aktualisiert wird oder wenn es durch Ändern der Containergröße neu gezeichnet wird. Im ersten Fall müsste seine Lage geändert werden und im zweiten Fall sein Verhältnis zum Grundstück transform
und der Wert von scale
. Der folgende Code ist eine Modifikation der Funktion actualizar_grafico()
um die Neupositionierung der Diagrammscheitelpunktsymbole einzuschließen.
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);
}
}
|
An der Funktion vorgenommene Änderungen actualizar_grafico()
um die neue Funktion zu erhalten actualizar_grafico_puntos()
Dies sind diejenigen, die im Code des vorherigen Beispiels hervorgehoben wurden. Zunächst nehmen wir in Zeile 5 einen Vektor von Objekten SVG als Parameter. Dieser Vektor enthält die Symbole, die in den neuen Knoten des Diagramms neu positioniert werden müssen.
In den Zeilen 39 und 40 werden die neuen Koordinaten des Mittelpunkts zugewiesen, cx
y cy
, zu denen der Werte, die dargestellt werden. Wenn das Symbol nicht auf der Mitte basiert, muss wahrscheinlich ein Versatz hinzugefügt werden cx
halbe Breite und Zoll cy
der halben Höhe, um sie exakt auf dem Diagrammknoten neu zu positionieren.
In den Zeilen 57 bis 61 werden die Punkte, die Koordinaten entsprechen, die nicht gezeichnet werden, weil sie vom linken Rand abgeschnitten werden, außerhalb des Diagramms neu positioniert. Die Koordinate von cy
auf Null und das von cx
auf eine beliebige negative Zahl (größer als der Punkt selbst), so dass sie nicht angezeigt wird, wenn sie, wie der linke Teil des Diagramms, durch das Fenster des geschnitten wird SVG.
Verwalten Sie das Diagramm von einem Objekt aus mit JavaScript
Alle bisher erläuterten Operationen können in ein Objekt integriert werden, um das Diagramm mit einem Stil zu verwalten, der typischer für die neuen Versionen von ist JavaScript. Diese Implementierungsalternative hat den zusätzlichen Vorteil, dass sie die Einbindung mehrerer Diagramme mit unterschiedlichen Werten auf derselben Webseite vereinfacht.
Bevor wir die Implementierung besprechen, werfen wir einen Blick auf die gängigsten Methoden zum Erstellen von Objekten JavaScript und einige Besonderheiten der Funktionen, die sich auf den Vorschlag zum Zeichnen von IoT-Sensorgrafiken auswirken.
Es wurde bereits erklärt, dass die neue Art der Objekterstellung in JavaScript (verfügbar seit Version 5 von ECMAScript) besteht aus der Verwendung Object.create
, an die man sich gewöhnen sollte, anstelle des „Klassikers“ zu verwenden new
, was natürlich immer noch korrekt funktioniert, obwohl sein Zweck eher darin besteht, den Stil von Sprachen mit klassenbasierten Objekten zu simulieren (JavaScript basiert die Erstellung von Objekten auf Prototypen) als eine funktionierende Alternative.
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();
}
|
Mit dem vorherigen Code können Sie sich die Unterschiede zwischen der Erstellung der Objekte merken Object.create
oder new
. Es dient auch dazu, die Funktion hervorzuheben, mit der das Objekt erstellt wird new
kann sich an einer beliebigen Stelle im Code befinden. Das Objekt muss bereits vorhanden sein, bevor es instanziiert werden kann Object.create
(ES5_Object-Objekt ist keine Funktion).
In den Zeilen 3 und 4, um einen Standardwert für die Eigenschaften in der Funktion festzulegen, mit der das Objekt erstellt wird new
, jeder Eigenschaft wird der Wert des entsprechenden Arguments zugewiesen oder (||
), wenn keine Argumente übergeben wurden, also undefiniert sind (undefined
), da dieser Umstand als bewertet wird false
, wird der Standardwert zugewiesen.
Der Kontext, in dem eine Funktion ausgeführt wird JavaScript wirft zwei Probleme auf, die es zu beachten gilt und die auch verwirrend sein können, wenn man diese Programmiersprache verwendet, nachdem man mit anderen zusammengearbeitet hat, wie z C o C + +, in unserem Fall. Der Kontext umfasst die im Bereich der Funktion definierten Variablen (und die globalen), was übrigens ein interessantes Konzept aufwirft, die „Abschlüsse“, die einen gesamten Programmierstil festlegen JavaScript. Allerdings war damit zu rechnen this
, das sich auf das Objekt bezieht, wenn es innerhalb des Codes verwendet wird, der es definiert, der Ausführungskontext, in dem es definiert wurde, bleibt erhalten, aber der verwendete Kontext ist der Kontext, aus dem die Funktion aufgerufen wird. Dieses Verhalten ist in den meisten Fällen transparent, es gibt jedoch zwei Umstände, unter denen es verwirrend sein kann: eine Funktion, die in einer anderen Funktion definiert ist, und eine Methode, die von einem Ereignis des Objekts aufgerufen wird. 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
*/
|
Beim Ausführen des vorherigen Codes wird der kommentierte Text am Ende in der Konsole angezeigt. Die beiden markierten Linien spiegeln Verhalten wider, das verwirrend sein kann: den Funktionsausführungskontext probar_dentro()
nicht probar()
, wie zu erwarten war, aber window
, das die globalen Variablen und nicht die gleichnamigen Eigenschaften anzeigt. Wenn Sie dieses Verhalten nicht wünschen, erstellen Sie einfach eine Variable in der Funktion der höchsten Ebene und weisen Sie sie zu this
, wie im folgenden Code.
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
*/
|
Zur Steuerung des Ausführungskontexts, wenn eine Methode von einem Ereignis aufgerufen wird window
, beispielsweise durch Größenänderung des Browserfensters, eine weitere Besonderheit von JavaScript: die Möglichkeit, „Funktionsfabriken“ zu programmieren, also Funktionen, die andere Funktionen generieren und diese mit zurückgeben 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
|
Im obigen Beispielcode die Methode llamar()
der Objekte Contexto
Es erledigt die Arbeit nicht, sondern gibt eine anonyme Funktion zurück, die sich darum kümmert. Um zu überprüfen, ob alles wie erwartet funktioniert, gibt es eine globale Variable mit demselben Namen wie die Eigenschaft, die die Funktion in der Konsole anzeigt. Bei korrektem Kontext wird der Wert der Eigenschaft angezeigt und nicht der der globalen Variablen.
JavaScript Versuchen Sie, die Semikolons zu korrigieren, die wir am Ende der Sätze weglassen. Dies ermöglicht einen entspannten Schreibstil, ist jedoch ein zweischneidiges Schwert, mit dem vorsichtig umgegangen werden muss. Um die unerwünschten Auswirkungen zu vermeiden, die dadurch bei Ausdrücken entstehen, die mehrere Zeilen einnehmen, können Sie in den meisten Fällen Klammern verwenden oder der Art und Weise voranstellen JavaScript wird den Code interpretieren; Deshalb enthält Zeile 8 des Beispiels function
dahinter return
, wenn ich eine andere Zeile verwendet hätte, wäre die Bedeutung ganz anders. Meiner Meinung nach besteht die am besten lesbare Lösung darin, eine Zwischenvariable (verzichtbar) zu verwenden, wie in der folgenden Version; Sobald das Verhalten verstanden ist, liegt die Entscheidung natürlich beim Programmierer.
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);
|
Im gleichen Sinne wie die Auswertung eines Ausdrucks als Funktion, d. h. Rückgabe einer Funktion und nicht des Werts, den die Funktion zurückgibt; in Zeile 21 des letzten Beispiels (es war in Zeile 19 des vorherigen Beispiels) endet es mit clearInterval
die mit aufgerufene Funktion setInterval
. Damit es 30 Sekunden lang wirkt, wird der Stopp mit verzögert setTimeout
, was wiederum eine Funktion als erstes Argument benötigt; um die Ausführung als Parameter zu liefern clearInterval
mit der Variablen, die den periodischen Aufruf enthält (und nicht mit der Funktion). clearInterval
) ist der Zweck der anonymen Funktion in der letzten Zeile.
Die Wahl zwischen dem Schreiben des Codes, der die Funktionsdefinition integriert, kompakter (wie in Zeile 21) oder der Verwendung einer meiner Meinung nach besser lesbaren Hilfsvariablen (wie in den Zeilen 19 und 20), variiert kaum in der Leistung und hängt mehr von Stil und Lesbarkeit ab Wartung.
Um den Code zu testen, bevor Daten auf dem Server vorliegen, können Sie einen Generator von Zufallswerten im gewünschten Bereich verwenden oder Tabellen mit kontrollierten Werten erstellen, die den Betrieb unter den gewünschten Bedingungen simulieren. Das folgende Beispiel verwendet einen einfachen Datengenerator über den gesamten Bereich, weshalb sie etwas übertrieben erscheinen.
Zum Testen können Sie Laden Sie den vollständigen Code des Beispiels herunter gebildet durch eine geschriebene Webseite HTML, der Stil CSS und der Code JavaScript. Letzteres ist am relevantesten, da die anderen Komponenten nur minimale Unterstützung bieten, sehr vereinfacht sind und in den Artikeln in den entsprechenden Abschnitten viel weiter entwickelt werden.
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);
}
|
Geben Sie Anmerkung