Hasilkan dan modifikasi grafik data SVG dari sensor yang terhubung ke IoT dengan JavaScript
Di bagian terakhir dari rangkaian artikel tentang menggambar grafik dengan data dari sensor yang terhubung ke Internet of Things, saatnya berbicara tentang cara membuat atau memodifikasi dengan JavaScript gambar dalam format SVG dan beberapa elemen HTML yang berfungsi sebagai wadah atau menyajikan informasi pelengkap pada grafik.
Target pengguna tutorial ini seharusnya membentuk profil elektronik dan pemrograman komputer. mikrokontroler, mereka mungkin tidak familiar dengannya HTML, CSS o SVG; Oleh karena itu, pada bagian sebelumnya telah dilakukan pengenalan singkat tentang bahasa atau teknologi terkait. Pada bagian terakhir ini pendekatannya sedikit berbeda, karena pembaca pasti tahu cara memprogramnya, bisa saja menggunakan bahasa tersebut C + + itu, seperti JavaScript, berbagi sintaks dasar dengan C dan ini dapat digunakan sebagai referensi untuk melewatkan sebagian besar konsep dasar pemrograman dan dengan demikian fokus pada perbedaan dan penggunaan spesifik yang menarik minat kita untuk membuat grafik sensor di IoT.
Namanya memberi petunjuk tentang perbedaan pertama: JavaScript Ini adalah bahasa pemrograman naskah (tanda hubung) dan dengan demikian, memang demikian ditafsirkan, tidak perlu mengkompilasinya; konteks di mana naskah (browser web, misalnya) akan membaca, menerjemahkan, dan melaksanakan perintah. Tepatnya, dalam banyak kasus ada a kompilasi waktu proses (JIT), tetapi untuk proses penulisan kode JavaScript Itu tidak mempengaruhi kami, kami cukup menulis kodenya dan itu bisa berfungsi.
Namanya juga mengandung kebingungan pertama: JavaScript tidak memiliki hubungan sedikit pun dengan Jawa. Awalnya, saat dikembangkan Netscape untuk browsernya, pertama-tama disebut Mocha dan kemudian LiveScript yang tidak terlalu membingungkan. Setelah penerapannya berhasil di browser, dan melampauinya, ini distandarisasi sebagai ECMAScript (Untuk ECMA-262, versi 6 pada saat penulisan) menjadi netral terhadap browser yang mengimplementasikannya. Saat ini juga ada standarnya ISO dari versi 5, 2011 (ISO / IEC 16262: 2011 pada saat menulis artikel)
Variabel, tipe data dasar dan objek dalam JavaScript
Berbeda dengan yang terjadi misalnya di C + +, en JavaScript tipe data tidak disertakan saat mendeklarasikan variabel dan juga tipe yang terkait dengan suatu variabel tidak tetap, dimungkinkan untuk menetapkan nilai dari tipe yang berbeda selama eksekusi program.
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
|
Pada contoh sebelumnya, variabel "benda" telah dideklarasikan (tanpa menunjukkan tipe datanya) kemudian data dengan tipe berbeda ditetapkan dan dikonsultasikan dengan typeof
tipe itu JavaScript yang telah dia tafsirkan. Untuk men-debug kode Anda dapat menulisnya di konsol inspektur browser web (yang tidak akan mempengaruhi presentasi web) dengan console.log()
.
Untuk memaksa konversi data ke tipe tertentu, terutama teks ke numerik, Anda dapat menggunakan fungsi seperti parseInt()
o parseFloat()
yang masing-masing dikonversi menjadi bilangan bulat atau angka floating point. Konversi sebaliknya dapat dilakukan dengan String()
, meskipun hal ini sepertinya tidak diperlukan karena konversi otomatis biasanya sudah cukup. Dengan parseFloat()
Misalnya, Anda bisa mendapatkan nilai properti halaman web, seperti lebar atau tinggi suatu objek, yang mencakup satuan; Dengan cara ini, ekspresi parseFloat("50px");
akan mengembalikan 50, nilai numerik, sebagai hasilnya.
En JavaScript tidak ada perbedaan antara tanda kutip ganda dan tunggal; Tipe data dalam kedua kasus adalah string
, dan masing-masing dapat menyertakan yang lain tanpa memerlukan kode escape.
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
|
Pada contoh sebelumnya terlihat bahwa suatu variabel, ketika sudah dideklarasikan (ada) tetapi belum diberi nilai apapun, mengandung tipe data yang tidak terdefinisi (undefined
). Objek yang belum ditetapkan memiliki nilai null
; Artinya, objek itu ada, tetapi tidak bernilai; variabel yang mereferensikannya tidak akan memiliki a typeof
undefined
tapi object
. Suatu objek juga bisa kosong, yaitu tidak null tetapi tidak memiliki properti apa pun.
untuk mendefinisikan suatu objek di JavaScript diapit kurung kurawal ({
y }
) properti atau metode, dipisahkan dengan tanda titik dua (:
) nama properti nilai properti dan dengan koma (,
) sifat yang berbeda. Anda dapat menemukan informasi lebih lanjut tentang cara mengekspresikan suatu objek dalam artikel di format JSON.
Meskipun Anda dapat menggunakan sintaksis yang mungkin membuat Anda berpikir sebaliknya, en JavaScript Tidak ada kelas selain prototipeArtinya, agar suatu objek mewarisi properti dan metode, objek lain dibuat (prototipe) yang digunakan oleh objek lain (anak-anak) sebagai referensi. Sintaks yang paling dekat dengan gaya JavaScript untuk menggunakan prototipe adalah Object.create
meskipun hal ini juga mungkin (dan terkadang berguna) untuk digunakan new
seperti dalam bahasa berorientasi objek lainnya.
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));
|
untuk menanyakan apakah satu objek merupakan turunan dari objek lain, jika Anda menggunakannya sebagai prototipe, jika Anda mewarisi propertinya, singkatnya, Anda dapat menggunakannya instanceof
(dibuat dengan new
) Atau isPrototypeOf
(dibuat dengan Object.create
) yang akan bernilai true ketika objek menggunakan prototipe dan false jika tidak.
Ketika suatu objek telah dibuat dengan menggunakan objek lain sebagai prototipe, yaitu, setelah suatu objek dibuat, maka objek tersebut dapat dibuat menambahkan properti baru atau mengganti properti prototipe menggunakan sintaks titik seperti pada gato.peso=2.5
.
La array di JavaScript Mereka berbeda dari yang mungkin Anda kenal C. Pertama-tama dinyatakan tanpa perlu menyebutkan panjangnya, hanya dengan tanda kurung siku buka dan tutup ([
y ]
), komponen dapat bersifat heterogen (tipe data berbeda dalam larik yang sama) dan elemen baru dapat ditambahkan tanpa dibatasi hingga batas tertentu. Matriks dari JavaScript sebenarnya adalah daftar (koleksi) elemen yang mana direferensikan dengan indeks numerik atau dengan nama. Sebuah array dapat secara bersamaan berisi indeks numerik dan nama elemen, tetapi objek (properti) biasanya digunakan untuk mengeksploitasi tipe kedua.
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
|
Seperti yang dapat dilihat pada contoh sebelumnya, untuk mengetahui apakah suatu variabel sesuai dengan instance array (itu adalah objek array), Anda dapat menggunakan instanceof
, seperti yang telah digunakan dengan objek umum atau, dalam versi yang lebih baru JavaScript Anda dapat menggunakan Array.isArray()
Untuk mengakses elemen array Anda dapat menggunakan indeksnya (matriz[7]
) atau dengan nama properti dengan nama dalam tanda kurung siku (matriz["nombre"]
) atau dengan sintaks titik biasa untuk objek (matriz.nombre
). Karena namanya adalah string teks, ekspresi, termasuk variabel, dapat digunakan untuk menyusunnya. Untuk melakukan loop melalui array dengan properti, loop dengan format dapat digunakan 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
*/
|
Menarik untuk dibahas tujuan kami obyek Date
, yang dapat digunakan untuk mewakili dan mengatur tanggal dan waktu JavaScript. Objek dapat dibuat instance-nya tanpa data, sehingga akan mengambil tanggal dan waktu saat ini, atau dapat dibuat dengan menunjukkan tanggal sebagai nilai, baik dalam milidetik sejak 1 Januari 1970 (seperti Waktu Unix atau waktu POSIX tetapi dinyatakan dalam milidetik, bukan detik) atau menentukan nilai terpisah untuk tahun, bulan, hari, jam...
Objeknya mencakup serangkaian lengkap metode untuk menanyakan atau mengatur tanggal dan waktu:
-
now()
Mengembalikan tanggal dan waktu saat ini yang dinyatakan dalam milidetik sejak 1 Januari 1970 -
getTime()
|setTime()
Mendapat atau mengubah, masing-masing, nilai waktu dalam milidetik sejak 1 Januari 1970. MenggunakanvalueOf()
, yang merupakan metode yang ada di sebagian besar objek, nilai objek Date yang sesuai juga diperoleh, sepertigetTime()
dengan Waktu Unix atau waktu POSIX dinyatakan dalam ms. -
getMilliseconds()
|setMilliseconds()
Digunakan untuk menanyakan atau menyetel bagian pecahan milidetik suatu objekDate
di mana hal itu dijalankan. Jika dikonsultasikan, nilai yang diperoleh adalah antara 0 dan 999 tetapi nilai yang lebih besar dapat diberikan yang akan terakumulasi dalam total tanggal dan waktu sehingga, seperti metode get lainnya, ini berfungsi untuk meningkatkan nilai objekDate
(atau kurangi jika nilai negatif digunakan). -
getSeconds()
|setSeconds()
Mengembalikan atau mengubah, masing-masing, nilai detik objekDate
. -
getMinutes()
|setMinutes()
Digunakan untuk berkonsultasi atau mengatur berita acara bendaDate
. -
getHours()
|setHours()
Memungkinkan Anda berkonsultasi atau mengubah jam (dari 0 hingga 23) objekDate
. -
getDay()
Mengembalikan hari dalam seminggu untuk tanggal tersebut, dinyatakan sebagai nilai dari 0 hingga 6 (Minggu hingga Sabtu). -
getDate()
|setDate()
Mengembalikan atau mengubah hari di bulan objekDate
di mana itu diterapkan. -
getMonth()
|setMonth()
Digunakan untuk melihat atau mengubah nomor bulan objekDate
. -
getFullYear()
|setFullYear()
Meminta atau menetapkan nilai tahun pada objek yang berisi tanggal dan waktu.
Metode sebelumnya Date
sertakan versi UTC untuk dapat bekerja secara langsung dengan waktu universal tanpa harus melakukan perhitungan perantara. Dalam pengertian itu, misalnya, getHours()
memiliki versi getUTCHours()
o getMilliseconds()
sebuah alternatif getUTCMilliseconds()
untuk bekerja sebagai alternatif dengan waktu resmi (legal) atau universal. Dengan getTimezoneOffset()
Anda bisa mengetahui perbedaan yang ada antara waktu universal dan waktu resmi setempat.
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;
|
Fungsi JavaScript
Jika Anda membaca ini, Anda pasti tahu cara memprogram. mikrokontroler en C o en C + + dan mengetahui konsep fungsi. Meski ide dasarnya sama, namun JavaScript Cara mereka didefinisikan dan digunakan sedikit berbeda. Untuk memulainya, telah dikatakan, JavaScript Itu tidak secara eksplisit menggunakan tipe data sehingga Anda tidak perlu menunjukkannya saat mendefinisikan fungsi. Mengikuti, Fungsi tidak wajib memiliki nama, fungsi dapat bersifat anonim. Mereka dapat dikaitkan dengan variabel untuk memanggilnya tetapi mungkin juga tidak diperlukan karena, kadang-kadang, berguna untuk memanggil mereka segera, yang tanda kurung dan parameternya ditambahkan setelah definisi fungsi.
Untuk mendefinisikan suatu fungsi, awalan function
, jika ada, tulis nama, argumen (parameter yang diteruskan ke fungsi) dalam tanda kurung, dan kode yang akan dieksekusi saat fungsi dipanggil dalam tanda kurung kurawal.
1
2
3
4
5
|
function doble(numero)
{
var resultado=numero*2;
return resultado;
}
|
Tentu saja, dalam contoh sebelumnya variabel "hasil" tidak diperlukan sama sekali, namun ini merupakan alasan yang baik untuk mengingat ruang lingkup variabel, yang berfungsi seperti yang Anda harapkan: variabel "hasil" hanya ada dalam fungsi "ganda". Di dalam JavaScript juga dapat digunakan let
, bukannya var
, untuk memasukkan variabel ke dalam konteks blok kode (diapit kurung kurawal, {
y }
)
Ketika berbicara tentang objek di bagian sebelumnya, ada sesuatu yang mendasar yang hilang: properti telah didefinisikan tetapi metode belum didefinisikan. Seperti yang diharapkan, metode objek adalah fungsi, mereka tidak memiliki nama dan digunakan (dipanggil) dari nama (properti) yang ditetapkan oleh definisi objek.
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”);
}
}
|
Pada contoh sebelumnya, sudah ada metode "view_temperature" yang menampilkan nilai properti "current_temperature" melalui konsol. Memang tidak terlalu berguna, namun memberikan gambaran yang lebih lengkap tentang seperti apa definisi suatu benda JavaScript.
Untuk mengakses metode suatu objek (fungsi) ke propertinya, gunakan this
, seperti pada contoh sebelumnya pada baris 11, saat menggunakan properti “current_temperature”.
Akses Model Objek Dokumen (DOM) dengan JavaScript
dari JavaScript Anda memiliki akses ke konten halaman web yang menjalankannya, serta beberapa aspek browser yang menampilkan halaman tersebut, meskipun tidak ke sumber daya sistem. Struktur data yang mendukung properti dan metode yang diakses JavaScript bagian dari objek jendela, khususnya, isi objek (dokumen HTML) sesuai dengan objeknya document
. Meskipun kadang-kadang digunakan untuk kejelasan, tidak perlu mengawali metode atau properti dengan jendela untuk merujuknya, cukup menggunakan, misalnya document
, tidak perlu menulis nama objek root seperti pada window.document
, selama jendela saat ini direferensikan.
Bentuk yang paling banyak digunakan menemukan objek di dalam dokumen HTML Itu melalui metode getElementById()
, yang mana id yang ditunjukkan saat membuat kode diteruskan sebagai argumen HTML. Dari penjelasan di bagian sebelumnya, mudah untuk berasumsi bahwa Anda juga dapat mengakses komponen di dalam objek document
menggunakan sintaks titik (document.componente
) atau tanda kurung menggunakan kedua nama (document["componente"]
), yang paling berguna, seperti indeks numerik, sulit digunakan dan tidak praktis saat mengakses konten halaman web yang dibuat secara manual.
dengan JavaScript Anda bisa dapatkan elemen yang berisi elemen lain (elemen atau node induk) berkonsultasi dengan properti Anda parentNode
atau properti Anda parentElement
, perbedaannya adalah elemen induknya (parentElement
) dari elemen terakhir string PENGHAKIMAN Itu nol (null
) dan simpul induk (parentNode
) adalah dokumen itu sendiri (document
).
untuk memodifikasi konten suatu elemen HTML, misalnya label <div>
, Itu bisa digunakan innerHTML
dan untuk mengubah propertinya, Anda dapat memilih untuk menetapkan kelas yang berbeda className
atau mengubah propertinya satu per satu dengan style
. Mengkonsultasikan gaya yang ditampilkan oleh suatu elemen pada halaman web belum tentu berguna style
karena hal ini mungkin bergantung pada beberapa faktor atau tidak ditentukan secara eksplisit. Untuk memeriksa gaya suatu elemen yang akhirnya ditampilkan di halaman web, metode getComputedStyle digunakan.
Ke elemen dokumen HTML Beberapa kelas dapat ditugaskan padanya untuk menentukan penampilan dan perilakunya, hingga mengelola daftar kelas suatu objek dari JavaScript Anda dapat menggunakan classList
yang menawarkan metodenya add
untuk menambahkan kelas baru ke daftar, remove
untuk menghapusnya, toggle
untuk menggantinya atau melihat konten daftar kelas suatu elemen item
dan contains
, yang mengembalikan kelas yang menempati posisi tertentu dalam daftar dan nilai true
o false
apakah kelas tertentu ada dalam daftar atau tidak.
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”)
}
|
Pada contoh sebelumnya letaknya dengan getElementById
objek yang ingin Anda manipulasi (sebuah elemen <div>
untuk miliknya id
), sebelum mengubah tampilan, konten dihapus dengan menetapkan dengan innerHTML
string teks kosong, ia diberi kelas baru className
dan gayanya dimodifikasi dengan style
tergantung pada nilai konten (suhu), perubahan warna, jika ada, melalui properti color
. Setelah aspek ditetapkan, nilainya ditulis kembali menggunakan innerHTML
.
Pada bagian kedua dari contoh di atas (baris 9 hingga 19) elemen kode diakses HTML menggunakan sintaks document[]
dan properti id
elemen untuk mengubah daftar kelasnya dengan metode ini classList.remove()
dan dengan metodenyaclassList.add()
, berdasarkan hasil beberapa kueri yang dijalankan dalam eksekusi bersyarat, yang mereka bandingkan gunakan classList.contains()
.
Kapan itu akan terjadi mengacu pada suatu elemen HTML beberapa kali di seluruh kode JavaScript, itu sedikit lebih efisien untuk menetapkannya ke variabel atau gunakan indeksnya alih-alih nama sejak itu, jika tidak, metode yang akan Anda gunakan JavaScript untuk mendapatkannya setiap kali akan memerlukan pencarian namanya, memakan waktu lebih lama dibandingkan jika suatu variabel diakses.
untuk menambahkan objek baru ke dokumen HTML, mereka dapat dibuat terlebih dahulu dengan metode ini createElement
de document
dan kemudian menggabungkannya ke elemen lainnya pada titik pohon yang diperlukan appendChild
. Untuk membuat objek XML, seperti benda SVG yang kami gunakan untuk menggambar grafik sensor IoT, dapat Anda gunakan createElementNS
(P untuk ruang nama). Seperti yang dijelaskan ketika berbicara tentang format SVG, namespace yang sesuai dengannya (untuk versi saat ini) adalah http://www.w3.org/2000/svg
, yang harus diteruskan ke createElementNS
sebagai argumen bersama dengan tipe elemen, svg
, pada kasus ini.
sebuah alternatif untuk innerHTML
untuk menambahkan teks sebagai konten ke elemen dokumen HTML adalah metodenya createTextNode()
Obyek document
. Dengan alternatif ini Anda bisa membuat teks baru (yang kemudian diakses jika ditugaskan ke variabel) yang dimasukkan ke dalam pohon objek dengan metode tersebut appendChild()
. Seperti alternatif untuk appendChild()
, yang menambahkan konten baru ke akhir dari apa yang sudah ada di node yang ditambahkan, dapat Anda gunakan metode insertBefore()
, yang menambahkan objek baru di depan objek yang sudah ada. Memakai insertBefore()
di tempat appendChild()
menyediakan metode yang berfungsi, misalnya, untuk mengurutkan objek baru di depan objek yang sudah ada ketika suatu elemen harus berada di depan elemen lainnya (seperti dalam daftar) atau menutupi atau ditutupi dalam struktur grafis yang di dalamnya terdapat elemen yang lebih dekat ke latar depan atau latar belakang.
Bereaksi terhadap peristiwa dengan JavaScript
Ketika jalan menggunakan halaman web sebagai wadah untuk grafik sensor yang terhubung dengan IoT itu digunakan onload
Di label <body>
untuk mulai menggambar grafik. Properti ini, terkait dengan objek kode HTML, mengacu kepada peristiwa JavaScript. Seperti yang sudah dijelaskan, ini menjalankan fungsi ketika halaman telah dimuat. Meskipun telah dikaitkan dengan kode tersebut HTML untuk lebih mengingatnya, itu bisa saja ditulis dalam kode JavaScript sebagai body.onload=dibujar;
sedang dibujar
nama fungsi yang harus dimulai saat halaman web dimuat.
Dalam versi terbaru dari JavaScript acara dapat dikaitkan dengan fungsi menggunakan addEventListener
dengan format objeto.addEventListener(evento,función);
atau menggunakan sintaks objeto.evento=función;
yang juga berfungsi pada implementasi lama. Untuk memutuskan tautan fungsi yang terkait dengan acara tersebut, Anda punya removeEventListener
yang memiliki format yang sama dengan addEventListener
.
JavaScript Ia mampu bereaksi terhadap banyak peristiwa yang dapat terjadi di halaman web. Misalnya, dapat mendeteksi ketika suatu elemen diklik HTML dengan onmousedown
, atau saat diklik dengan onclick
, ketika tombol ditekan dengan onkeydown
, dengan mengoperasikan bilah gulir dengan onscroll
. Untuk tujuan kita, itu sudah cukup bagi kita mendeteksi pemuatan halaman dengan onload
dan ukurannya diubah dengan onresize
. Kita akan mengasosiasikan kejadian ini dengan objeknya body
y window
itu PENGHAKIMAN masing-masing. Yang pertama dapat ditetapkan dalam kode HTML, seperti yang terlihat dan yang kedua di dalam kode JavaScript di dalam fungsi yang dipanggil pertama dan dengan format window.onresize=redimensionar;
sedang redimensionar
fungsi yang akan dipanggil setiap kali jendela berubah ukuran.
Jalankan setelah interval waktu tertentu
JavaScript memiliki dua sumber daya untuk eksekusi yang ditangguhkan: setTimeout
, yang menjalankan fungsi setelah interval waktu dan setInterval
yang akan menjalankan suatu fungsi setiap interval waktu tertentu. Kedua metode memerlukan parameter (1) fungsi yang dipanggil dan (2) interval waktu yang dinyatakan dalam milidetik. Untuk menghentikan operasinya, Anda dapat menetapkan hasil yang dikembalikan oleh fungsi-fungsi ini ke variabel dan meneruskannya sebagai argumen clearTimeout
oa clearInterval
ketika Anda tidak ingin memanggilnya lagi (atau ketika Anda tidak ingin mengeksekusinya untuk pertama kali) setTimeout
o setInterval
masing-masing.
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
}
|
Pada contoh sebelumnya metode ini diperkenalkan alert
yang berfungsi untuk menampilkan tanda peringatan. Meskipun dulunya digunakan secara luas, saat ini kode tersebut hampir dilarang JavaScript karena betapa agresif (intrusifnya) menutupi halaman web dengan kotak dialog.
Dalam sebuah program yang ditulis untuk a mikrokontroler dari seri kecil (seperti yang ada di piring Arduino Uno) biasanya menggunakan variabel global, seperti pada contoh sebelumnya di JavaScript, karena kodenya singkat dan tidak terlalu membingungkan, karena sering kali fungsi diimplementasikan secara ad hoc dan karena penggunaan variabel global memungkinkan untuk memprediksi penggunaan memori dengan cara yang sangat sederhana dan intuitif, yang sangat penting dalam sistem dengan sedikit sumber daya . Alih-alih, en JavaScript Merupakan hal yang umum untuk mengurangi penggunaan variabel global seminimal mungkin. karena tidak perlu terburu-buru penggunaan memori, karena berjalan normal di a CPU dengan sumber daya yang jauh lebih unggul daripada a MCU, karena kemungkinan besar akan hidup berdampingan dengan banyak kode pihak ketiga yang harus berfungsi tanpa mengganggu dan karena ini adalah sistem terbuka, konteks eksekusi di masa depan tidak dapat diprediksi (program dari a mikrokontroler small sepenuhnya menentukan operasinya tanpa menambahkan lebih banyak kode setelah beroperasi) dan karena dimensi aplikasi dapat mempersulit pembacaan jika kode tidak merangkum operasinya, menjadikan metode selengkap mungkin.
Operasi matematika dengan objek JavaScript Math
Operasi matematika perhitungan matematika yang lebih rumit dikelompokkan dalam objek Math
. Objek ini digunakan secara langsung, tidak perlu membuat instance untuk menggunakan metode atau properti (konstanta) yang dimilikinya.
Math.abs(n)
Nilai absolut dari parameter nMath.acos(n)
Arccosine dari parameter n (menghasilkan radian)Math.asin(n)
Arcsinus parameter n (menghasilkan radian)Math.atan(n)
Arctangen parameter n (menghasilkan radian)Math.atan2(n,m)
Arctangen n/m (menghasilkan radian)Math.ceil(n)
Bulatkan parameter ke bilangan bulat terdekat ke atasMath.cos(α)
Kosinus parameter α (α dalam radian)Math.E
nomor e (≃2.718281828459045)Math.exp(n)
e dinaikkan ke parameter n: enMath.floor(n)
Bulatkan parameter n ke bilangan bulat terdekat ke bawahMath.log(n)
Logaritma natural (basis e) dari parameter nMath.LN2
Logaritma natural (basis e) dari 2 (≃0.6931471805599453)Math.LN10
Logaritma natural (basis e) dari 10 (≃2.302585092994046)Math.LOG2E
Logaritma basis 2 e (≃1.4426950408889634)Math.LOG10E
Logaritma basis 10 e (≃0.4342944819032518)Math.max(a,b,c,…)
Nilai terbesar dari daftar parameter yang dilewatiMath.min(a,b,c,…)
Nilai terkecil dari daftar parameter yang dilewatiMath.PI
Angka π (≃3.141592653589793)Math.pow(n,m)
Parameter pertama n dinaikkan ke parameter kedua m:nmMath.random()
(Hampir) angka acak antara 0.0 dan 1.0Math.round(n)
Bulatkan parameter n ke bilangan bulat terdekatMath.sin(α)
Sinus parameter α (α dalam radian)Math.sqrt(n)
Akar kuadrat dari parameter nMath.SQRT1_2
Akar kuadrat dari 1/2 (≃0.7071067811865476)Math.SQRT2
Akar kuadrat dari 2 (≃1.4142135623730951)Math.tan(α)
Tangen parameter α (α dalam radian)
Memuat data dari server dengan AJAX
Metode yang diikuti untuk menggambar informasi yang disimpan di IoT terdiri dari memuat data dari server dari waktu ke waktu dan menggambar ulang grafik yang diwakilinya. Untuk membaca data dari server digunakan teknologi AJAX (JavaScript dan XML Asinkron) melalui suatu objek XMLHttpRequest
de JavaScript. Pembuatan plot grafik data dilakukan dengan menggunakan kembali suatu objek SVG yang sudah ada dalam kodenya HTML dan berisi plot yang koordinatnya diubah agar sesuai dengan data baru yang dimuat.
Pada contoh proposal ini, selain memperbarui gambar, teks pada halaman web juga diperbarui yang menunjukkan tanggal dan nilai data pengukuran terakhir untuk setiap grafik.
Di sisi server terdapat database yang berisi informasi yang telah dipantau oleh sensor yang terhubung ke IoT. Basis data ini dibaca oleh permintaan objek XMLHttpRequest
merespons dengan informasi yang dikodekan dalam format JSON, meskipun nama metode yang digunakan menunjukkan hubungannya dengan format XML.
Dalam tutorial polaridad.es pertama di Penyimpanan data IoT Anda dapat melihat contoh infrastruktur untuk mengelola, dari sisi server, informasi yang disediakan oleh perangkat yang terhubung ke Internet of Things. Dalam rangkaian artikel ini server digunakan sebagai sumber daya Apache dari mana Anda dapat menggunakan bahasa pemrograman PHP untuk mengakses basis data MySQL o MariaDB. Di server yang digunakan untuk mendukung IoT, sangat umum ditemukan database MongoDB (NoSQL) dan bahasa pemrograman JavaScript pada Node.js sebagai infrastruktur perangkat lunak.
Fungsi selanjutnya bertugas meminta data terbaru salah satu sensor dari server. Dalam pemanggilan fungsi, objek digunakan sebagai argumen JavaScript yang mendukung data yang diambil. Jika grafik yang sama mewakili beberapa nilai, misalnya untuk mencari korelasi secara visual, permintaan dapat dibuat ke server untuk mengembalikan beberapa nilai secara bersamaan, metode yang lebih optimal karena cara kerja server. protokol 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);
}
|
Pada baris ketiga dari contoh sebelumnya, query yang akan dibuat ke server disiapkan, di mana argumen "zona" akan diteruskan, yang nilainya akan menjadi nama atau kode tempat yang dipantau karena informasi tentang suatu area mungkin hidup berdampingan dalam database yang sama sensor yang berbeda (misalnya, termometer yang mengukur suhu di ruangan berbeda). Parameter yang diteruskan ke fungsi sebelumnya, objek dengan data bagan, diharapkan menyertakan properti dengan nama ruangan ("name_suffix").
Di antara baris 7 dan 14 kode sebelumnya, obyek XMLHttpRequest
yang disimpan dalam variabel "ajax". Sebelum memilih cara membuat objek, Anda mencari window
jika XMLHttpRequest
tidak tersedia (sesuatu yang terjadi di penjelajah Microsoft versi lama dan meskipun tertinggal jauh, ini berfungsi sebagai contoh alternatif untuk membuat objek menggunakan sintaksis (yang lebih asli)) Object.create
o new
, mirip dengan bahasa berorientasi objek lainnya.
Agar dapat mengatur respon dengan segera, kode yang menanganinya disiapkan pada baris 15 hingga 26 sebelum membuat permintaan ke server.
Cara melakukan kueri HTTP ke server terdiri dari membuka koneksi dengan open
menunjukkan jenis dan halaman (opsional nama pengguna dan kata sandi), menyiapkan headernya dari protokol dengan setRequestHeader
y kirim permintaannya dengan send
. Tajuknya HTTP Content-length
Anda perlu mengetahui panjang kueri (jumlah karakter) yang dihitung menggunakan length
.
Ketika permintaan AJAX sudah siap, fungsi yang terkait dengan acara tersebut dijalankan onreadystatechange
. Alih-alih menugaskan suatu fungsi, pada contoh sebelumnya, fungsi anonim didefinisikan dengan cepat yang akan mengatur penerimaan data yang datang dari server. Pertama-tama, pada baris 18, diverifikasi bahwa status permintaan adalah "selesai", yang sesuai dengan nilainya 4
dari properti readyState
, bahwa statusnya adalah "OK" dari protokol HTTP (kode 200
) yang dapat diperoleh dari properti status
dan bahwa data yang telah tiba adalah format JSON, berkonsultasi dengan properti responseType
.
Setelah diverifikasi bahwa status responnya sesuai dengan yang diharapkan, di baris 20 pada contoh sebelumnya membuat objek dengan hasilnya, mengubah teks JSON. Sebagai respon, tanggal diharapkan akan dikembalikan, hal ini memungkinkan kita untuk melihat apakah hasil yang dikirimkan server sebelumnya telah terwakili dalam grafik, yang diverifikasi pada baris 21. Jika datanya baru, pada baris 23 fungsi yang bertanggung jawab untuk menggambar ulang grafik dengan informasi baru disebut.
Gagasan ketika mengusulkan metode membaca ini adalah bahwa data akan sering di-refresh. Jika informasi yang disajikan sesuai dengan jangka panjang (seperti suhu dalam satu hari atau seminggu), permintaan awal dapat diterapkan yang mengumpulkan semua data yang tersedia dan kemudian, serupa dengan yang ada di contoh, yang memperbaruinya di koresponden periode.
Hasilkan data acak untuk pengujian
Ketika semua infrastruktur server dan klien sudah siap, fungsi seperti di bagian sebelumnya akan bertugas membaca data dan menggambar grafik dengannya, tetapi Pada tahap pengujian mungkin lebih praktis untuk menggunakan angka acak dalam rentang terkendali untuk melihat apakah kode yang ditulis sudah benar. Fungsi berikut dapat menjadi contoh untuk memperoleh data saat membangun aplikasi akhir.
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);
}
|
Daripada membaca informasi dari database, contoh di atas menghasilkannya secara acak dan meneruskannya ke fungsi yang bertugas menggambar grafik. Data yang ditemukan adalah vektor yang dibentuk oleh tanggal yang dinyatakan sebagai nilai dalam milidetik, momen perekaman informasi sensor, dan data yang dipantau, yang berada antara nilai maksimum dan nilai minimum.
Dalam contoh ini, ketika menghasilkan tanggal, tanggal tersebut dapat ditunda hingga satu detik (1000 milidetik) sehubungan dengan tanggal pada saat penemuan. Sebagai Math.random()
menghasilkan angka antara 0.0 dan 1.0, mengalikannya dengan 1000 menghasilkan angka antara 0 dan 1000 yang kemudian diubah menjadi bilangan bulat. Dengan cara yang sama, nilai diperoleh dengan mengalikan bilangan acak dengan rentang (maksimum dikurangi minimum) dan menjumlahkan minimum.
Gambarkan grafik sensor IoT dengan plot SVG
Karena kita telah melihat bagaimana kita dapat memperoleh nilai yang ingin kita wakili (suhu, dalam contoh) dan lokasi temporalnya, yang dapat dinyatakan bersama dalam bentuk koordinat, contoh di bawah ini menunjukkan fungsi menggambar jalur yang menggabungkan titik-titik tersebut dan secara opsional area berwarna yang dibatasi oleh garis di atas. Hasilnya akan seperti gambar berikut.
Sumbu horizontal (X) dari grafik mewakili waktu dan sumbu vertikal (Y) mewakili nilai-nilai yang telah dipantau oleh sensor yang terhubung ke IoT. Interval horizontal adalah beberapa detik karena dalam proposal ini grafik diperbarui sangat sering (misalnya setiap detik) untuk memberikan informasi hampir real-time mengenai keadaan sensor.
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
}
|
Pada kode sebelumnya terdapat dua aspek yang menarik, pertama perhitungan yang memungkinkan mengadaptasi rentang nilai yang diwakili dan kedua konstruksi properti d
yang menunjukkan koordinat titik-titik pada tata letak (path
).
Untuk mengadaptasi rentang nilai yang direpresentasikan, rentang tersebut dipindahkan dari nilai minimum dan diskalakan sehingga besaran tampak sesuai dengan ukuran grafik.. Dalam hal waktu, offset diperoleh dengan mengurangkan rentang yang ingin Anda tampilkan dari waktu terlama (tanggal dan waktu terdekat dengan waktu saat ini) (dalam contoh 20 detik). Perpindahan nilai suhu adalah pada kisaran yang lebih rendah (satu derajat) dikurangi nilai terendah, sehingga data yang ditunjukkan di bawah ini adalah yang paling mirip dengan nilai terendah yang diperbolehkan tetapi menyisakan margin yang memungkinkan kita untuk mengapresiasi nilai suhu tersebut. . lulus
Koefisien yang mengalikan nilai waktu untuk memperoleh koordinat horizontal grafik diperoleh dengan membagi total lebar grafik (100 unit pada contoh) dengan rentang waktu yang diwakili (20 detik pada contoh). Untuk mendapatkan koefisien dengan nilai suhu skalar, harus diingat bahwa rentang yang diwakili berkisar dari margin di bawah nilai minimum ke margin di atas maksimum, satu derajat dalam kedua kasus. Dengan cara ini, koefisien skala vertikal dihasilkan dari pembagian tinggi grafik (100 unit pada contoh) dengan nilai maksimum, dikurangi nilai minimum ditambah margin atas dan bawah. Karena nilai-nilai ini dapat berkembang sepenuhnya pada suhu negatif, kami menggunakan Math.abs()
menggunakan nilai mutlak selisihnya.
Properti d
Obyek path
Itu dibangun dengan menggabungkan koordinat titik-titik dalam sebuah teks. Setiap pasangan koordinat diawali dengan kode SVG L
, yang menarik garis dari posisi saat ini ke nilai absolut yang ditunjukkan oleh koordinat. Nilai X dan Y dipisahkan dengan koma dan operasi masing-masing SVG dipisahkan oleh spasi dari berikutnya.
Untuk memulai tata letak, gunakan kode M
(pindah ke koordinat absolut). Dalam kasus plot tertutup dan terisi, Anda memulai dari kanan bawah, dalam kasus plot terbuka yang menggambarkan profil data, Anda memulai dengan nilai terakhir yang diwakili (yang terbaru). Untuk menyelesaikan tata letak tertutup, kode digunakan Z
menambahkan sebagai titik terakhir titik yang mempunyai nilai koordinat X yang sama dengan titik terakhir garis dan sebagai koordinat Y nilai terkecil yang diwakili.
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
);
}
|
Dalam contoh ini, fungsinya dibujar_grafico()
, yang merupakan panggilan pada pemuatan halaman, mendapatkan nilai awal untuk diuji (bukan nilai real-time terakhir) dan menyiapkan rentang di mana data akan dirender: 20 detik (20000 ms) secara horizontal dan 15°C dalam vertikal dari -5°C hingga +10°C dengan margin atas dan bawah satu derajat. Lakukan dua panggilan ke actualizar_grafico()
, pada lintasan pertama true
sebagai argumen, yang menunjukkan bahwa grafik harus ditutup untuk mewakili area terisi, dan pada panggilan kedua grafik tersebut lolos false
untuk menarik garis. Dalam setiap kasus, objeknya path
dimodifikasi adalah yang memiliki tampilan yang sesuai, dengan isian dan tanpa batas pada kasus pertama dan dengan ketebalan garis tertentu dan tanpa isian pada kasus kedua.
Fungsi itu actualizar_grafico()
bekerja pada suatu objek SVG yang menggunakan kode berikut sebagai wadah HTML. Objek SVG berisi dua jalur, satu untuk menggambar garis dan satu lagi untuk menggambar area yang diisi. Saat memuat halaman web, dari elemen <body>
fungsi sebelumnya dipanggil secara otomatis, dibujar_grafico()
terima kasih untuk acaranya 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>
|
Pada baris 10 kode HTML di atas, lebar (sebagai contoh) 820 px dan tinggi 150 px ditetapkan dalam gaya (sesuatu yang, dalam versi final, disarankan untuk dilakukan dengan kelas dan dokumen CSS). Tampaknya aneh bahwa garis 13 dan 14 menentukan ukuran suatu benda SVG seperti lebar dan tinggi 100% (yang paling sesuai dengan dimensi jendela, 100×100). Seperti yang telah disebutkan, alasan melakukan hal ini adalah untuk selalu bekerja dengan dimensi yang diketahui dan menyesuaikan nilai yang diwakilinya. Alternatif lain adalah menghitung ruang grafik setiap saat dan kemudian menyesuaikan kembali nilai atau gaya dimensi tetap untuk grafik, yang harus dipatuhi oleh dokumen tersebut.
Memilih grafik yang dimensinya berubah sesuai dengan kode HTML, properti harus disertakan vector-effect
dengan nilai non-scaling-stroke
untuk mencegah deformasi ketebalan garis ketika grafik tidak mempertahankan proporsi 1:1 yang dipilih pada halaman web tempat grafik tersebut ditampilkan, seperti yang terjadi pada proposal sebelumnya.
Untuk "memotong" grafik dan hanya menampilkan area yang Anda pilih, gunakan viewBox
. Dalam hal ini kita telah memilih untuk melihat bagian grafik yang dimulai dari 0,0 (pojok kiri atas) dan berukuran 100x100 ke bawah dan ke kanan. Bagian gambar yang terletak pada koordinat dengan nilai negatif atau lebih besar dari 100 tidak akan ditampilkan di halaman web meskipun ada di objek SVG
Tambahkan elemen baru ke gambar SVG
Pada contoh sebelumnya, fungsinya actualizar_grafico()
menggunakan tata letak SVG dimana kepemilikannya diubah d
, yang menyatakan rantai koordinat. Alternatifnya adalah membuat keseluruhan objek setiap kali digambar ulang. Keuntungan opsi pertama adalah tampilan grafis (seperti ketebalan atau warna) ditentukan dalam kode HTML, batasannya adalah objek harus dibuat sebelumnya.
Untuk membuat objek SVG, gunakan createElementNS()
, yang memungkinkan termasuk ruang nama. Pada contoh di bawah ini objek teks baru dibuat (text
) dan dikaitkan dengan suatu elemen SVG yang sudah ada dalam kode HTML dari situs web. Setelah elemen baru dibuat, propertinya ditetapkan setAttribute()
dan ditambahkan ke SVG dengan 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]);
|
Ubah proporsi elemen gambar
Jika Anda telah mencoba memberi label dengan fungsi pada contoh di bagian sebelumnya, Anda akan melihat bahwa teks tampak berubah bentuk ketika proporsi objek pada halaman web (width
y height
Dari kode HTML) tidak sama dengan luas yang diwakili (viewBox
). Untuk menyesuaikan proporsi perlu diketahui ukuran benda SVG untuk itu Anda dapat berkonsultasi dengan gaya objek, atau wadahnya HTML, jika objeknya SVG mengalihkan properti ini. Menugaskan kepemilikan transform
ke objek SVG yang bergantung pada proporsinya, deformasi dapat dikoreksi dengan menerapkan operasi penskalaan scale()
dimana koefisien pada X berbeda dengan koefisien pada Y.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
function
rotular
(
objeto_grafico,
texto,
inicio=[0,0],
altura=10.0,
proporcion=1.0,
tipo_letra=“SircuitoRegularMedium”,
color_texto=“#000000”,
color_fondo=“#FFFFFF”
)
{
var escala_horizontal=parseFloat(getComputedStyle(objeto_grafico).height)/parseFloat(getComputedStyle(objeto_grafico).width);
nuevo_objeto_svg=document.createElementNS(“http://www.w3.org/2000/svg”,‘text’);
nuevo_objeto_svg.setAttribute(“transform”,“scale(“+escala_horizontal+“,1.0)”); // scale permite cambiar la escala en X e Y
//nuevo_objeto_svg.setAttribute(“transform”,”scaleX(“+escala_horizontal+”)”); // Como se sabe que sólo cambia la escala en X, se puede usar scaleX
nuevo_objeto_svg.setAttribute(“x”,inicio[0]);
nuevo_objeto_svg.setAttribute(“y”,inicio[1]);
nuevo_objeto_svg.setAttribute(“font-family”,tipo_letra);
nuevo_objeto_svg.setAttribute(“font-size”,altura);
nuevo_objeto_svg.setAttribute(“fill”,color_texto);
nuevo_objeto_svg.textContent=texto;
objeto_grafico.appendChild(nuevo_objeto_svg);
}
//rotular(document.getElementById(“cosa_svg”),”HOLA”,[10,10]);
|
SVG memungkinkan beberapa objek untuk dikelompokkan membentuk elemen komposit baru yang juga mendukung properti, seperti benda sederhana. Untuk menerapkan transformasi yang sama ke serangkaian objek sekaligus, bukan setiap objek secara terpisah, Anda dapat mengelompokkannya menurut sumber daya ini dan menerapkan satu properti transform
kepada mereka semua.
Seperti yang dijelaskan ketika dibicarakan format SVG, elemen grup diapit di dalam label <g>
y </g>
. Untuk menambahkan dari JavaScript elemen ke dalam grup SVG digunakan, seperti terlihat pada contoh sebelumnya, appendChild()
setelah objek baru didefinisikan.
Untuk menetapkan asal ketika menerapkan transformasi, properti dapat digunakan pada objek SVG transform-origin
, yang nilainya merupakan koordinat X dan Y dari titik awal transformasi. Jika nilai asal transformasi tidak ditunjukkan secara jelas (di browser web), pusat koordinat akan digunakan. Sayangnya, pada saat penulisan, menentukan perilaku transformasi menggunakan sumber selain sumber default tidaklah homogen di seluruh browser dan harus digunakan dengan hati-hati.
Seiring dengan transformasi skala dengan scale
Ada yang lain, seperti rotasi dengan rotation
dan gerakan dengan translate
, yang menawarkan a alternatif untuk representasi grafik: alih-alih mendapatkan koordinat baru, Anda dapat merepresentasikannya dalam ruangnya sendiri dan mengubah grafik agar sesuai dengan format yang Anda inginkan untuk merepresentasikannya.
Tambahkan referensi ke bagan
Sekarang bagian utama grafik telah diselesaikan dengan memplot nilai dengan profil dan area yang terisi, dapat dilengkapi dengan referensi yang membantu pembacaannya. Sebagai contoh, mari kita mulai dengan menggambar beberapa referensi horizontal (garis) yang menandai nilai maksimum dan minimum yang dapat diterima serta nilai yang diinginkan. Seperti yang dijelaskan, Anda dapat memilih untuk menambahkan objek ke SVG langsung dari JavaScript atau memasukkannya secara manual ke dalam kode HTML dan memodifikasinya nanti dengan 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();
|
Tampaknya logis untuk memberi label pada referensi horizontal ini dengan teks yang menjelaskan nilai yang diwakilinya. Untuk menyorot teks, Anda dapat menggunakan persegi panjang yang menonjol dari latar belakang dan grafik. Karena teks harus diskalakan untuk mengimbangi deformasi, semuanya dapat dikelompokkan ke dalam objek yang skalanya akan diterapkan; Keuntungan utama melakukannya dengan cara ini adalah dapat memodifikasinya dalam satu operasi jika wadah grafik (jendela browser) diubah ukurannya dan mengubah proporsi yang dikoreksi oleh skala.
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();
|
Ada beberapa aspek menarik pada contoh kode di atas. Pertama-tama, beri komentar bahwa konstanta (variabel global) telah digunakan untuk membuat contoh lebih mudah dibaca oleh pengguna pemrograman. mikrokontroler en C o en C + +. Seperti yang akan dilihat nanti, cara optimal untuk memprogramnya JavaScript Ini akan menggunakan objek yang berisi nilai dan metode ini yang akan mengelola referensi dalam contoh ini atau grafik, secara umum, dalam sistem produksi.
Di sisi lain, dengan memajukan kode yang lebih umum, fungsi terpisah telah dikembangkan yang menghitung koefisien berbeda yang mengoreksi proporsi grafik untuk menyesuaikan teks. proporcion_grafico()
, skala nilai tergantung pada jangkauannya escala()
dan faktor koreksi untuk pengukuran yang diketahui nilai absolutnya, seperti pengukuran dalam acuan medida_grafico()
.
Membaca kode ini akan membantu memperjelas konteks di mana aplikasi seperti ini bekerja, yang menggambar grafik secara real-time dan harus fleksibel untuk disajikan dalam berbagai konteks grafis (setidaknya berbagai ukuran dan proporsi). Pertama-tama, objek harus dibuat SVG, baik "secara manual" dalam kode HTML, baik melalui kode JavaScript dan dalam hal apa pun, referensi ke objek-objek ini selanjutnya harus diperoleh untuk memanipulasinya JavaScript sehingga grafik baru dapat digambar dan representasi grafik yang sudah digambar dapat disesuaikan dengan perubahan media penyajiannya.
Referensi lain yang dapat membantu menafsirkan suatu grafik dengan mudah adalah titik-titik yang mewakili nilai tertentu (simpul garis). Dalam contoh ini, di mana kita mewakili besaran tunggal, pemilihan simbol tidaklah penting, tetapi jika beberapa nilai berbeda ditumpangkan untuk mencari korelasi, menarik untuk membedakannya, selain menggunakan sumber daya lain seperti warna. , dengan menggambar simbol yang berbeda. Grafik yang digunakan untuk simpul garis harus diubah ukuran dan proporsinya, seperti yang terjadi, misalnya, pada teks, sehingga dimensinya bersifat absolut dan proporsinya tetap terjaga meskipun ukuran kotak yang dikandungnya berubah.
Pada contoh sebelumnya kita telah melihat cara menghitung koefisien yang berbeda untuk mengubah skala dan memperbaiki proporsi gambar; Mengenai cara menerapkan pengelolaan simbol node atau simpul pada grafik, solusi yang mungkin adalah dengan menyimpan objek SVG menjadi vektor dan mengubah posisinya ketika grafik diperbarui dengan membaca nilai baru, atau ketika digambar ulang dengan mengubah ukuran wadah. Dalam kasus pertama posisinya harus diubah dan dalam kasus kedua proporsinya dengan properti transform
dan nilai scale
. Kode berikut merupakan modifikasi dari fungsinya actualizar_grafico()
untuk menyertakan reposisi simbol simpul grafik.
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);
}
}
|
Modifikasi dilakukan pada fungsi actualizar_grafico()
untuk mendapatkan fungsi baru actualizar_grafico_puntos()
Merekalah yang disorot dalam kode contoh sebelumnya. Pertama, pada baris 5, kita mengambil vektor objek SVG sebagai parameter. Vektor ini akan berisi simbol-simbol yang perlu diposisikan ulang di node baru pada grafik.
Pada baris 39 dan 40 koordinat pusat baru ditetapkan, cx
y cy
, dengan nilai-nilai yang diwakili. Jika simbol tidak berada di tengah, mungkin perlu menambahkan offset cx
setengah lebar dan masuk cy
setengah tingginya untuk memposisikannya tepat pada simpul grafik.
Pada garis 57 sampai 61, titik-titik yang sesuai dengan koordinat yang tidak tergambar karena terpotong oleh tepi kiri diposisikan ulang di luar grafik. Koordinat dari cy
ke nol dan itu cx
ke bilangan negatif apa pun (lebih besar dari titik itu sendiri) sehingga tidak ditampilkan saat dipotong, seperti bagian kiri grafik, di jendela grafik SVG.
Kelola bagan dari suatu objek dengan JavaScript
Semua operasi yang telah dijelaskan sejauh ini dapat diintegrasikan ke dalam objek untuk mengelola grafik dengan gaya yang lebih khas dari versi baru JavaScript. Alternatif implementasi ini memiliki keuntungan tambahan yaitu menyederhanakan penggabungan beberapa grafik, dengan nilai berbeda, pada halaman web yang sama.
Sebelum membahas implementasinya, mari kita tinjau cara paling umum untuk membuat objek JavaScript dan beberapa kekhasan fungsi yang mempengaruhi usulan menggambar grafik sensor IoT.
Telah dijelaskan bahwa cara baru untuk membuat objek di JavaScript (tersedia sejak versi 5 ECMAScript) terdiri dari penggunaan Object.create
, yang harusnya biasa digunakan daripada yang "klasik" new
, yang tentu saja masih berfungsi dengan benar, meskipun tujuannya lebih untuk mensimulasikan gaya bahasa dengan objek berbasis kelas (JavaScript mendasarkan pembuatan objek pada prototipe) daripada alternatif yang berfungsi.
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();
}
|
Kode sebelumnya memungkinkan Anda mengingat perbedaan antara membuat objek dengan Object.create
atau dengan new
. Ini juga berfungsi untuk menekankan hal itu, sementara fungsi yang digunakan untuk membuat objek tersebut new
bisa berada di mana saja dalam kode, objek harus sudah ada sebelum dapat dipakai Object.create
(Objek ES5_Object bukan fungsi).
Pada baris 3 dan 4, untuk menetapkan nilai default ke properti dalam fungsi yang membuat objek tersebut new
, setiap properti ditetapkan ke nilai argumen terkait atau (||
), jika tidak ada argumen yang diberikan, yaitu jika argumen tersebut tidak terdefinisi (undefined
), karena keadaan itu dievaluasi sebagai false
, nilai default ditetapkan.
Konteks di mana suatu fungsi dijalankan JavaScript menimbulkan dua masalah yang penting untuk diingat dan juga dapat membingungkan ketika menggunakan bahasa pemrograman ini setelah bekerja dengan orang lain, seperti C o C + +, dalam kasus kami. Konteksnya mencakup variabel-variabel yang didefinisikan dalam lingkup fungsi (dan variabel global) yang, secara kebetulan, memunculkan konsep menarik, "penutupan" yang membentuk keseluruhan gaya pemrograman dalam JavaScript. Meski begitu, hal itu bisa diharapkan this
, yang mengacu pada objek ketika digunakan dalam kode yang mendefinisikannya, konteks eksekusi yang telah didefinisikan dipertahankan tetapi yang digunakannya adalah konteks pemanggilan fungsi. Perilaku ini transparan dalam banyak kasus, namun ada dua keadaan yang dapat membingungkan: fungsi yang didefinisikan di dalam fungsi lain dan metode yang dipanggil dari peristiwa objek. 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
*/
|
Saat mengeksekusi kode sebelumnya, teks komentar di bagian akhir ditampilkan di konsol. Dua garis yang ditandai mencerminkan perilaku yang dapat membingungkan: konteks eksekusi fungsi probar_dentro()
tidak probar()
, seperti yang diharapkan, tapi window
, yang menampilkan variabel global dan bukan properti dengan nama yang sama. Jika Anda tidak menginginkan perilaku ini, cukup buat variabel di fungsi tingkat tertinggi dan tetapkan ke dalamnya this
, seperti pada kode berikut.
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
*/
|
Untuk mengontrol konteks eksekusi ketika suatu metode dipanggil dari suatu peristiwa window
, misalnya dengan mengubah ukuran jendela browser, kekhasan lainnya JavaScript: kemungkinan memprogram "pabrik fungsi", yaitu fungsi yang menghasilkan fungsi lain, mengembalikannya 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
|
Pada contoh kode di atas, metodenya llamar()
dari benda-benda itu Contexto
Itu tidak berfungsi tetapi mengembalikan fungsi anonim yang menanganinya. Untuk memverifikasi bahwa semuanya berfungsi seperti yang diharapkan, ada variabel global dengan nama yang sama dengan properti yang ditampilkan fungsi di konsol; Jika konteksnya benar, nilai properti akan ditampilkan dan bukan nilai variabel global.
JavaScript Coba perbaiki tanda titik koma yang kami hilangkan di akhir kalimat. Hal ini memungkinkan terciptanya gaya penulisan yang santai namun merupakan pedang bermata dua yang harus ditangani dengan hati-hati. Dalam kebanyakan kasus, untuk menghindari efek yang tidak diinginkan yang dihasilkan dalam ekspresi yang menempati beberapa baris, Anda dapat menggunakan tanda kurung atau mengawali cara di mana JavaScript akan menafsirkan kode tersebut; Itu sebabnya baris 8 dari contoh tersebut disertakan function
di belakang return
, jika saya menggunakan baris lain maka maknanya akan sangat berbeda. Menurut pendapat saya, solusi yang paling mudah dibaca adalah dengan menggunakan variabel perantara (yang dapat dibuang) seperti pada versi berikut; Jelas sekali, setelah perilaku dipahami, keputusan ada di tangan pemrogram.
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);
|
Dalam arti yang sama mengevaluasi ekspresi sebagai suatu fungsi, yaitu mengembalikan suatu fungsi dan bukan nilai yang dikembalikan oleh fungsi tersebut; pada baris 21 dari contoh terakhir (pada baris 19 dari contoh sebelumnya) berhenti dengan clearInterval
fungsi yang dipanggil dengan setInterval
. Agar dapat bekerja selama 30 detik, penghentiannya ditunda dengan setTimeout
, yang pada gilirannya memerlukan fungsi sebagai argumen pertama; untuk mengirimkan eksekusi sebagai parameter clearInterval
dengan variabel yang berisi panggilan periodik (dan bukan fungsinya clearInterval
) untuk itulah fungsi anonim di baris terakhir dibuat.
Pilihan antara menulis kode yang mengintegrasikan definisi fungsi, lebih ringkas (seperti pada baris 21) atau menggunakan variabel tambahan, menurut pendapat saya, lebih mudah dibaca (seperti pada baris 19 dan 20) sedikit berbeda dalam kinerja dan lebih bergantung pada gaya dan keterbacaan untuk pemeliharaan.
Untuk menguji kode, sebelum memiliki data di server, Anda dapat menggunakan generator nilai acak dalam rentang yang diinginkan atau menyiapkan tabel dengan nilai terkontrol yang mensimulasikan operasi dalam kondisi yang diinginkan. Contoh berikut menggunakan generator data sederhana di seluruh rentang, itulah sebabnya contoh tersebut tampak agak berlebihan.
Untuk mengujinya, Anda bisa unduh kode lengkap contohnya dibentuk oleh halaman web yang ditulis HTML, gaya CSS dan kodenya JavaScript. Yang terakhir adalah yang paling relevan, karena komponen lainnya hanya memiliki dukungan minimal, sangat disederhanakan dan lebih dikembangkan dalam artikel di bagian terkait.
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);
}
|
Posting