Bumuo at magbago ng SVG graphics ng data mula sa mga sensor na konektado sa IoT gamit ang JavaScript
Sa huling bahaging ito ng serye ng mga artikulo sa pagguhit graphics na may data mula sa mga sensor na konektado sa Internet of Things, oras na para pag-usapan kung paano bumuo o magbago gamit ang JavaScript mga guhit sa format SVG at ilan sa mga elemento HTML na nagsisilbing lalagyan o nagpapakita ng pantulong na impormasyon sa mga graphic.
Ang mga target na gumagamit ng tutorial na ito ay dapat na bumuo ng isang electronics at computer programming profile. mga microcontroller, maaaring hindi sila pamilyar sa HTML, CSS o SVG; Para sa kadahilanang ito, sa mga nakaraang yugto ay ginawa ang isang maikling pagpapakilala sa wika o ang kaukulang teknolohiya. Sa huling bahaging ito, medyo naiiba ang diskarte, dahil tiyak na alam ng mga mambabasa kung paano magprogram, posible na ang paggamit ng wika C + + na, paano JavaScript, nagbabahagi ng pangunahing syntax sa C at maaari itong magamit bilang isang sanggunian upang laktawan ang karamihan sa mga pangunahing konsepto ng programming at sa gayon ay tumuon sa mga pagkakaiba at ang partikular na paggamit na interesado sa amin upang lumikha ng mga sensor graphics sa IoT.
Ang pangalan ay nagbibigay ng pahiwatig sa unang pagkakaiba: JavaScript Ito ay isang programming language script (gitling) at dahil dito, ito ay binibigyang kahulugan, hindi na kailangang i-compile ito; ang konteksto kung saan ang script (isang web browser, halimbawa) ang magbabasa, magsasalin at magsagawa ng mga order. Upang maging tumpak, sa karamihan ng mga kaso mayroong a runtime compilation (JIT), ngunit para sa proseso ng pagsulat ng code JavaScript Hindi ito nakakaapekto sa amin, isinusulat lang namin ang code at maaari itong gumana.
Ang pangalan ay naglalaman din ng unang pagkalito: JavaScript ay walang kahit katiting na relasyon sa Java. Sa una, kapag ito ay binuo Netscape para sa browser nito, tinawag muna itong Mocha at pagkatapos ay ang hindi gaanong nakakalito na LiveScript. Matapos ang matagumpay na pagpapatupad nito sa mga browser, at lampasan ang mga ito, na-standardize ito bilang ECMAScript (Ang ECMA-262, bersyon 6 sa oras ng pagsulat) upang maging neutral kaugnay ng mga browser na nagpapatupad nito. Sa kasalukuyan ay mayroon ding pamantayan ISO mula sa bersyon 5, 2011 (ISO / IEC 16262: 2011 sa oras ng pagsulat ng artikulo)
Mga variable, pangunahing uri ng data at mga bagay sa JavaScript
Hindi tulad ng nangyayari, halimbawa, sa C + +, en JavaScript hindi kasama ang uri ng data kapag nagdedeklara ng variable at gayundin ang uri na nauugnay sa isang variable ay hindi naayos, posible na magtalaga ng isang halaga ng ibang uri sa buong pagpapatupad ng programa.
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 |
Sa nakaraang halimbawa, ang variable na "bagay" ay idineklara na (nang hindi ipinapahiwatig ang uri ng data) pagkatapos ay ang data ng ibang uri ay itinalaga at ito ay kinokonsulta sa typeof
yung tipong JavaScript na kanyang naipaliwanag. Upang i-debug ang code maaari mo itong isulat sa inspector console ng web browser (na hindi makakaapekto sa presentasyon ng web) gamit ang console.log()
.
Upang pilitin ang pag-convert ng data sa isang partikular na uri, lalo na ang teksto sa numeric, maaari kang gumamit ng mga function tulad ng parseInt()
o parseFloat()
na nagko-convert sa mga integer o mga numero ng floating point ayon sa pagkakabanggit. Ang kabaligtaran ng conversion ay maaaring gawin sa String()
, bagaman ito ay malamang na hindi kinakailangan dahil ang awtomatikong conversion ay karaniwang sapat. Sa parseFloat()
Halimbawa, maaari mong makuha ang halaga ng isang web page property, gaya ng lapad o taas ng isang bagay, na kinabibilangan ng mga unit; Sa ganitong paraan, ang pagpapahayag parseFloat("50px");
ay magbabalik ng 50, isang numeric na halaga, bilang isang resulta.
En JavaScript walang pagkakaiba sa pagitan ng double at single quotes; Ang uri ng data sa parehong mga kaso ay string
, at maaaring isama ng bawat isa sa kanila ang isa pa nang hindi nangangailangan ng mga escape code.
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 |
Sa nakaraang halimbawa makikita na ang isang variable, kapag ito ay naideklara na (umiiral) ngunit hindi pa naitatalaga ng anumang halaga, ay naglalaman ng isang hindi natukoy na uri ng data (undefined
). Ang isang hindi nakatalagang bagay ay may halaga null
; Iyon ay, ang bagay ay umiiral, ngunit walang halaga; isang variable na sumangguni dito ay hindi magkakaroon ng a typeof
undefined
pero object
. Ang isang bagay ay maaari ding walang laman, iyon ay, hindi null ngunit walang anumang mga katangian.
Sa tukuyin ang isang bagay sa JavaScript ay nakapaloob sa mga tirante ({
y }
) ang mga katangian o pamamaraan, na pinaghihiwalay ng colon sign (:
) pangalan ng ari-arian halaga ng ari-arian at sa pamamagitan ng kuwit (,
) ang iba't ibang katangian. Makakahanap ka ng higit pang impormasyon tungkol sa paraang ito ng pagpapahayag ng isang bagay sa artikulo sa Format ng JSON.
Bagama't maaari kang gumamit ng syntax na maaaring humantong sa iyong mag-isip nang iba, en JavaScript Walang mga klase ngunit mga prototypeIyon ay, para sa isang bagay na magmana ng mga katangian at pamamaraan, isa pang bagay ang nilikha (ang prototype) na ginagamit ng iba (ang mga bata) bilang isang sanggunian. Ang syntax na pinakamalapit sa istilo ng JavaScript ang gumamit ng prototype ay Object.create
bagaman posible rin (at minsan ay kapaki-pakinabang) gamitin new
tulad ng sa ibang object-oriented na mga wika.
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)); |
Sa query kung ang isang bagay ay isang instance ng isa pa, kung gagamitin mo ito bilang isang prototype, kung namana mo ang mga katangian nito, sa madaling salita, maaari mong gamitin instanceof
(nilikha gamit ang new
) O isPrototypeOf
(nilikha gamit ang Object.create
) na susuriin sa true kapag ang object ay gumagamit ng prototype at false kapag hindi.
Kapag ang isang bagay ay nalikha gamit ang isa pa bilang isang prototype, iyon ay, kapag ang isang bagay ay na-instantiate, maaari itong maging magdagdag ng mga bagong property o i-override ang mga prototype na property gamit ang dot syntax gaya ng sa gato.peso=2.5
.
La mga array sa JavaScript Iba sila sa malamang na kilala mo C. Upang magsimula, idineklara ang mga ito nang hindi kinakailangang ipahiwatig ang kanilang haba, kasama lamang ang mga palatandaan ng pagbubukas at pagsasara ng mga square bracket ([
y ]
), ang mga bahagi ay maaaring magkakaiba (iba't ibang uri ng data sa parehong array) at ang mga bagong elemento ay maaaring idagdag nang hindi nililimitahan sa isang limitasyon. Ang mga matrice ng JavaScript ay talagang mga listahan (mga koleksyon) ng mga elemento kung saan isinangguni ng isang numerical index o ng isang pangalan. Ang isang array ay maaaring sabay na maglaman ng mga numeric index at mga pangalan ng elemento, ngunit karaniwan na gumamit ng mga bagay (properties) upang pagsamantalahan ang pangalawang uri.
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 |
Tulad ng makikita sa nakaraang halimbawa, upang malaman kung ang isang variable ay tumutugma sa isang halimbawa ng isang array (ito ay isang array object) maaari mong gamitin instanceof
, gaya ng nagamit na sa mga generic na bagay o, sa mas kamakailang mga bersyon ng JavaScript maaari mong gamitin sa Array.isArray()
Upang ma-access ang mga elemento ng array maaari mong gamitin ang index nito (matriz[7]
) o sa pamamagitan ng pangalan ng ari-arian na may pangalan sa mga square bracket (matriz["nombre"]
) o gamit ang karaniwang tuldok na syntax para sa mga bagay (matriz.nombre
). Dahil ang pangalan ay isang text string, isang expression, kabilang ang mga variable, ay maaaring gamitin upang buuin ito. Upang mag-loop sa isang array na may mga katangian, maaaring gumamit ng loop na may format 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 */ |
Ito ay kawili-wili para sa aming layunin na tratuhin ang bagay Date
, kung saan kakatawan at pamahalaan ang petsa at oras sa JavaScript. Maaaring ma-instantiate ang object nang walang data, kaya aabutin nito ang kasalukuyang petsa at oras, o maaari itong gawin sa pamamagitan ng pagpapakita ng petsa bilang isang halaga, alinman sa millisecond mula noong Enero 1, 1970 (tulad ng Oras ng Unix o oras ng POSIX ngunit ipinahayag sa millisecond sa halip na mga segundo) o pagtukoy ng hiwalay na mga halaga ng taon, buwan, araw, oras...
Kasama sa object ang isang kumpletong serye ng mga paraan upang mag-query o magtakda ng petsa at oras:
-
now()
Ibinabalik ang kasalukuyang petsa at oras na ipinahayag sa millisecond mula noong Enero 1, 1970 -
getTime()
|setTime()
Nakukuha o binago, ayon sa pagkakabanggit, ang halaga ng oras sa millisecond mula noong Enero 1, 1970. GamitvalueOf()
, na isang paraan na naroroon sa karamihan ng mga bagay, ang halaga ng katumbas na bagay na Petsa ay nakuha din, tulad nggetTime()
sa Oras ng Unix o oras ng POSIX ipinahayag sa ms. -
getMilliseconds()
|setMilliseconds()
Ginagamit upang i-query o itakda ang fractional millisecond na bahagi ng objectDate
kung saan ito isinasagawa. Kung kinunsulta, ang halaga na nakuha ay nasa pagitan ng 0 at 999 ngunit ang mas malalaking halaga ay maaaring italaga na maiipon sa kabuuang petsa at oras kaya, tulad ng iba pang mga pamamaraan ng pagkuha, ito ay nagsisilbi upang mapataas ang halaga ng bagay.Date
(o bawasan ito, kung ang mga negatibong halaga ay ginagamit). -
getSeconds()
|setSeconds()
Ibinabalik o binago, ayon sa pagkakabanggit, ang halaga ng mga segundo ng bagayDate
. -
getMinutes()
|setMinutes()
Ginagamit upang konsultahin o itakda ang minuto ng bagayDate
. -
getHours()
|setHours()
Binibigyang-daan kang kumonsulta o baguhin ang mga oras (mula 0 hanggang 23) ng bagayDate
. -
getDay()
Ibinabalik ang araw ng linggo para sa petsa, na ipinahayag bilang isang halaga mula 0 hanggang 6 (Linggo hanggang Sabado). -
getDate()
|setDate()
Ibinabalik o binabago ang araw ng buwan ng bagayDate
kung saan ito inilapat. -
getMonth()
|setMonth()
Ginagamit upang kumonsulta o baguhin ang bilang ng buwan ng bagayDate
. -
getFullYear()
|setFullYear()
Nagtatanong o nagtatakda ng halaga ng taon sa bagay na naglalaman ng petsa at oras.
Ang mga nakaraang pamamaraan ng Date
isama ang isang bersyon UTC upang magawang gumana nang direkta sa unibersal na oras nang hindi kinakailangang gumawa ng mga intermediate na kalkulasyon. Sa ganitong kahulugan, halimbawa, getHours()
ay may bersyon getUTCHours()
o getMilliseconds()
isang alternatibo getUTCMilliseconds()
upang gumana bilang kahalili sa opisyal (legal) o unibersal na oras. Sa getTimezoneOffset()
Maaari mong malaman ang pagkakaiba na umiiral sa pagitan ng unibersal na oras at lokal na opisyal na oras.
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; |
Mga function ng JavaScript
Kung binabasa mo ito tiyak na alam mo kung paano magprogram. mga microcontroller en C o en C + + at alamin ang konsepto ng function. Bagama't pareho ang pangunahing ideya, sa JavaScript Ang paraan ng pagtukoy at paggamit sa mga ito ay medyo naiiba. Sa simula, sinabi na, JavaScript Hindi ito tahasang gumagamit ng mga uri ng data kaya hindi mo kailangang ipahiwatig ito kapag tinutukoy ang function. Upang sundin, Hindi sapilitan para sa isang function na magkaroon ng pangalan, maaari silang maging anonymous. Maaaring iugnay ang mga ito sa isang variable upang i-invoke ang mga ito ngunit maaaring hindi rin ito kinakailangan dahil, kung minsan, kapaki-pakinabang na i-invoke kaagad ang mga ito, kung saan idinaragdag ang mga panaklong at mga parameter pagkatapos ng kahulugan ng function.
Upang tukuyin ang isang function, prefix function
, kung naaangkop, isulat ang pangalan, ang mga argumento (ang mga parameter na ipinasa sa function) sa mga panaklong, at ang code na isasagawa kapag ang function ay na-invoke sa mga braces.
1 2 3 4 5 | function doble(numero) { var resultado=numero*2; return resultado; } |
Tiyak, sa nakaraang halimbawa ang variable na "resulta" ay hindi kailangan, ngunit ito ay isang magandang dahilan upang tandaan ang variable na saklaw, na gumagana tulad ng iyong inaasahan: ang variable na "resulta" ay umiiral lamang sa loob ng "double" na function. Sa JavaScript pwede ding gamitin let
, sa halip ng var
, upang saklawin ang isang variable sa isang konteksto ng block ng code (na nakapaloob sa mga kulot na brace, {
y }
)
Kapag pinag-uusapan ang tungkol sa mga bagay sa nakaraang seksyon, isang bagay ang pangunahing nawawala: ang mga katangian ay tinukoy ngunit ang mga pamamaraan ay hindi natukoy. Tulad ng inaasahan, Ang mga pamamaraan ng object ay mga function, wala silang pangalan at ginagamit (invoked) mula sa (property) na pangalan na itinalaga ng object definition.
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”); } } |
Sa nakaraang halimbawa, mayroon nang paraan, "view_temperature", na nagpapakita ng halaga ng property na "current_temperature" sa pamamagitan ng console. Hindi ito masyadong kapaki-pakinabang, ngunit nagbibigay ito ng mas kumpletong ideya kung ano ang kahulugan ng isang bagay JavaScript.
Upang ma-access ang mga pamamaraan ng isang bagay (mga function) sa mga katangian nito, gamitin this
, tulad ng sa nakaraang halimbawa sa linya 11, kapag ginagamit ang property na "current_temperature".
I-access ang Document Object Model (DOM) gamit ang JavaScript
Mula sa JavaScript May access ka sa nilalaman ng web page kung saan ito tumatakbo, pati na rin sa ilang aspeto ng browser na nagpapakita ng page na iyon, bagama't hindi sa mga mapagkukunan ng system. Ang istruktura ng data na sumusuporta sa mga katangian at pamamaraan na na-access mula sa JavaScript bahagi ng bagay sa bintana, partikular, ang nilalaman ng bagay (ang dokumento HTML) ay tumutugma sa bagay document
. Bagama't kung minsan ay ginagamit ito para sa kalinawan, hindi kinakailangan na unahan ang window sa mga pamamaraan o mga katangian upang sumangguni sa mga ito, sapat na, halimbawa, upang gamitin document
, hindi na kailangang isulat ang pangalan ng root object tulad ng in window.document
, hangga't ang kasalukuyang window ay isinangguni.
Ang pinaka ginagamit na anyo ng maghanap ng bagay sa loob ng dokumento HTML Ito ay sa pamamagitan ng pamamaraan getElementById()
, kung saan ang id na ipinahiwatig sa paggawa ng code ay ipinasa bilang argumento HTML. Mula sa ipinaliwanag sa mga nakaraang seksyon, madaling ipagpalagay na maaari mo ring ma-access ang mga bahagi sa loob ng bagay document
gamit ang dot syntax (document.componente
) o mga bracket na gumagamit ng parehong pangalan (document["componente"]
), ang pinakakapaki-pakinabang, gaya ng numerical index, mahirap gamitin at hindi praktikal kapag ina-access ang nilalaman ng isang manu-manong binubuong web page.
may JavaScript maaari kunin ang elementong naglalaman ng isa pang elemento (elemento o parent node) pagkonsulta sa iyong ari-arian parentNode
o ang iyong ari-arian parentElement
, ang pagkakaiba ay ang elemento ng magulang (parentElement
) ng huling elemento ng string Paghatol Ito ay null (null
) at ang parent node (parentNode
) ay ang mismong dokumento (document
).
Sa baguhin ang nilalaman ng isang elemento HTML, halimbawa ng isang label <div>
, Maaari itong gamitin innerHTML
at upang baguhin ang mga pag-aari nito, maaari mong piliing italaga ito sa ibang klase className
o baguhin ang mga katangian nito nang paisa-isa style
. Upang kumonsulta sa istilong ipinapakita ng isang elemento sa web page ay hindi kinakailangang kapaki-pakinabang style
dahil maaaring nakadepende ito sa ilang salik o hindi pa malinaw na tinukoy. Upang suriin ang istilo ng isang elemento na sa wakas ay ipinapakita sa web page, ginagamit ang getComputedStyle method.
Sa isang elemento ng dokumento HTML Maraming klase ang maaaring italaga dito upang matukoy ang hitsura at pag-uugali nito, sa pamahalaan ang listahan ng mga klase ng isang bagay mula sa JavaScript maaari mong gamitin sa classList
na nag-aalok ng mga pamamaraan add
para magdagdag ng bagong klase sa listahan, remove
para tanggalin, toggle
upang palitan ito o kumonsulta sa nilalaman ng listahan ng klase ng isang elemento na may item
at contains
, na nagbabalik sa klase na sumasakop sa isang tiyak na posisyon sa listahan at isang halaga true
o false
kung ang isang partikular na klase ay nasa listahan.
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”) } |
Sa nakaraang halimbawa ito ay matatagpuan sa getElementById
ang bagay na gusto mong manipulahin (isang elemento <div>
para sa kanya id
), bago baguhin ang hitsura, ang nilalaman ay tatanggalin sa pamamagitan ng pagtatalaga sa innerHTML
isang walang laman na string ng teksto, ito ay itinalaga ng isang bagong klase na may className
at ang istilo nito ay binago ng style
depende sa halaga ng nilalaman (temperatura), pagpapalit ng kulay, kung naaangkop, sa pamamagitan ng property color
. Kapag ang aspeto ay naitatag, ang halaga ay isinusulat gamit muli innerHTML
.
Sa ikalawang bahagi ng halimbawa sa itaas (mga linya 9 hanggang 19) isang elemento ng code ay na-access HTML gamit ang syntax document[]
at ari-arian id
ng elemento upang baguhin ang listahan ng klase nito gamit ang pamamaraan classList.remove()
at sa pamamaraanclassList.add()
, batay sa resulta ng ilang query na isinagawa sa mga conditional execution, na inihahambing nila gamit classList.contains()
.
Kailan ito pupunta sumangguni sa isang elemento HTML ilang beses sa buong code JavaScript, konti lang mas mahusay na italaga ito sa isang variable o gamitin ang index nito sa halip na ang pangalan dahil, kung hindi, ang paraan na iyong gagamitin JavaScript upang makuha ito sa bawat oras ay mangangailangan ng paghahanap para sa pangalan nito, na gumugugol ng kaunting oras kaysa kung ang isang variable ay na-access.
Sa magdagdag ng mga bagong bagay sa dokumento HTML, maaari silang malikha muna gamit ang pamamaraan createElement
de document
at kalaunan ay isama ang mga ito sa iba pang mga elemento sa punto ng puno na kinakailangan appendChild
. Upang lumikha ng isang bagay XML, tulad ng mga bagay SVG na ginagamit namin sa pagguhit ng graph ng mga IoT sensor, maaari mong gamitin createElementNS
(NS para sa name space). Tulad ng ipinaliwanag kapag pinag-uusapan ang format SVG, ang namespace na tumutugma dito (para sa kasalukuyang bersyon) ay http://www.w3.org/2000/svg
, na dapat ipasa sa createElementNS
bilang isang argumento kasama ang uri ng elemento, svg
, sa kasong ito.
isang kahalili sa innerHTML
upang magdagdag ng teksto bilang nilalaman sa isang elemento ng dokumento HTML ay ang pamamaraan createTextNode()
ng bagay document
. Gamit ang alternatibong ito magagawa mo lumikha ng bagong teksto (na kung saan ay na-access sa ibang pagkakataon kung ito ay nakatalaga sa isang variable) na isinama sa object tree na may pamamaraan appendChild()
. Tulad ng kahalili sa appendChild()
, na nagdaragdag ng bagong nilalaman sa dulo ng kung ano ang mayroon na sa node kung saan ito idinagdag, maaari mong gamitin ang paraan insertBefore()
, na nagdaragdag ng isang bagong bagay sa harap ng isang umiiral na. Magsuot insertBefore()
sa halip ng appendChild()
nagbibigay ng paraan na nagsisilbi, halimbawa, sa pagbukud-bukurin ang mga bagong bagay sa harap ng mga umiiral na kapag ang isang elemento ay dapat na nasa harap ng isa pa (tulad ng sa isang listahan) o takip o nasasakop sa isang graphic na istraktura kung saan mayroong mga elemento na mas malapit sa foreground o background.
Mag-react sa mga kaganapan gamit ang JavaScript
Kapag ang paraan ng gumamit ng web page bilang lalagyan para sa mga graph ng sensor na konektado sa IoT ito ay ginamit onload
Sa tatak <body>
upang simulan ang pagguhit ng graph. Ang property na ito, na nauugnay sa mga object ng code HTML, tumutukoy sa Mga kaganapan JavaScript. Gaya ng ipinaliwanag na, nagsasagawa ito ng function kapag na-load ang page. Kahit na ito ay nauugnay sa code HTML para mas matandaan ito, maaaring nakasulat ito sa code JavaScript bilang body.onload=dibujar;
pagkatao dibujar
ang pangalan ng function na dapat simulan kapag nag-load ang web page.
Sa mga pinakabagong bersyon ng JavaScript Ang mga kaganapan ay maaaring maiugnay sa mga pag-andar gamit addEventListener
kasama ang format objeto.addEventListener(evento,función);
o gamit ang syntax objeto.evento=función;
na gumagana din sa mas lumang mga pagpapatupad. Upang i-unlink ang function na nauugnay sa kaganapan, mayroon ka removeEventListener
na may parehong format bilang addEventListener
.
JavaScript Ito ay may kakayahang tumugon sa maraming kaganapan na maaaring mangyari sa isang web page. Halimbawa, maaari itong makakita kapag na-click ang isang elemento HTML sa onmousedown
, o kapag na-click sa onclick
, kapag pinindot ang isang key gamit ang onkeydown
, sa pamamagitan ng pagpapatakbo ng scroll bar gamit ang onscroll
. Para sa aming layunin ito ay sapat na para sa amin tuklasin ang pag-load ng pahina gamit ang onload
at ang pagbabago ng laki nito sa onresize
. Iuugnay natin ang mga pangyayaring ito sa mga bagay body
y window
del Paghatol ayon sa pagkakabanggit. Ang una ay maaaring italaga sa code HTML, gaya ng nakikita at ang pangalawa sa loob ng code JavaScript sa loob ng function na tinatawag ng una at may format window.onresize=redimensionar;
pagkatao redimensionar
ang function na tatawagin sa tuwing nagbabago ang laki ng window.
Tumakbo pagkatapos ng agwat ng oras
JavaScript ay may dalawang mapagkukunan para sa ipinagpaliban ang pagpapatupad: setTimeout
, na nagsasagawa ng isang function pagkatapos ng agwat ng oras at setInterval
na magpapatupad ng isang function sa bawat tiyak na agwat ng oras. Ang parehong mga pamamaraan ay nangangailangan bilang mga parameter (1) ang invoked function at (2) ang agwat ng oras na ipinahayag sa millisecond. Upang ihinto ang kanilang operasyon, maaari mong italaga ang resulta na ibinalik ng mga function na ito sa mga variable at ipasa ang mga ito bilang argumento sa clearTimeout
Oa clearInterval
kapag hindi mo nais na i-invoke ang mga ito muli (o kapag hindi mo nais na sila ay maisakatuparan sa unang pagkakataon) setTimeout
o setInterval
ayon sa pagkakabanggit.
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 } |
Sa nakaraang halimbawa ang pamamaraan ay ipinakilala alert
na nagsisilbing magpakita ng babala. Kahit na ito ay malawakang ginagamit sa nakaraan, ito ay kasalukuyang halos pinagbawalan mula sa code JavaScript dahil sa kung gaano agresibo (mapanghimasok) ito upang takpan ang web page gamit ang isang dialog box.
Sa isang programang isinulat para sa a microcontroller ng isang maliit na serye (tulad ng nasa plato Arduino uno) karaniwan nang gumamit ng mga pandaigdigang variable, tulad ng sa nakaraang halimbawa sa JavaScript, dahil ang code ay maikli at hindi partikular na nakakalito, dahil maraming beses na ang mga function ay ipinatupad nang ad hoc at dahil ang paggamit ng mga pandaigdigang variable ay ginagawang posible upang mahulaan ang paggamit ng memorya sa isang napaka-simple at madaling maunawaan na paraan, na kritikal sa mga system na may kaunting mga mapagkukunan. . sa halip, en JavaScript Karaniwang bawasan ang paggamit ng mga global variable sa pinakamababang posible. dahil hindi nito kailangang madaliin ang paggamit ng memorya, dahil normal itong tumatakbo sa a CPU na may mga mapagkukunang higit na nakahihigit kaysa sa a MCU, dahil ito ay malamang na magkakasamang mabuhay sa maraming third-party na code kung saan dapat itong gumana nang hindi nakakasagabal at dahil ito ay isang bukas na sistema, ang konteksto ng pagpapatupad sa hinaharap ay hindi mahulaan (ang programa ng isang microcontroller Ang small ay ganap na tinutukoy ang operasyon nito nang hindi nagdaragdag ng higit pang code kapag ito ay gumagana na) at dahil ang mga sukat ng mga application ay maaaring maging mahirap sa pagbabasa kung ang code ay hindi nakapaloob sa operasyon nito, na ginagawa ang mga pamamaraan bilang self-contained hangga't maaari.
Mga pagpapatakbo sa matematika gamit ang object ng JavaScript Math
Ang mga mathematical na operasyon ng mas kumplikadong mathematical na pagkalkula ay pinagsama-sama sa object Math
. Direktang ginagamit ang bagay na ito, hindi kinakailangang i-instantiate ito upang magamit ang mga pamamaraan o katangian (constants) na isinasama nito.
Math.abs(n)
Ganap na halaga ng parameter nMath.acos(n)
Arccosine ng parameter n (resulta sa radians)Math.asin(n)
Arcsine ng parameter n (resulta sa radians)Math.atan(n)
Arctangent ng parameter n (resulta sa radians)Math.atan2(n,m)
Arctangent ng n/m (resulta sa radians)Math.ceil(n)
Bilugan ang parameter sa pinakamalapit na integer pataasMath.cos(α)
Cosine ng parameter α (α sa radians)Math.E
e numero (≃2.718281828459045)Math.exp(n)
e itinaas sa parameter n: enMath.floor(n)
I-round ang parameter n sa pinakamalapit na integer pababaMath.log(n)
Natural logarithm (base e) ng parameter nMath.LN2
Natural logarithm (base e) ng 2 (≃0.6931471805599453)Math.LN10
Natural logarithm (base e) ng 10 (≃2.302585092994046)Math.LOG2E
Base 2 logarithm ng e (≃1.4426950408889634)Math.LOG10E
Base 10 logarithm ng e (≃0.4342944819032518)Math.max(a,b,c,…)
Pinakamalaking halaga ng listahan ng mga parameter na naipasaMath.min(a,b,c,…)
Pinakamaliit na halaga ng listahan ng mga parameter na naipasaMath.PI
Numero π (≃3.141592653589793)Math.pow(n,m)
Unang parameter n itinaas sa pangalawang parameter m: nmMath.random()
(Halos) random na numero sa pagitan ng 0.0 at 1.0Math.round(n)
Round parameter n sa pinakamalapit na integerMath.sin(α)
Sine ng parameter α (α sa radians)Math.sqrt(n)
Square root ng parameter nMath.SQRT1_2
Square root ng 1/2 (≃0.7071067811865476)Math.SQRT2
Square root ng 2 (≃1.4142135623730951)Math.tan(α)
Tangent ng parameter α (α sa radians)
Mag-load ng data mula sa server gamit ang AJAX
Ang pamamaraang sinusunod upang iguhit ang impormasyong nakaimbak sa IoT ay binubuo ng paglo-load ng data mula sa server paminsan-minsan at muling pagguhit ng graph kung saan kinakatawan ang mga ito. Upang basahin ang data mula sa server, ginagamit ang teknolohiya AJAX (Asynchronous JavaScript At XML) sa pamamagitan ng isang bagay XMLHttpRequest
de JavaScript. Ang pag-plot ng data graph ay ginagawa sa pamamagitan ng muling paggamit ng isang bagay SVG na nasa code na HTML at naglalaman iyon ng isang plot na ang mga coordinate ay binago upang gawin silang tumutugma sa bagong data na na-load.
Sa halimbawa ng panukalang ito, bilang karagdagan sa pag-update ng drawing, ina-update din ang isang text sa web page na nagpapakita ng petsa at halaga ng huling sinukat na data para sa bawat graph.
Sa gilid ng server mayroong isang database na naglalaman ng impormasyon na sinusubaybayan ng mga sensor na konektado sa IoT. Ang database na ito ay binabasa ng object request XMLHttpRequest
pagtugon sa impormasyong naka-encode sa Format ng JSON, bagama't ang pangalan ng pamamaraang ginamit ay nagmumungkahi ng kaugnayan sa format XML.
Sa unang polaridad.es tutorial sa Imbakan ng data ng IoT Makakakita ka ng isang halimbawa ng isang imprastraktura upang pamahalaan, mula sa panig ng server, ang impormasyong ibinibigay ng mga device na konektado sa Internet of Things. Sa seryeng ito ng mga artikulo ang isang server ay ginagamit bilang isang mapagkukunan Apache mula sa kung saan maaari mong gamitin ang programming language PHP upang ma-access ang isang database MySQL o MariaDB. Sa mga server na ginamit upang suportahan ang IoT, karaniwan nang maghanap ng mga database MongoDB (NoSQL) at ang programming language JavaScript sa node.js bilang imprastraktura ng software.
Ang susunod na function ay responsable para sa paghiling ng pinakabagong data mula sa isa sa mga sensor mula sa server. Sa function na tawag, ang bagay ay ginagamit bilang isang argumento JavaScript na sumusuporta sa data na iginuhit. Kung ang parehong graph ay kumakatawan sa ilang mga halaga, halimbawa upang biswal na maghanap para sa isang ugnayan, ang isang kahilingan ay maaaring gawin sa server upang ibalik ang ilan nang sabay-sabay, isang mas pinakamainam na paraan dahil sa paraan ng paggana ng server. HTTP protocol.
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); } |
Sa ikatlong linya ng nakaraang halimbawa, inihanda ang query na gagawin sa server, kung saan ipapasa ang argumentong "zone", ang halaga nito ay ang pangalan o code ng sinusubaybayang lugar dahil ang impormasyon tungkol sa ang lugar ay maaaring magkasama sa iisang database. iba't ibang sensor (halimbawa, mga thermometer na sumusukat sa temperatura sa iba't ibang silid). Ang parameter na ipinasa sa nakaraang function, ang object na may data ng chart, ay inaasahang magsasama ng property na may pangalan ng kwarto ("name_suffix").
Sa pagitan ng mga linya 7 at 14 ng nakaraang code, ang bagay XMLHttpRequest
na nakaimbak sa variable na "ajax". Bago pumili kung paano likhain ang bagay, maghanap ka window
kung XMLHttpRequest
ay hindi magagamit (isang bagay na nangyari sa mga lumang bersyon ng explorer ng Microsoft at bagama't ito ay malayo, nagsisilbi itong isang halimbawa ng mga alternatibo upang lumikha ng bagay gamit ang (mas katutubong) syntax) Object.create
o new
, katulad ng iba pang mga object-oriented na wika.
Upang mapangasiwaan kaagad ang tugon, ang code na humahawak dito ay inihanda sa mga linya 15 hanggang 26 bago gumawa ng kahilingan sa server.
Ang paraan ng isagawa ang query HTTP sa server ay binubuo ng magbukas ng koneksyon sa open
na nagpapahiwatig ng uri at pahina (opsyonal na username at password), ihanda ang mga header ng protocol na may setRequestHeader
y ipadala ang kahilingan sa send
. Ang header HTTP Content-length
kailangan mong malaman ang haba ng query (bilang ng mga character) na kinakalkula gamit length
.
Kapag ang kahilingan AJAX handa na, ang function na nauugnay sa kaganapan ay naisakatuparan onreadystatechange
. Sa halip na magtalaga ng isang function, sa nakaraang halimbawa isang anonymous na function ay tinukoy sa mabilisang na mamamahala sa pagtanggap ng data na dumarating mula sa server. Una sa lahat, sa linya 18, na-verify na ang katayuan ng kahilingan ay "tapos", na tumutugma sa halaga 4
ng pag-aari readyState
, na ang katayuan ay "OK" ng HTTP protocol (code 200
) na maaaring makuha mula sa ari-arian status
at na ang data na dumating ay Format ng JSON, pagkonsulta sa ari-arian responseType
.
Kapag na-verify na ang status ng tugon ay tulad ng inaasahan, sa linya 20 ng nakaraang halimbawa lumilikha ng isang bagay na may resulta, na nagko-convert ng teksto JSON. Ang tugon ay nagbibigay para sa isang petsa na ibabalik, ito ay nagbibigay-daan sa amin upang makita kung ang resulta na ipinadala ng server ay dati nang kinakatawan sa graph, na na-verify sa linya 21. Kung ang data ay bago, sa linya 23 Ang function na ay responsable para sa muling pagguhit ng graph gamit ang bagong impormasyon ay tinatawag na.
Ang ideya kapag nagmumungkahi ng paraan ng pagbabasa na ito ay ang data ay ire-refresh nang napakadalas. Kung ang impormasyong ipinakita ay tumutugma sa isang mahabang panahon (tulad ng mga temperatura ng isang araw o isang linggo), ang isang paunang kahilingan ay maaaring ipatupad na kumukolekta ng lahat ng magagamit na data at pagkatapos ay isa, katulad ng isa sa halimbawa, na nag-a-update nito sa ang period correspondent.
Bumuo ng random na data para sa pagsubok
Kapag handa na ang lahat ng imprastraktura ng server at kliyente, ang isang function na tulad ng nasa nakaraang seksyon ang mamamahala sa pagbabasa ng data at pagguhit ng graph kasama nito, ngunit Sa yugto ng pagsubok, maaaring mas praktikal na gumamit ng mga random na numero sa loob ng isang kinokontrol na hanay para makita kung tama ang nakasulat na code. Ang sumusunod na function ay maaaring magsilbi bilang isang halimbawa upang makakuha ng data habang binubuo ang panghuling aplikasyon.
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); } |
Sa halip na basahin ang impormasyon mula sa isang database, ang halimbawa sa itaas ay bumubuo ng mga ito nang random at ipinapasa ang mga ito sa function na namamahala sa pagguhit ng graph. Ang naimbentong data ay isang vector na nabuo sa pamamagitan ng isang petsa na ipinahayag bilang isang halaga sa millisecond, ang sandali ng pagtatala ng impormasyon ng sensor, at ang sinusubaybayang data, na nasa pagitan ng isang maximum na halaga at isang minimum na halaga.
Sa halimbawang ito, kapag bumubuo ng petsa, maaari itong maantala ng hanggang isang segundo (1000 millisecond) na may kinalaman sa petsa sa oras ng pag-imbento. Bilang Math.random()
bumubuo ng isang numero sa pagitan ng 0.0 at 1.0, ang pagpaparami nito sa 1000 ay gumagawa ng isang numero sa pagitan ng 0 at 1000 na pagkatapos ay na-convert sa isang integer. Sa parehong paraan, ang halaga ay nakuha sa pamamagitan ng pagpaparami ng random na numero sa hanay (maximum minus minimum) at pagdaragdag ng minimum.
Iguhit ang graph ng mga IoT sensor na may SVG plot
Dahil nakita natin kung paano natin makukuha ang mga halaga na nais nating katawanin (temperatura, sa halimbawa) at ang kanilang temporal na lokasyon, na maaaring ipahayag nang magkasama sa anyo ng mga coordinate, ang halimbawa sa ibaba ay nagpapakita ng isang function upang gumuhit ng isang landas. na nagdurugtong sa mga puntong iyon at opsyonal na isang may kulay na lugar na hinahati ng linyang iyon sa itaas. Ang resulta ay magiging katulad ng sumusunod na larawan.
Ang pahalang na axis (X) ng graph ay kumakatawan sa oras at ang vertical axis (Y) ang mga halaga na sinusubaybayan ng mga sensor na konektado sa IoT. Ang pahalang na pagitan ay ilang segundo dahil sa panukalang ito ang graph ay napakadalas na ina-update (bawat segundo, halimbawa) upang magbigay ng halos real-time na impormasyon sa estado ng mga 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 } |
Sa nakaraang code mayroong dalawang kawili-wiling aspeto, una ang pagkalkula na nagpapahintulot iakma ang hanay ng mga value na kinakatawan at pangalawa ang pagtatayo ng ari-arian d
na nagpapahiwatig ng mga coordinate ng mga punto sa layout (path
).
Upang iakma ang saklaw ng mga halaga na kinakatawan, ang mga ito ay inilipat mula sa isang minimum at pinaliit upang ang nakikitang magnitude ay tumutugma sa laki ng graph. Sa kaso ng oras, ang offset ay nakuha sa pamamagitan ng pagbabawas ng hanay na gusto mong ipakita mula sa pinakamahabang oras (ang petsa at oras na pinakamalapit sa kasalukuyang isa) (20 segundo sa halimbawa). Ang pag-aalis ng mga halaga ng temperatura ay ang mas mababang hanay (isang degree) na binawasan ang pinakamababang halaga, upang ang data na ipinapakita sa ibaba ay ang pinakakatulad sa pinakamababang halaga na pinapayagan ngunit nag-iiwan ng margin na nagpapahintulot sa amin na pahalagahan ang mga nagagawa .pasa
Ang koepisyent na nagpaparami ng mga halaga ng oras upang makuha ang mga pahalang na coordinate ng graph ay nakuha sa pamamagitan ng paghati sa kabuuang lapad ng graph (100 unit sa halimbawa) sa saklaw ng oras na kinakatawan (20 segundo sa halimbawa). Upang makuha ang koepisyent na may mga halaga ng temperatura ng scalar, dapat tandaan na ang saklaw na kinakatawan ay napupunta mula sa isang margin sa ibaba ng pinakamababang halaga hanggang sa isang margin sa itaas ng maximum, isang degree sa parehong mga kaso. Sa ganitong paraan, ang vertical scale coefficient ay nagreresulta mula sa paghahati sa taas ng graph (100 units sa halimbawa) sa maximum na halaga, binawasan ang minimum kasama ang upper at lower margin. Dahil ang mga halagang ito ay maaaring ganap na bumuo sa mga negatibong temperatura, ginagamit namin Math.abs()
upang gamitin ang ganap na halaga ng pagkakaiba.
Ang pag-aari d
ng bagay path
Ito ay binuo sa pamamagitan ng pagsasama-sama ng mga coordinate ng mga punto sa isang teksto. Ang bawat pares ng mga coordinate ay pinangungunahan ng isang code SVG L
, na kumukuha ng linya mula sa kasalukuyang posisyon patungo sa isang ganap na halaga na ipinahiwatig ng mga coordinate. Ang mga halaga ng X at Y ay pinaghihiwalay ng mga kuwit at bawat operasyon SVG ay pinaghihiwalay ng isang puwang mula sa susunod.
Upang simulan ang layout, gamitin ang code M
(lumipat sa isang ganap na coordinate). Sa kaso ng closed at filled plot, magsisimula ka sa kanang ibaba, sa kaso ng open plot na kumukuha ng data profile, magsisimula ka sa huling value na kinakatawan (pinakabago). Upang tapusin ang saradong layout, ginagamit ang code Z
pagdaragdag bilang huling punto ng isa na may parehong X coordinate value bilang huling punto ng linya at bilang Y coordinate ang pinakamaliit na value na kinakatawan.
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 ); } |
Sa halimbawang ito, ang function dibujar_grafico()
, na siyang tawag sa pag-load ng page, ay nakakakuha ng mga paunang halaga upang subukan (hindi ang huling real-time na halaga) at inihahanda ang hanay kung saan ire-render ang data: 20 segundo (20000 ms) nang pahalang at 15°C sa patayo mula -5°C hanggang +10°C na may isang degree sa itaas at ibabang margin. Gumawa ng dalawang tawag sa actualizar_grafico()
, sa unang pass true
bilang isang argumento, na nagpapahiwatig na ang tsart ay dapat na sarado upang kumatawan sa isang punong lugar, at sa pangalawang tawag ay pumasa ito false
upang gumuhit ng linya. Sa bawat kaso, ang bagay path
ang binago ay ang may katumbas na hitsura, na may punan at walang hangganan sa unang kaso at may tiyak na kapal ng linya at walang punan sa pangalawa.
Ang pag-andar actualizar_grafico()
magtrabaho sa isang bagay SVG na gumagamit ng sumusunod na code bilang isang lalagyan HTML. Ang bagay SVG naglalaman ng dalawang landas, isa upang gumuhit ng linya at isa pa upang iguhit ang punong lugar. Kapag naglo-load ng web page, mula sa elemento <body>
ang nakaraang function ay awtomatikong tinatawag, dibujar_grafico()
salamat sa kaganapan 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> |
Sa linya 10 ng code HTML sa itaas, ang isang lapad (bilang isang halimbawa) ng 820 px at isang taas na 150 px ay itinatag sa estilo (isang bagay na, sa huling bersyon, ito ay ipinapayong gawin sa isang klase at isang dokumento CSS). Tila kakaiba na ang mga linya 13 at 14 ay tumutukoy sa laki ng bagay SVG tulad ng 100% lapad at taas (na pinakamahusay na tumutugma sa mga sukat ng window, 100 × 100). Tulad ng nabanggit na, ang dahilan ng paggawa nito ay upang palaging gumana sa mga kilalang sukat at ayusin ang mga kinakatawan na halaga dito. Ang iba pang mga alternatibo ay ang kalkulahin ang espasyo ng graph sa bawat oras at pagkatapos ay muling ayusin ang mga halaga o pilitin ang mga nakapirming dimensyon para sa graph, na kung saan ang dokumento ay kailangang sumunod sa.
Ang pagkakaroon ng pagpili para sa isang graph na ang mga sukat ay nagbabago ayon sa code HTML, kinakailangang isama ang ari-arian vector-effect
sa tapang non-scaling-stroke
upang maiwasang ma-deform ang mga kapal ng linya kapag hindi pinapanatili ng graph ang napiling 1:1 na proporsyon sa web page kung saan ito ipinapakita, tulad ng nangyari sa nakaraang panukala.
Upang "i-crop" ang graph at ipakita lamang ang lugar na pipiliin mo, gamitin viewBox
. Sa kasong ito, pinili naming makita ang bahagi ng graph na nagsisimula sa 0,0 (kaliwang sulok sa itaas) at may sukat na 100x100 pababa at pakanan. Ang bahagi ng pagguhit na matatagpuan sa mga coordinate na may mga negatibong halaga o higit sa 100 ay hindi ipapakita sa web page kahit na mayroon sila sa object SVG
Magdagdag ng mga bagong elemento sa SVG drawing
Sa nakaraang halimbawa, ang function actualizar_grafico()
gumamit ng layout SVG kung saan binago ang pagmamay-ari d
, na siyang nagpapahayag ng coordinate chain. Ang kahalili ay ang likhain ang buong bagay sa tuwing ito ay muling iginuhit. Ang bentahe ng unang opsyon ay ang graphic na hitsura (tulad ng kapal o kulay) ay tinukoy sa code HTML, ang limitasyon ay ang mga bagay ay dapat na nilikha dati.
Upang lumikha ng mga bagay na SVG, gamitin createElementNS()
, na nagpapahintulot na isama ang namespace. Sa halimbawa sa ibaba isang bagong text object ang nilikha (text
) at nauugnay sa isang elemento SVG na mayroon na sa code HTML ng website. Kapag nalikha na ang bagong elemento, itatalaga ang mga katangian nito sa setAttribute()
at idinagdag sa SVG sa 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]); |
Baguhin ang proporsyon ng mga elemento ng pagguhit
Kung sinubukan mo ang pag-label gamit ang function sa halimbawa sa nakaraang seksyon, makikita mo na ang teksto ay lumilitaw na deformed kapag ang proporsyon ng bagay sa web page (width
y height
Ng code HTML) ay hindi katumbas ng lugar na kinakatawan (viewBox
). Upang iakma ang proporsyon, kailangan mong malaman ang mga sukat ng bagay SVG kung saan maaari mong konsultahin ang estilo ng bagay, o ang lalagyan HTML, kung ang bagay SVG ilipat ang ari-arian na ito. Pagtatalaga ng pagmamay-ari transform
sa mga bagay SVG na depende sa proporsyon, ang pagpapapangit ay maaaring itama sa pamamagitan ng paglalapat ng scaling operation scale()
kung saan ang koepisyent sa X ay iba sa 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 nagbibigay-daan sa ilang mga bagay na mapangkat na bumubuo ng isang bagong pinagsama-samang elemento na sumusuporta din sa mga katangian, tulad ng mga simpleng bagay. Upang ilapat ang parehong pagbabago sa isang serye ng mga bagay nang sabay-sabay sa halip na ang bawat bagay nang hiwalay, maaari mong pangkatin ang mga ito ayon sa mapagkukunang ito at maglapat ng isang pag-aari transform
sa kanilang lahat.
Tulad ng ipinaliwanag kapag pinag-uusapan SVG na format, ang mga elemento ng isang pangkat ay nakapaloob sa loob ng mga label <g>
y </g>
. Upang magdagdag mula sa JavaScript elemento sa isang pangkat SVG ay ginagamit, tulad ng nakikita sa nakaraang halimbawa, appendChild()
kapag natukoy na ang bagong bagay.
Upang magtatag ng pinagmulan kapag nag-aaplay ng mga pagbabago, maaaring gamitin ang property sa mga bagay SVG transform-origin
, na ang halaga ay ang X at Y na mga coordinate ng punto kung saan nagsisimula ang pagbabago. Kung ang isang halaga para sa pinagmulan ng pagbabago ay hindi malinaw na ipinahiwatig (sa web browser), ang sentro ng mga coordinate ay ginagamit. Sa kasamaang palad, sa oras ng pagsulat, ang pagtukoy sa gawi ng mga pagbabagong-anyo gamit ang isang pinagmulan maliban sa default ay hindi homogenous sa mga browser at dapat gamitin nang may pag-iingat.
Kasabay ng pagbabago ng sukat sa scale
Mayroong iba, tulad ng pag-ikot sa rotation
at ang kilusan na may translate
, na nag-aalok ng a alternatibo sa representasyon ng graph: sa halip na makakuha ng mga bagong coordinate, maaari mong katawanin ang mga ito sa kanilang sariling espasyo at baguhin ang graph upang umangkop sa format kung saan mo gustong kumatawan sa kanila.
Magdagdag ng mga sanggunian sa tsart
Ngayon na ang pangunahing bahagi ng graph ay nalutas sa pamamagitan ng paglalagay ng mga halaga sa isang profile at isang puno na lugar, maaari itong kumpletuhin ng mga sanggunian na makakatulong sa pagbabasa nito. Bilang halimbawa, magsimula tayo sa pamamagitan ng pagguhit ng ilang pahalang na sanggunian (mga linya) na minarkahan ang maximum at minimum na katanggap-tanggap na mga halaga pati na rin ang nais na halaga. Gaya ng ipinaliwanag, maaari mong piliing idagdag ang mga bagay sa SVG diretso mula sa JavaScript o manu-manong isama ang mga ito sa code HTML at baguhin ang mga ito sa ibang pagkakataon gamit ang 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(); |
Mukhang lohikal na lagyan ng label ang mga pahalang na sanggunian na ito ng teksto na nagpapalinaw sa halaga na kinakatawan ng mga ito. Upang i-highlight ang teksto, maaari kang gumamit ng mga parihaba na lalabas mula sa background at sa graphic. Dahil ang mga teksto ay kailangang i-scale upang mabayaran ang pagpapapangit, lahat sila ay maaaring igrupo sa isang bagay kung saan ilalapat ang sukat; Ang pangunahing bentahe ng paggawa nito sa paraang ito ay ang magagawang baguhin ang mga ito sa isang operasyon kung ang lalagyan ng graph (ang browser window) ay binago ang laki at binago ang proporsyon na itinatama ng sukat.
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(); |
Mayroong ilang mga kawili-wiling aspeto sa halimbawang code sa itaas. Una sa lahat, magkomento na ang mga constants (global variable) ay ginamit upang gawing mas nababasa ang halimbawa sa mga user na nagmumula sa programming. mga microcontroller en C o en C + +. Tulad ng makikita sa ibang pagkakataon, ang pinakamainam na paraan upang i-program ito JavaScript Ito ay gagamit ng mga bagay na naglalaman ng mga halaga at pamamaraang ito na mamamahala sa mga sanggunian sa halimbawang ito o sa graph, sa pangkalahatan, sa isang sistema ng produksyon.
Sa kabilang banda, sa pagsulong kung ano ang magiging mas generic na code, binuo ang mga hiwalay na function na kinakalkula ang iba't ibang coefficient na nagwawasto sa proporsyon ng graph upang ayusin ang teksto proporcion_grafico()
, ang sukat ng mga halaga depende sa kanilang saklaw escala()
at isang salik sa pagwawasto para sa mga sukat na kilala sa ganap na halaga, tulad ng mga sukat sa mga sanggunian medida_grafico()
.
Ang pagbabasa ng code na ito ay dapat makatulong na linawin ang konteksto kung saan gumagana ang isang application na tulad nito, na gumuhit ng mga graphics sa real time at dapat na flexible upang maipakita sa iba't ibang mga graphical na konteksto (iba't ibang laki at proporsyon, hindi bababa sa). Una sa lahat, ang mga bagay ay dapat mabuo SVG, alinman sa "manual" sa code HTML, alinman sa pamamagitan ng code JavaScript at sa anumang kaso, ang mga sanggunian sa mga bagay na ito ay dapat na pagkatapos ay makuha upang manipulahin ang mga ito mula sa JavaScript upang ang mga bagong graph ay maiguguhit at ang representasyon ng isang naguhit na graph ay maiangkop sa isang pagbabago sa midyum kung saan ito ipinakita.
Ang isa pang sanggunian na maaaring makatulong na madaling bigyang-kahulugan ang isang graph ay ang mga puntos na kumakatawan sa mga tiyak na halaga (ang mga node ng linya). Sa halimbawang ito, kung saan kinakatawan namin ang isang solong magnitude, ang pagpili ng isang simbolo ay hindi kritikal, ngunit kung maraming iba't ibang mga halaga ang pinatong upang maghanap ng ugnayan, ito ay kagiliw-giliw na makilala, bilang karagdagan sa paggamit ng iba pang mga mapagkukunan tulad ng kulay , sa pamamagitan ng pagguhit ng iba't ibang simbolo. Ang mga graphic na ginamit para sa line node ay dapat na mabago sa laki at proporsyon, tulad ng nangyayari, halimbawa, sa mga teksto, upang ang mga sukat nito ay ganap at upang ang mga proporsyon nito ay mapanatili kahit na ang mga nasa kahon na naglalaman nito ay nagbabago. ang graphic.
Sa nakaraang halimbawa nakita na natin kung paano kalkulahin ang iba't ibang mga coefficient upang muling sukatin at itama ang proporsyon ng pagguhit; Tungkol sa kung paano ipatupad ang pamamahala ng mga simbolo ng mga node o vertices ng graph, ang isang posibleng solusyon ay ang pag-imbak ng mga bagay. SVG sa isang vector at baguhin ang posisyon nito kapag ang graph ay na-update sa pamamagitan ng pagbabasa ng isang bagong halaga, o kapag ito ay muling iginuhit sa pamamagitan ng pagbabago ng laki ng lalagyan. Sa unang kaso ang posisyon nito ay kailangang baguhin at sa pangalawa ang proporsyon nito sa ari-arian transform
at ang halaga ng scale
. Ang sumusunod na code ay isang pagbabago ng function actualizar_grafico()
upang isama ang muling pagpoposisyon ng mga simbolo ng graph vertex.
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); } } |
Mga pagbabagong ginawa sa function actualizar_grafico()
para makuha ang bagong function actualizar_grafico_puntos()
Sila ang mga naka-highlight sa code ng nakaraang halimbawa. Una, sa linya 5, kumuha kami ng isang vector ng mga bagay SVG bilang parameter. Maglalaman ang vector na ito ng mga simbolo na kailangang i-reposition sa mga bagong node ng graph.
Sa mga linya 39 at 40 ang mga bagong coordinate ng center ay itinalaga, cx
y cy
, sa mga value na kinakatawan. Kung ang simbolo ay hindi nakabatay sa gitna, malamang na kakailanganing magdagdag ng offset cx
kalahati ng lapad at sa cy
ng kalahati ng taas upang muling iposisyon ang mga ito nang eksakto sa graph node.
Sa mga linya 57 hanggang 61, ang mga puntos na tumutugma sa mga coordinate na hindi iginuhit dahil ang mga ito ay pinutol ng kaliwang gilid ay inilalagay muli sa labas ng graph. Ang coordinate ng cy
sa zero at ng cx
sa anumang negatibong numero (mas malaki kaysa sa mismong punto) upang hindi ito maipakita kapag pinutol, tulad ng kaliwang bahagi ng graph, sa tabi ng window ng SVG.
Pamahalaan ang chart mula sa isang bagay gamit ang JavaScript
Ang lahat ng mga operasyon na ipinaliwanag sa ngayon ay maaaring isama sa isang bagay upang pamahalaan ang graph na may istilong mas tipikal ng mga bagong bersyon ng JavaScript. Ang alternatibong pagpapatupad na ito ay may karagdagang bentahe ng pagpapasimple ng pagsasama ng ilang mga graph, ng iba't ibang mga halaga, sa parehong web page.
Bago talakayin ang pagpapatupad, suriin natin ang mga pinakakaraniwang paraan upang lumikha ng mga bagay JavaScript at ilan sa mga kakaiba ng mga function na nakakaapekto sa panukala para sa pagguhit ng IoT sensor graphics.
Naipaliwanag na ang bagong paraan ng paglikha ng mga bagay sa JavaScript (magagamit mula sa bersyon 5 ng ECMAScript) ay binubuo ng paggamit Object.create
, na dapat masanay sa paggamit sa halip na ang "classic" new
, na siyempre gumagana pa rin ng tama, kahit na ang layunin nito ay higit na gayahin ang estilo ng mga wika na may mga bagay na nakabatay sa klase (JavaScript ibinabatay ang paglikha ng mga bagay sa mga prototype) kaysa sa isang gumaganang alternatibo.
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(); } |
Ang nakaraang code ay nagbibigay-daan sa iyo na matandaan ang mga pagkakaiba sa pagitan ng paglikha ng mga bagay na may Object.create
may new
. Ito rin ay nagsisilbi upang bigyang-diin iyon, habang ang function kung saan ang bagay ay nilikha gamit new
maaaring nasa kahit saan sa code, dapat na umiiral na ang object bago ito ma-instantiate Object.create
(Ang object ng ES5_Object ay hindi isang function).
Sa mga linya 3 at 4, upang magtakda ng default na halaga sa mga katangian sa function na lumilikha ng bagay na may new
, ang bawat ari-arian ay itinalaga sa halaga ng katumbas na argumento o (||
), kung walang mga argumento na naipasa, iyon ay, kung ang mga ito ay hindi natukoy (undefined
), dahil ang pangyayaring iyon ay sinusuri bilang false
, ang default na halaga ay itinalaga.
Ang konteksto kung saan isinasagawa ang isang function JavaScript nagtataas ng dalawang isyu na mahalagang tandaan at maaari ding maging nakalilito kapag ginagamit ang programming language na ito pagkatapos na makipagtulungan sa iba, gaya ng C o C + +, sa kaso natin. Kasama sa konteksto ang mga variable na tinukoy sa saklaw ng function (at ang mga pandaigdigan) na, sa pamamagitan ng paraan, ay nagtataas ng isang kawili-wiling konsepto, ang "mga pagsasara" na nagtatatag ng isang buong istilo ng programming sa JavaScript. Sabi nga, maasahan na this
, na tumutukoy sa bagay kapag ginamit sa loob ng code na tumutukoy dito, ang konteksto ng pagpapatupad kung saan ito ay tinukoy ay pinananatili ngunit ang ginagamit nito ay ang konteksto kung saan tinawag ang function. Ang pag-uugali na ito ay malinaw sa karamihan ng mga kaso, ngunit may dalawang pangyayari kung saan maaari itong maging nakalilito: isang function na tinukoy sa loob ng isa pang function at isang pamamaraan na tinatawag mula sa isang object event. 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 */ |
Kapag isinagawa ang nakaraang code, ang nagkomento na teksto sa dulo ay ipinapakita sa console. Ang dalawang may markang linya ay nagpapakita ng gawi na maaaring nakakalito: ang konteksto ng pagpapatupad ng function probar_dentro()
hindi probar()
, gaya ng inaasahan, ngunit window
, na nagpapakita ng mga pandaigdigang variable at hindi ang mga katangian ng parehong pangalan. Kung hindi mo gusto ang gawi na ito, gumawa lang ng variable sa pinakamataas na antas ng function at italaga ito sa this
, tulad ng sa sumusunod na code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | var primero=“Primero global”; var segundo=“Segundo global”; var Contexto= { primero:“Primero en contexto”, segundo:“Segundo en contexto”, probar: function() { var esto=this; console.log(“Primero en contexto: “+esto.primero); console.log(“Segundo en contexto: “+esto.segundo); function probar_dentro() { console.log(“Primero dentro: “+esto.primero); console.log(“Segundo dentro: “+esto.segundo); } probar_dentro(); } } var probador=Object.create(Contexto); probador.probar(); /* Primero en contexto: Primero en contexto Segundo en contexto: Segundo en contexto Primero dentro: Primero en contexto Segundo dentro: Segundo en contexto */ |
Upang kontrolin ang konteksto ng pagpapatupad kapag ang isang pamamaraan ay tinawag mula sa isang kaganapan window
, halimbawa sa pamamagitan ng pagbabago ng laki ng window ng browser, isa pang kakaiba ng JavaScript: ang posibilidad ng pagprograma ng "mga pabrika ng pag-andar", iyon ay, mga pag-andar na bumubuo ng iba pang mga pag-andar, na nagbabalik sa kanila 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 |
Sa halimbawang code sa itaas, ang pamamaraan llamar()
ng mga bagay Contexto
Hindi nito ginagawa ang trabaho ngunit nagbabalik ng hindi kilalang function na nangangalaga dito. Para ma-verify na gumagana ang lahat gaya ng inaasahan, mayroong isang global variable na may parehong pangalan bilang property na ipinapakita ng function sa console; Kung tama ang konteksto, ang value ng property ang ipapakita at hindi ng global variable.
JavaScript Subukang iwasto ang mga palatandaan ng tuldok-kuwit na tinanggal namin sa dulo ng mga pangungusap. Ito ay nagbibigay-daan para sa isang nakakarelaks na istilo ng pagsulat ngunit ito ay isang tabak na may dalawang talim na dapat tratuhin nang mabuti. Sa karamihan ng mga kaso, upang maiwasan ang mga hindi kanais-nais na epekto na nagagawa nito sa mga expression na sumasakop sa ilang linya, maaari kang gumamit ng mga panaklong o unahan ang paraan kung saan JavaScript ay magbibigay-kahulugan sa code; Iyon ang dahilan kung bakit kasama sa linya 8 ng halimbawa function
sa likod ng return
, kung gumamit ako ng ibang linya ang kahulugan ay ibang-iba. Sa palagay ko, ang pinakanababasang solusyon ay ang paggamit ng intermediate (dispensable) na variable tulad ng sa sumusunod na bersyon; Malinaw, kapag naiintindihan ang pag-uugali, ang desisyon ay tumutugma sa programmer.
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); |
Sa parehong kahulugan ng pagsusuri ng isang expression bilang isang function, iyon ay, pagbabalik ng isang function at hindi ang halaga na ibinalik ng function; sa linya 21 ng huling halimbawa (ito ay sa linya 19 ng nakaraang isa) ito ay humihinto sa clearInterval
ang function na tinatawag na may setInterval
. Upang ito ay kumilos sa loob ng 30 segundo, ang paghinto ay ipinagpaliban sa setTimeout
, na nangangailangan naman ng function bilang unang argumento; upang maihatid ang pagpapatupad bilang isang parameter clearInterval
kasama ang variable na naglalaman ng panaka-nakang tawag (at hindi ang function clearInterval
) ay para saan ginawa ang anonymous na function sa huling linya.
Ang pagpili sa pagitan ng pagsulat ng code na isinasama ang kahulugan ng function, mas compact (tulad ng sa linya 21) o paggamit ng isang auxiliary variable, sa aking opinyon, mas nababasa (tulad ng sa mga linya 19 at 20) ay nag-iiba-iba sa pagganap at depende sa higit pang istilo at pagiging madaling mabasa para sa pagpapanatili.
Upang subukan ang code, bago magkaroon ng data sa server, maaari kang gumamit ng generator ng mga random na halaga sa nais na hanay o maghanda ng mga talahanayan na may mga kinokontrol na halaga na gayahin ang operasyon sa ilalim ng nais na mga kondisyon. Ang sumusunod na halimbawa ay gumagamit ng isang simpleng generator ng data sa buong saklaw, kaya naman lumalabas na medyo pinalaki ang mga ito.
Upang subukan, maaari mong i-download ang buong code ng halimbawa nabuo sa pamamagitan ng isang web page na nakasulat sa HTML, ang style CSS at ang code JavaScript. Ang huli ay ang pinaka-may-katuturan, dahil ang iba pang mga bahagi ay kaunting suporta lamang, napaka-pinasimple at higit na binuo sa mga artikulo sa kaukulang mga seksyon.
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); } |
Post Komento