JavaScript ile IoT'ye bağlı sensörlerden gelen verilerin SVG grafiklerini oluşturun ve değiştirin
Çizim üzerine makaleler serisinin bu son bölümünde Nesnelerin İnternetine bağlı sensörlerden gelen verileri içeren grafiklerile nasıl oluşturulacağı veya değiştirileceği hakkında konuşmanın zamanı geldi JavaScript formatındaki çizimler SVG ve bazı elementler HTML kap görevi gören veya grafiklere tamamlayıcı bilgiler sunan.
Bu eğitimin hedef kullanıcılarının bir elektronik ve bilgisayar programlama profili oluşturması gerekmektedir. mikrodenetleyicileraşina olmayabilirler HTML, CSS o SVG; Bu nedenle önceki bölümlerde dile veya ilgili teknolojiye kısa bir giriş yapıldı. Bu son kısımda yaklaşım biraz farklı, okuyucular mutlaka programlamayı bildikleri için dili kullanmaları mümkün. C + + bu nasıl JavaScript, temel sözdizimini şununla paylaşır: C ve temel programlama kavramlarının çoğunu atlamak ve böylece farklılıklara ve IoT'de sensör grafikleri oluşturmak için bizi ilgilendiren spesifik kullanıma odaklanmak için bir referans olarak kullanılabilir.
İsim ilk farka dair ipucu veriyor: JavaScript Bir programlama dilidir senaryo (tire) ve bu nedenle yorumlanır, derlemeye gerek yoktur; hangi bağlamda senaryo (örneğin bir web tarayıcısı) emirleri okuyacak, tercüme edecek ve uygulayacaktır. Kesin olmak gerekirse, çoğu durumda bir çalışma zamanı derlemesi (JIT), ancak kod yazma işlemi için JavaScript Bu bizi etkilemiyor, sadece kodu yazıyoruz ve çalışabiliyor.
İsim aynı zamanda ilk karışıklığı da içeriyor: JavaScript ile en ufak bir ilişkisi yok Java. Başlangıçta geliştirildiğinde Netscape tarayıcısı için önce Mocha, ardından daha az kafa karıştırıcı olan LiveScript olarak adlandırıldı. Tarayıcılarda başarılı bir şekilde uygulanıp onları aştıktan sonra şu şekilde standartlaştırıldı: ECMAScript (Için ECMA-262, sürüm 6 Bunu uygulayan tarayıcılara karşı tarafsız olmak için bu yazının yazıldığı sırada). Şu anda da bir standart var ISO sürüm 5, 2011'den itibaren (ISO / IEC 16262: 2011 makalenin yazıldığı sırada)
JavaScript'te değişkenler, temel veri türleri ve nesneler
Örneğin, olanlardan farklı olarak C + +, en JavaScript Bir değişken bildirilirken veri türü dahil edilmez ve ayrıca bir değişkenle ilişkili tür sabit değildir, programın yürütülmesi boyunca farklı türde bir değer atamak mümkündür.
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 |
Önceki örnekte, "şey" değişkeni bildirildi (veri tipi belirtilmeden), ardından farklı tipte bir veri atanır ve ona başvurulur. typeof
şu tip JavaScript yorumladığını söyledi. Kodun hatalarını ayıklamak için bunu web tarayıcısının denetçi konsoluna (web'in sunumunu etkilemeyecektir) yazabilirsiniz. console.log()
.
Verilerin belirli bir türe, özellikle de metinden sayısala dönüştürülmesini zorlamak için aşağıdaki gibi işlevleri kullanabilirsiniz: parseInt()
o parseFloat()
bunlar sırasıyla tam sayılara veya kayan noktalı sayılara dönüştürülür. Ters dönüşüm şu şekilde yapılabilir: String()
, ancak otomatik dönüştürme genellikle yeterli olduğundan gerekli olması pek olası değildir. İle parseFloat()
Örneğin, bir web sayfası özelliğinin, birimleri içeren bir nesnenin genişliği veya yüksekliği gibi değerini alabilirsiniz; Bu şekilde ifade parseFloat("50px");
sonuç olarak sayısal bir değer olan 50 değerini döndürecektir.
En JavaScript çift ve tek tırnak arasında fark yoktur; Her iki durumda da veri türü string
ve her biri kaçış kodlarına ihtiyaç duymadan diğerini içerebilir.
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 |
Önceki örnekte, bir değişkenin bildirildiği (var olduğu) ancak herhangi bir değer atanmadığı zaman, tanımlanmamış bir veri türü içerdiği görülebilir (undefined
). Atanmamış bir nesnenin değeri vardır null
; Yani nesne vardır ama değeri yoktur; ona referans veren bir değişkenin typeof
undefined
Çin object
. Bir nesne aynı zamanda boş olabilir, yani boş olmayabilir ancak herhangi bir özelliğe sahip olmayabilir.
Daha içinde bir nesne tanımlayın JavaScript parantez içine alınır ({
y }
) iki nokta üst üste işaretiyle ayrılmış özellikler veya yöntemler (:
) özellik adı özellik değeri ve virgülle (,
) farklı özellikler. Bir nesnenin bu şekilde ifade edilmesi hakkında daha fazla bilgiyi şu makalede bulabilirsiniz: JSON biçimi.
Aksini düşünmenize yol açabilecek sözdizimini kullanabilseniz de, en JavaScript Sınıflar yok ama prototipler varYani, bir nesnenin özellikleri ve yöntemleri miras alması için, diğerlerinin (çocukların) referans olarak kullandığı başka bir nesne (prototip) oluşturulur. Stiline en yakın sözdizimi JavaScript bir prototip kullanmak Object.create
kullanılması da mümkün (ve bazen faydalı) olmasına rağmen new
diğer nesne yönelimli dillerde olduğu gibi.
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)); |
Daha bir nesnenin diğerinin örneği olup olmadığını sorgula, eğer onu prototip olarak kullanırsanız, özelliklerini miras alırsanız, kısacası kullanabilirsiniz. instanceof
(ile oluşturuldu new
) o isPrototypeOf
(ile oluşturuldu Object.create
) nesne prototipi kullandığında true, kullanmadığında false olarak değerlendirilecektir.
Bir nesne bir başka nesneyi prototip olarak kullanarak yaratıldığında, yani bir nesne bir kez başlatıldığında, yeni özellikler ekleyin veya prototip özelliklerini geçersiz kılın olduğu gibi nokta sözdizimini kullanma gato.peso=2.5
.
La diziler JavaScript Muhtemelen tanıdığınız kişilerden farklılar C. Başlangıç olarak uzunluklarını belirtmeye gerek kalmadan sadece köşeli parantezlerin açma ve kapama işaretleri ile bildirilirler ([
y ]
), bileşenler heterojen olabilir (aynı dizide farklı veri türleri) ve yeni öğeler bir sınırla sınırlandırılmadan eklenebilir. matrisleri JavaScript aslında öğelerin listeleridir (koleksiyonlarıdır) sayısal bir indeks veya bir isimle referans verilir. Bir dizi aynı anda sayısal dizinler ve öğe adları içerebilir, ancak ikinci türden yararlanmak için nesnelerin (özelliklerin) kullanılması yaygındır.
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 |
Önceki örnekte görülebileceği gibi, bir değişkenin bir dizi örneğine (bu bir dizi nesnesidir) karşılık gelip gelmediğini bilmek için şunu kullanabilirsiniz: instanceof
genel nesnelerde veya daha yeni sürümlerde zaten kullanıldığı gibi JavaScript başvurabilirsin Array.isArray()
Dizinin elemanlarına erişmek için indeksini kullanabilirsiniz (matriz[7]
) veya köşeli parantez içindeki adla birlikte özellik adına göre (matriz["nombre"]
) veya nesneler için olağan nokta sözdizimi ile (matriz.nombre
). Ad bir metin dizesi olduğundan, onu oluşturmak için değişkenleri içeren bir ifade kullanılabilir. Özelliklere sahip bir dizide döngü yapmak için formata sahip bir döngü kullanılabilir 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 */ |
Tedavi etme amacımız açısından ilginç nesne Date
tarih ve saati temsil edecek ve yönetecek olan JavaScript. Nesne veri olmadan oluşturulabilir, dolayısıyla geçerli tarih ve saati alır veya 1 Ocak 1970'ten bu yana milisaniye cinsinden bir değer olarak bir tarih belirtilerek oluşturulabilir (örneğin, Unix zamanı veya POSIX zamanı ancak saniye yerine milisaniye cinsinden ifade edilir) veya yıl, ay, gün, saat gibi ayrı değerler belirtilerek...
Nesne tam bir dizi içerir tarih ve saati sorgulama veya ayarlama yöntemleri:
-
now()
1 Ocak 1970'den bu yana milisaniye cinsinden ifade edilen geçerli tarih ve saati döndürür -
getTime()
|setTime()
1 Ocak 1970'den bu yana milisaniye cinsinden zaman değerini sırasıyla alır veya değiştirir.valueOf()
Çoğu nesnede bulunan bir yöntem olan, karşılık gelen Date nesnesinin değeri de elde edilir;getTime()
ile Unix zamanı veya POSIX zamanı ms cinsinden ifade edilir. -
getMilliseconds()
|setMilliseconds()
Nesnenin kesirli milisaniye kısmını sorgulamak veya ayarlamak için kullanılırDate
üzerinde yürütülür. Başvurulursa elde edilen değer 0 ile 999 arasındadır ancak toplam tarih ve saatte birikecek daha büyük değerler atanabilir, böylece diğer get yöntemleri gibi nesnenin değerini artırmaya hizmet eder.Date
(veya negatif değerler kullanılıyorsa azaltın). -
getSeconds()
|setSeconds()
Nesnenin saniye değerini sırasıyla döndürür veya değiştirirDate
. -
getMinutes()
|setMinutes()
Nesnenin tutanaklarına danışmak veya ayarlamak için kullanılırDate
. -
getHours()
|setHours()
Nesnenin saatlerine (0'dan 23'e kadar) bakmanıza veya değiştirmenize olanak tanırDate
. -
getDay()
Tarihe ilişkin haftanın gününü, 0'dan 6'ya (Pazar'dan Cumartesi'ye) kadar bir değer olarak ifade ederek döndürür. -
getDate()
|setDate()
Nesnenin ayın gününü döndürür veya değiştirirDate
hangisinde uygulanır. -
getMonth()
|setMonth()
Nesnenin ay numarasını incelemek veya değiştirmek için kullanılırDate
. -
getFullYear()
|setFullYear()
Tarih ve saati içeren nesnedeki yıl değerini sorgular veya ayarlar.
Daha önceki yöntemler Date
bir sürüm ekle UTC ara hesaplamalar yapmaya gerek kalmadan doğrudan evrensel zamanla çalışabilmek. Bu anlamda örneğin getHours()
bir sürümü var getUTCHours()
o getMilliseconds()
bir alternatif getUTCMilliseconds()
resmi (yasal) veya evrensel zamanla alternatif olarak çalışmak. İle getTimezoneOffset()
Evrensel saat ile yerel resmi saat arasındaki farkı biliyorsunuz.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | var dia_semana=[“domingo”,“lunes”,“martes”,“miércoles”,“jueves”,“viernes”,“sábado”]; var nombre_mes=[“enero”,“febrero”,“marzo”,“abril”,“mayo”,“junio”,“julio”,“agosto”,“septiembre”,“octubre”,“noviembre”,“diciembre”]; var digitos_hora; var hoy=new Date(); var texto_hoy=“”; texto_hoy+=“Hoy es “; texto_hoy+=dia_semana[hoy.getDay()]; texto_hoy+=“, “; texto_hoy+=hoy.getDate(); texto_hoy+=” de “; texto_hoy+=nombre_mes[hoy.getMonth()]; texto_hoy+=” de “; texto_hoy+=hoy.getFullYear(); texto_hoy+=” y son las “; digitos_hora=hoy.getHours(); texto_hoy+=digitos_hora>9?digitos_hora:“0”+digitos_hora; texto_hoy+=“:”; digitos_hora=hoy.getMinutes(); texto_hoy+=digitos_hora>9?digitos_hora:“0”+digitos_hora; texto_hoy+=“:”; digitos_hora=hoy.getSeconds(); texto_hoy+=digitos_hora>9?digitos_hora:“0”+digitos_hora; |
JavaScript işlevleri
Eğer bunu okuyorsanız kesinlikle nasıl programlanacağını biliyorsunuzdur. mikrodenetleyiciler en C içinde C + + ve fonksiyon kavramını bilir. Temel fikir aynı olsa da JavaScript Tanımlanma ve kullanılma şekilleri biraz farklıdır. Başlangıç olarak, zaten söylendi, JavaScript Açıkça veri türlerini kullanmadığından, işlevi tanımlarken belirtmenize gerek yoktur.. Takip etmek, Bir işlevin bir isme sahip olması zorunlu değildir; anonim olabilirler. Bunları çağırmak için bir değişkenle ilişkilendirilebilirler ancak bazen gerekli olmayabilir, çünkü bazen parantezlerin ve parametrelerin fonksiyonun tanımından sonra eklendiği hemen çağırmak yararlı olabilir.
Bir işlevi tanımlamak için önek function
, mümkünse adı, argümanları (fonksiyona iletilen parametreler) parantez içine ve fonksiyon çağrıldığında yürütülecek kodu parantez içine yazın.
1 2 3 4 5 | function doble(numero) { var resultado=numero*2; return resultado; } |
Elbette, önceki örnekte "sonuç" değişkenine hiç ihtiyaç duyulmamıştı, ancak bu, şunu hatırlamak için iyi bir bahanedir: değişken kapsam, beklediğiniz gibi çalışır: "sonuç" değişkeni yalnızca "double" işlevi içinde bulunur. İçinde JavaScript ayrıca kullanılabilir let
yerine var
, bir değişkeni kod bloğu bağlamına dahil etmek için (küme parantezleri içine alınmış, {
y }
)
Önceki bölümde nesnelerden bahsederken temel bir şey eksikti: özellikler tanımlanmış ancak yöntemler tanımlanmamıştı. Beklenildiği gibi, nesne yöntemleri işlevlerdir, adları yoktur ve nesne tanımı tarafından atanan (özellik) adından kullanılır (çağrılır).
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”); } } |
Önceki örnekte, konsol aracılığıyla "current_temperature" özelliğinin değerini görüntüleyen "view_temperature" adında bir yöntem zaten mevcuttur. Pek kullanışlı değil ama bir nesnenin tanımının neye benzediğine dair daha eksiksiz bir fikir veriyor. JavaScript.
Bir nesnenin (işlevlerin) yöntemlerine özelliklerine erişmek için şunu kullanın: this
11. satırdaki önceki örnekte olduğu gibi, "current_temperature" özelliğini kullanırken.
Belge Nesne Modeline (DOM) JavaScript ile erişme
. JavaScript Sistem kaynaklarına olmasa da, üzerinde çalıştığı web sayfasının içeriğine ve o sayfayı görüntüleyen tarayıcının bazı özelliklerine erişebilirsiniz. Erişilen özellikleri ve yöntemleri destekleyen veri yapısı JavaScript pencere nesnesinin bir kısmı, özellikle nesnenin içeriği (belge HTML) nesneye karşılık gelir document
. Bazen netlik sağlamak için kullanılsa da, yöntem veya özelliklere atıfta bulunmak için bunların önüne pencere koymak gerekli değildir, örneğin şunu kullanmak yeterlidir: document
olduğu gibi kök nesnenin adını yazmaya gerek yoktur. window.document
Geçerli pencereye başvurulduğu sürece.
En çok kullanılan şekli belgede bir nesne bulma HTML Bu yöntem sayesinde getElementById()
, kod oluşturulurken belirtilen kimliğin argüman olarak iletildiği yer HTML. Önceki bölümlerde anlatılanlardan, nesnenin içindeki bileşenlere de erişebileceğinizi varsaymak kolaydır. document
nokta sözdizimini kullanarak (document.componente
) veya parantez içinde hem adı (document["componente"]
), sayısal dizin gibi en kullanışlı olanı, manuel olarak oluşturulmuş bir web sayfasının içeriğine erişirken kullanımı zor ve pratik değildir.
ile JavaScript yapabilirsiniz başka bir öğe içeren öğeyi alın (öğe veya ana düğüm) mülkünüzle ilgili danışmanlık parentNode
veya mülkünüz parentElement
fark, ana öğenin (parentElement
) dizenin son elemanının KARAR Bu boş (null
) ve ana düğüm (parentNode
) belgenin kendisidir (document
).
Daha bir öğenin içeriğini değiştirmek HTMLörneğin bir etiketinki <div>
, Kullanılabilir innerHTML
ve özelliklerini değiştirmek için ona farklı bir sınıf atamayı seçebilirsiniz. className
veya özelliklerini tek tek değiştirin style
. Web sayfasındaki bir öğe tarafından görüntülenen stile bakmak her zaman yararlı olmayabilir style
çünkü çeşitli faktörlere bağlı olabilir veya açıkça belirtilmemiş olabilir. Sonunda web sayfasında görüntülenen bir öğenin stilini kontrol etmek için getComputedStyle yöntemi kullanılır..
Bir belge öğesine HTML Görünümünü ve davranışını belirlemek için ona birkaç sınıf atanabilir. bir nesnenin sınıflarının listesini yönetmek JavaScript başvurabilirsin classList
yöntemleri sunan add
Listeye yeni bir sınıf eklemek için, remove
onu kaldırmak için, toggle
onu değiştirmek veya bir öğenin sınıf listesinin içeriğine bakmak için item
ve contains
listede belirli bir konumu kaplayan sınıfı ve bir değeri döndürür true
o false
Belirli bir sınıfın listede olup olmadığı.
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”) } |
Önceki örnekte şu konumda bulunur: getElementById
işlemek istediğiniz nesne (bir öğe <div>
onun için id
), görünümü değiştirmeden önce içerik ile atanarak silinir. innerHTML
boş bir metin dizesi, yeni bir sınıfa atanır className
ve stili şu şekilde değiştirildi: style
içeriğin değerine (sıcaklığa) bağlı olarak, varsa özellik aracılığıyla rengin değiştirilmesi color
. Görünüm oluşturulduktan sonra değer tekrar kullanılarak yazılır. innerHTML
.
Yukarıdaki örneğin ikinci bölümünde (9'dan 19'a kadar olan satırlar) bir kod öğesine erişilir. HTML sözdizimini kullanarak document[]
ve mülk id
Bu yöntemle sınıf listesini değiştirmek için öğenin classList.remove()
ve yöntemleclassList.add()
kullanarak karşılaştırdıkları, koşullu yürütmelerde gerçekleştirilen birkaç sorgunun sonucuna dayalıdır. classList.contains()
.
Ne zaman gidiyor bir öğeye atıfta bulunmak HTML varias kod boyunca kere JavaScript, Birazcık onu bir değişkene atamak daha verimli veya isim yerine indeksini kullanın, aksi takdirde kullanacağınız yöntem JavaScript bunu her seferinde elde etmek, adının aranmasını gerektirir ve bir değişkene erişildiğinden biraz daha fazla zaman harcar.
Daha belgeye yeni nesneler ekleme HTML, yöntemle ilk önce oluşturulabilirler createElement
de document
ve daha sonra bunları ağacın gerekli olduğu noktada geri kalan öğelere dahil edin. appendChild
. Bir nesne oluşturmak için XMLnesneler gibi SVG IoT sensörlerinin grafiğini çizmek için kullandığımız createElementNS
(NS için ad alanı). Format hakkında konuşurken açıklandığı gibi SVG, ona karşılık gelen ad alanı (geçerli sürüm için) http://www.w3.org/2000/svg
, iletilmesi gereken createElementNS
öğe türüyle birlikte bir argüman olarak, svg
, bu durumda.
bir alternatif innerHTML
bir belge öğesine içerik olarak metin eklemek için HTML yöntem bu createTextNode()
nesne document
. Bu alternatifle şunları yapabilirsiniz: yeni metin oluştur (bir değişkene atanırsa daha sonra erişilir) yöntemle nesne ağacına dahil edilir appendChild()
. olarak alternatif appendChild()
Yeni içeriği, eklendiği düğümde zaten mevcut olanın sonuna ekleyen, kullanabilirsiniz yöntem insertBefore()
, mevcut bir nesnenin önüne yeni bir nesne ekler. Giymek insertBefore()
yerine appendChild()
örneğin aşağıdakilere hizmet eden bir yöntem sağlar: yeni nesneleri mevcut nesnelerin önüne sıralayın bir öğenin diğerinin önünde olması (bir listede olduğu gibi) veya ön plana veya arka plana daha yakın öğelerin bulunduğu bir grafik yapıyı kaplaması veya kaplaması gerektiğinde.
Etkinliklere JavaScript ile tepki verme
Ne zaman yolu IoT bağlantılı sensör grafikleri için bir web sayfasını kapsayıcı olarak kullanma kullanılmış onload
Etikette <body>
Grafiği çizmeye başlamak için. Kod nesneleriyle ilişkili bu özellik HTML, şuna atıfta bulunur: Etkinlikler JavaScript. Daha önce açıklandığı gibi sayfa yüklendiğinde bir işlevi çalıştırır. Her ne kadar kodla ilişkilendirilmiş olsa da HTML daha akılda tutmak için kodda yazılmış olabilir JavaScript olarak body.onload=dibujar;
olma dibujar
web sayfası yüklendiğinde başlatılması gereken fonksiyonun adı.
En son sürümlerinde JavaScript olaylar işlevlerle ilişkilendirilebilir. addEventListener
format ile objeto.addEventListener(evento,función);
veya sözdizimini kullanarak objeto.evento=función;
bu aynı zamanda eski uygulamalarda da işe yarar. Etkinlikle ilişkili işlevin bağlantısını kaldırmak için, removeEventListener
ile aynı formata sahip olan addEventListener
.
JavaScript Bir web sayfasında meydana gelebilecek çok sayıda olaya tepki verme yeteneğine sahiptir. Örneğin bir öğeye ne zaman tıklandığını algılayabilir HTML ile onmousedown
veya ile tıklandığında onclick
ile bir tuşa basıldığında onkeydown
kaydırma çubuğunu kullanarak onscroll
. Amacımız açısından bu bizim için yeterli ile sayfa yükünü tespit et onload
ve yeniden boyutlandırılması onresize
. Bu olayları nesnelerle ilişkilendireceğiz. body
y window
del KARAR sırasıyla. İlki kodda atanabilir HTML, görüldüğü gibi ve koddaki ikinci JavaScript ilk tarafından çağrılan fonksiyonun içinde ve formatta window.onresize=redimensionar;
olma redimensionar
pencerenin boyutu her değiştiğinde çağrılacak işlev.
Belirli bir zaman aralığından sonra çalıştır
JavaScript için iki kaynağı var ertelenmiş yürütme: setTimeout
, belirli bir zaman aralığından sonra bir işlevi yürütür ve setInterval
her belirli zaman aralığında bir işlevi yürütecek olan. Her iki yöntem de parametre olarak (1) çağrılan işlevi ve (2) milisaniye cinsinden ifade edilen zaman aralığını gerektirir. İşlemlerini durdurmak için, bu işlevler tarafından döndürülen sonucu değişkenlere atayabilir ve bunları argüman olarak iletebilirsiniz. clearTimeout
oa clearInterval
onları tekrar çağırmak istemediğinizde (veya ilk kez çalıştırılmalarını istemediğinizde) setTimeout
o setInterval
sırasıyla.
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 } |
Önceki örnekte yöntem tanıtılmıştır. alert
bir uyarı işareti göstermeye yarar. Geçmişte yaygın olarak kullanılmasına rağmen şu anda neredeyse koddan yasaklanmıştır. JavaScript web sayfasını bir iletişim kutusuyla kaplamanın ne kadar agresif (müdahaleci) olduğu nedeniyle.
için yazılmış bir programda mikrodenetleyici küçük bir serinin (tabaktaki gibi) Arduino Uno) önceki örnekte olduğu gibi global değişkenlerin kullanılması yaygındır. JavaScript, kod kısa olduğundan ve özellikle kafa karıştırıcı olmadığından, çoğu zaman işlevler geçici olarak uygulandığından ve küresel değişkenlerin kullanımı, az kaynağa sahip sistemlerde kritik olan, bellek kullanımını çok basit ve sezgisel bir şekilde tahmin etmeyi mümkün kıldığından . Yerine, en JavaScript Küresel değişkenlerin kullanımını mümkün olan en aza indirmek yaygındır. çünkü normal bir şekilde çalıştığı için bellek kullanımını aceleye getirmesi gerekmez. işlemci sahip olduğundan çok daha üstün kaynaklara sahip MCU, müdahale etmeden çalışması gereken birçok üçüncü taraf koduyla bir arada bulunması muhtemel olduğundan ve açık bir sistem olduğundan gelecekteki yürütme bağlamı tahmin edilemez (bir programın programı). mikrodenetleyici Small, çalışmaya başladıktan sonra daha fazla kod eklemeden çalışmasını tamamen belirler) ve uygulamaların boyutları, kodun çalışmasını kapsamaması durumunda okumayı zorlaştırabileceğinden, yöntemleri mümkün olduğunca kendi kendine yeten hale getirir.
JavaScript Math nesnesiyle matematiksel işlemler
Daha karmaşık matematiksel hesaplamaların matematiksel işlemleri nesnede gruplandırılmıştır. Math
. Bu nesne doğrudan kullanılır; içerdiği yöntemleri veya özellikleri (sabitleri) kullanmak için nesnenin başlatılmasına gerek yoktur.
Math.abs(n)
N parametresinin mutlak değeriMath.acos(n)
N parametresinin arkkosinüsü (radyan cinsinden sonuç)Math.asin(n)
N parametresinin ark sinüsü (radyan cinsinden sonuç)Math.atan(n)
N parametresinin arktanjantı (radyan cinsinden sonuç)Math.atan2(n,m)
N/m'nin arktanjantı (radyan cinsinden sonuç)Math.ceil(n)
Parametreyi yukarıya doğru en yakın tam sayıya yuvarlayınMath.cos(α)
α parametresinin kosinüsü (radyan cinsinden α)Math.E
e numarası (≃2.718281828459045)Math.exp(n)
e parametresine yükseltildi n: enMath.floor(n)
N parametresini en yakın aşağı tam sayıya yuvarlayınMath.log(n)
N parametresinin doğal logaritması (e tabanı)Math.LN2
2'nin doğal logaritması (e tabanı) (≃0.6931471805599453)Math.LN10
10'nin doğal logaritması (e tabanı) (≃2.302585092994046)Math.LOG2E
e'nin 2 tabanlı logaritması (≃1.4426950408889634)Math.LOG10E
e'nin 10 tabanlı logaritması (≃0.4342944819032518)Math.max(a,b,c,…)
Geçirilen parametreler listesinin en büyük değeriMath.min(a,b,c,…)
Geçirilen parametreler listesinin en küçük değeriMath.PI
Sayı π (≃3.141592653589793)Math.pow(n,m)
Birinci parametre n, ikinci parametre m'ye yükseltildi: nmMath.random()
(Neredeyse) 0.0 ile 1.0 arasında rastgele sayıMath.round(n)
N parametresini en yakın tam sayıya yuvarlayınMath.sin(α)
α parametresinin sinüsü (radyan cinsinden α)Math.sqrt(n)
N parametresinin kareköküMath.SQRT1_2
1/2'nin karekökü (≃0.7071067811865476)Math.SQRT2
2'nin karekökü (≃1.4142135623730951)Math.tan(α)
α parametresinin tanjantı (radyan cinsinden α)
AJAX ile sunucudan veri yükleme
IoT'de saklanan bilgilerin çizilmesi için izlenen yöntem, verilerin zaman zaman sunucudan yüklenmesi ve bunların temsil edildiği grafiğin yeniden çizilmesinden oluşur. Sunucudan veri okumak için teknoloji kullanılır AJAX (Eşzamansız JavaScript ve XML) bir nesne aracılığıyla XMLHttpRequest
de JavaScript. Veri grafiğinin çizilmesi bir nesnenin yeniden kullanılmasıyla yapılır SVG bu zaten kodda var HTML ve yüklenen yeni verilere karşılık gelecek şekilde koordinatları değiştirilen bir çizim içerir.
Bu öneri örneğinde, çizimin güncellenmesinin yanı sıra, web sayfasında her grafik için son ölçülen verinin tarihini ve değerini gösteren bir metin de güncellenmektedir.
Sunucu tarafında bilgilerin yer aldığı bir veritabanı bulunmaktadır. IoT'ye bağlı sensörlerin izlediğini. Bu veritabanı nesne isteği tarafından okunur XMLHttpRequest
kodlanmış bilgilerle yanıt vermek JSON biçimi, kullanılan yöntemin adı formatla bir ilişki olduğunu düşündürse de XML.
Polaridad.es'in ilk eğitiminde Nesnelerin İnterneti veri depolama Nesnelerin İnterneti'ne bağlı cihazların sağladığı bilgilerin sunucu tarafından yönetilmesine yönelik bir altyapı örneğini görebilirsiniz. Bu makale serisinde kaynak olarak bir sunucu kullanılıyor Apache programlama dilini kullanabileceğiniz PHP bir veritabanına erişmek için MySQL o MariaDB. IoT'yi desteklemek için kullanılan sunucularda veritabanları bulmak çok yaygındır. MongoDB (NoSQL) ve programlama dili JavaScript üzerinde node.js Yazılım altyapısı olarak.
Bir sonraki işlev, sunucudaki sensörlerden birinden en son verilerin talep edilmesinden sorumludur. İşlev çağrısında nesne argüman olarak kullanılır JavaScript çizilen verileri destekleyen. Aynı grafik birkaç değeri temsil ediyorsa, örneğin görsel olarak bir korelasyon aramak için, sunucuya aynı anda birden fazla değer döndürmesi için bir istekte bulunulabilir; bu, sunucunun çalışma şekli nedeniyle daha uygun bir yöntemdir. HTTP protokolü.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | function consultar_ultimo_valor_sensores(objeto_grafico) { var consulta=‘zona=”+objeto_grafico.sufijo_nombre; var pagina=“ultimo_valor_sensor.php”; var resultado; var ajax; if(window.XMLHttpRequest) { ajax=new XMLHttpRequest(); // ajax=Object.create(XMLHttpRequest); } else // Versiones antiguas de MS Internet Explorer { ajax=new ActiveXObject(“Microsoft.XMLHTTP”); } ajax.onreadystatechange= function() { if(ajax.readyState==4&&ajax.status==200&&ajax.responseType==“json”) { resultado=JSON.parse(ajax.responseText); if(resultado.fecha>objeto_grafico.fecha[objeto_grafico.fecha.length–1]) { // Normalmente se gestionará la respuesta utilizando el objeto redibujar_grafico(objeto_grafico,resultado); // Si los datos son sencillos y tienen una estructura clara puede ser más práctico usarla directamente // redibujar_grafico(objeto_grafico,[resultado.fecha,resultado.temperatura]); } } } ajax.open(“POST”,pagina); ajax.setRequestHeader(“Method”,“POST “+pagina+” HTTP/1.1″); ajax.setRequestHeader(“Content-type”,“application/x-www-form-urlencoded”); ajax.setRequestHeader(“Content-length”,consulta.length); ajax.setRequestHeader(“Connection”,“close”); ajax.send(consulta); } |
Önceki örneğin üçüncü satırında, sunucuya yapılacak sorguda, izlenen yerin adı veya kodu olacak "zone" argümanının iletileceği sorgu hazırlanır. Aynı veri tabanında farklı sensörler (örneğin farklı odalardaki sıcaklığı ölçen termometreler) bir arada bulunabilir. Önceki işleve iletilen parametrenin, yani grafik verilerinin bulunduğu nesnenin, oda adını ("name_suffix") içeren bir özelliği içermesi beklenir.
Önceki kodun 7. ve 14. satırları arasında, nesne XMLHttpRequest
"ajax" değişkeninde saklanır. Nesnenin nasıl oluşturulacağını seçmeden önce arama yaparsınız window
kendi kendine XMLHttpRequest
mevcut değildi (Microsoft Explorer'ın eski sürümlerinde olan bir şeydi ve çok geride olmasına rağmen, nesneyi (daha yerel) sözdizimini kullanarak oluşturmak için alternatiflerin bir örneği olarak hizmet ediyor) Object.create
o new
diğer nesne yönelimli dillerdekine benzer.
Yanıtı anında yönetebilmek için, sunucuya istek yapılmadan önce 15'ten 26'ya kadar olan satırlarda onu işleyen kod hazırlanır.
Yolu sorguyu gerçekleştir HTTP sunucuya oluşur bir bağlantı aç ile open
türü ve sayfayı belirten (isteğe bağlı olarak kullanıcı adı ve şifre), başlıkları hazırla ile protokolün setRequestHeader
y isteği gönder ile send
. Başlık HTTP Content-length
kullanılarak hesaplanan sorgunun uzunluğunu (karakter sayısı) bilmeniz gerekir. length
.
Talep ne zaman AJAX hazır olduğunda, olayla ilişkili işlev yürütülür onreadystatechange
. Önceki örnekte, bir işlev atamak yerine, sunucudan gelen verilerin alımını yönetecek anonim bir işlev anında tanımlanmıştır. Öncelikle 18. satırda isteğin durumunun "tamamlandı" olduğu doğrulanır, bu da değere karşılık gelir. 4
mülkün readyState
durumunun "Tamam" olduğunu HTTP protokolü (kod 200
) mülkten edinilebilecek status
ve gelen veriler şöyle JSON biçimi, mülk danışmanlığı responseType
.
Yanıtın durumunun beklendiği gibi olduğu doğrulandıktan sonra, önceki örneğin 20. satırında sonucu içeren bir nesne oluşturur, metni dönüştürür JSON. Yanıt, döndürülecek bir tarih sağlar; bu, sunucunun gönderdiği sonucun daha önce grafikte temsil edilip edilmediğini görmemize olanak tanır ve bu, 21. satırda doğrulanır. Veriler yeniyse, 23. satırda. Grafiğin yeni bilgilerle yeniden çizilmesinden sorumludur denir.
Bu okuma yöntemini önerirken amaç, verilerin çok sık yenilenmesidir. Sunulan bilgi uzun bir döneme karşılık geliyorsa (bir günün veya bir haftanın sıcaklıkları gibi), mevcut tüm verileri toplayan bir ilk talep uygulanabilir ve ardından örnektekine benzer şekilde bu verileri güncelleyen bir talep uygulanabilir. Dönem muhabiri.
Test için rastgele veriler oluşturun
Tüm sunucu ve istemci altyapısı hazır olduğunda, önceki bölümdeki gibi bir fonksiyon veriyi okumaktan ve onunla grafiği çizmekten sorumlu olacak, ancak Test aşamasında kontrollü bir aralıktaki rastgele sayıları kullanmak daha pratik olabilir yazılan kodun doğru olup olmadığını görmek için Aşağıdaki fonksiyon, son uygulamayı oluştururken veri elde etmek için örnek teşkil edebilir.
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); } |
Yukarıdaki örnek, bilgileri bir veritabanından okumak yerine, bunları rastgele oluşturur ve grafiği çizmekten sorumlu fonksiyona iletir. İcat edilen veri, milisaniye cinsinden değer olarak ifade edilen bir tarih, sensör bilgilerinin kaydedildiği an ve maksimum değer ile minimum değer arasındaki izlenen verilerden oluşan bir vektördür.
Bu örnekte bir tarih üretilirken, buluş tarihindeki tarihe göre bir saniyeye (1000 milisaniye) kadar geciktirilebilmektedir. Gibi Math.random()
0.0 ile 1.0 arasında bir sayı üretir, bu sayının 1000 ile çarpılması 0 ile 1000 arasında bir sayı üretir ve bu sayı daha sonra bir tam sayıya dönüştürülür. Aynı şekilde rastgele sayının aralıkla (maksimum eksi minimum) çarpılıp minimumun eklenmesiyle değer elde edilir.
IoT sensörleri grafiğini SVG grafiğiyle çizin
Temsil etmek istediğimiz değerleri (örnekte sıcaklık) ve bunların koordinat şeklinde birlikte ifade edilebilecek zamansal konumlarını nasıl elde edebileceğimizi gördüğümüz için, aşağıdaki örnekte bir yol çizme fonksiyonu gösterilmektedir. bu noktaları birleştiren ve isteğe bağlı olarak üstteki o çizgiyle sınırlandırılan renkli bir alan. Sonuç aşağıdaki resimdeki gibi olacaktır.
Grafiğin yatay ekseni (X) zamanı, dikey ekseni (Y) ise IoT'ye bağlı sensörlerin izlediği değerleri temsil eder. Yatay aralık birkaç saniyedir, çünkü bu öneride grafik, sensörlerin durumu hakkında neredeyse gerçek zamanlı bilgi sağlamak üzere çok sık (örneğin her saniyede) güncellenmektedir.
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 } |
Önceki kodda iki ilginç yön vardır; ilki, hesaplamaya izin veren hesaplamadır. temsil edilen değer aralığını uyarlayın ve ikincisi mülk inşaatı d
düzendeki noktaların koordinatlarını gösteren (path
).
Temsil edilen değer aralığını uyarlamak için, bunlar minimumdan hareket ettirilir ve görünür büyüklük grafiğin boyutuna karşılık gelecek şekilde ölçeklendirilir.. Zaman durumunda, uzaklık, görüntülemek istediğiniz aralığın en uzun zamandan (geçerli olana en yakın tarih ve saat) (örnekte 20 saniye) çıkarılmasıyla elde edilir. Sıcaklık değerlerinin yer değiştirmesi, alt aralıktan (bir derece) eksi en düşük değere eşittir, böylece aşağıda gösterilen veriler izin verilen en düşük değere en çok benzeyendir ancak izin verilenleri takdir etmemize izin veren bir marj bırakır. . geçmek
Grafiğin yatay koordinatlarını elde etmek için zaman değerlerini çarpan katsayı, grafiğin toplam genişliğinin (örnekte 100 birim) temsil edilen zaman aralığına (örnekte 20 saniye) bölünmesiyle elde edilir. Skaler sıcaklık değerleriyle katsayıyı elde etmek için, temsil edilen aralığın minimum değerin altındaki bir marjdan maksimumun üzerindeki bir marja (her iki durumda da bir derece) kadar gittiği unutulmamalıdır. Bu şekilde dikey ölçek katsayısı, grafiğin yüksekliğinin (örnekte 100 birim) maksimum değer eksi minimum artı üst ve alt kenar boşluğuna bölünmesiyle elde edilir. Bu değerler tamamen negatif sıcaklıklarda gelişebileceğinden, Math.abs()
farkın mutlak değerini kullanmak.
Özellikler d
nesne path
Bir metindeki noktaların koordinatlarının birleştirilmesiyle oluşturulur.. Her koordinat çiftinin önünde bir kod bulunur SVG L
Geçerli konumdan koordinatlarla gösterilen mutlak değere bir çizgi çizen. X ve Y değerleri virgülle ayrılır ve her işlem SVG diğerinden bir boşlukla ayrılır.
Düzeni başlatmak için kodu kullanın M
(mutlak bir koordinata gidin). Kapalı ve dolu grafik durumunda sağ alttan başlarsınız, veri profilini çizen açık grafik durumunda temsil edilen son değerle (en yeni) başlarsınız. Kapalı düzeni tamamlamak için kod kullanılır Z
son nokta olarak, çizginin son noktasıyla aynı X koordinat değerine sahip olanı ve Y koordinatı olarak temsil edilen en küçük değeri ekler.
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 ); } |
Bu örnekte fonksiyon dibujar_grafico()
sayfa yükleme çağrısı olan , test edilecek başlangıç değerlerini alır (son gerçek zamanlı değeri değil) ve verilerin oluşturulacağı aralığı hazırlar: Yatay olarak 20 saniye (20000 ms) ve sıcaklıkta 15°C. -5°C ile +10°C arası dikey, bir derece üst ve alt kenar boşluğu. İki arama yapın actualizar_grafico()
, ilk geçişte true
grafiğin doldurulmuş bir alanı temsil edecek şekilde kapatılması gerektiğini belirten bir argüman olarak ve ikinci çağrıda geçer false
çizgiyi çizmek için. Her durumda nesne path
değiştirilmiş, ilk durumda dolgulu ve kenarlıksız, ikinci durumda ise belirli bir çizgi kalınlığı olan ve dolgusuz, karşılık gelen görünüme sahip olandır.
İşlevi actualizar_grafico()
bir nesne üzerinde çalışmak SVG aşağıdaki kodu konteyner olarak kullanan HTML. Nesne SVG biri çizgiyi çizmek için, diğeri ise doldurulmuş alanı çizmek için iki yol içerir. Web sayfasını yüklerken öğeden <body>
önceki işlev otomatik olarak çağrılır, dibujar_grafico()
etkinlik sayesinde 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> |
Kodun 10. satırında HTML yukarıda, stilde 820 piksellik bir genişlik (örnek olarak) ve 150 piksellik bir yükseklik belirlenmiştir (son versiyonda bunun bir sınıf ve bir belge ile yapılması tavsiye edilecektir) CSS). 13 ve 14. satırların nesnenin boyutunu tanımlaması garip görünüyor SVG %100 genişlik ve yükseklik gibi (pencere boyutlarına en iyi uyan, 100×100). Daha önce de belirttiğimiz gibi bunu yapmanın nedeni her zaman bilinen boyutlarla çalışmak ve temsil edilen değerleri ona göre ayarlamaktır. Diğer alternatifler ise her seferinde grafiğin alanını hesaplamak ve ardından değerleri yeniden ayarlamak veya belgenin uyması gereken grafik için sabit boyutları zorlamak olacaktır.
Koda göre boyutları değişen bir grafik tercih etmiş olmak HTMLözelliği dahil etmek gerekir vector-effect
değeri ile non-scaling-stroke
önceki teklifte olduğu gibi, grafiğin görüntülendiği web sayfasında seçilen 1:1 oranlarını korumaması durumunda çizgi kalınlıklarının deforme olmasını önlemek için.
Grafiği "kırpmak" ve yalnızca seçtiğiniz alanı göstermek için şunu kullanın: viewBox
. Bu durumda grafiğin 0,0'dan başlayan (sol üst köşe) ve aşağı ve sağa doğru 100x100 ölçüsündeki kısmını görmeyi seçtik. Çizimin negatif değerli veya 100'den büyük koordinatlarda yer alan kısmı, nesnede bulunsa dahi web sayfasında görüntülenmeyecektir. SVG
SVG çizimine yeni öğeler ekleme
Önceki örnekte fonksiyon actualizar_grafico()
bir düzen kullan SVG sahipliğin değiştirildiği yer d
Koordinat zincirini ifade eden şey budur. Alternatif, her yeniden çizildiğinde nesnenin tamamını oluşturmak olabilir. İlk seçeneğin avantajı grafik görünümünün (kalınlık veya renk gibi) kodda tanımlanmış olmasıdır. HTMLsınırlaması nesnelerin önceden oluşturulmuş olması gerektiğidir.
SVG nesneleri oluşturmak için şunu kullanın: createElementNS()
dahil edilmesini sağlayan ad alanı. Aşağıdaki örnekte yeni bir metin nesnesi yaratılmıştır (text
) ve bir öğeyle ilişkilidir SVG kodda zaten mevcut olan HTML web sitesinin. Yeni eleman oluşturulduktan sonra özellikleri şu şekilde atanır: setAttribute()
ve eklenir SVG ile 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]); |
Çizim öğelerinin oranını değiştirin
Bir önceki bölümdeki örnekte yer alan fonksiyonla etiketlemeyi denediyseniz, web sayfasındaki nesnenin oranı (orantısı) bozulduğunda metnin deforme göründüğünü görmüşsünüzdür.width
y height
kodun HTML) temsil edilen alanınkine eşit değildir (viewBox
). Orantıyı ayarlamak için nesnenin ölçülerini bilmek gerekir. SVG bunun için nesnenin veya kabın stiline başvurabilirsiniz HTMLeğer nesne SVG bu mülkü devredin. Sahiplik atama transform
nesnelere SVG Orana bağlı olarak deformasyon ölçeklendirme işlemi uygulanarak düzeltilebilir. scale()
burada X'teki katsayı Y'dekinden farklıdır.
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 özellikleri de destekleyen yeni bir kompozit eleman oluşturacak şekilde birçok nesnenin gruplandırılmasına olanak tanır, basit nesneler gibi. Aynı dönüşümü her nesneyi ayrı ayrı uygulamak yerine bir dizi nesneye aynı anda uygulamak için bunları bu kaynağa göre gruplandırabilir ve tek bir özellik uygulayabilirsiniz. transform
hepsine.
Bahsederken açıklandığı gibi SVG formatı, bir grubun elemanları etiketlerin içine alınır <g>
y </g>
. Şuradan eklemek için: JavaScript bir gruba ait öğeler SVG Önceki örnekte görüldüğü gibi kullanılır, appendChild()
yeni nesne tanımlandıktan sonra.
Dönüşümleri uygularken bir orijin oluşturmak için bu özellik nesneler üzerinde kullanılabilir. SVG transform-origin
Değeri dönüşümün başladığı noktanın X ve Y koordinatlarıdır. Dönüşümün orijini için bir değer açıkça belirtilmemişse (web tarayıcısında), koordinatların merkezi kullanılır. Ne yazık ki, bu yazının yazıldığı sırada, dönüşümlerin davranışını varsayılan kaynak dışında bir kaynak kullanarak belirlemek, tarayıcılar arasında homojen değildir ve dikkatli kullanılmalıdır.
Ölçek dönüşümüyle birlikte scale
Rotasyon gibi başkaları da var rotation
ve onunla birlikte hareket translate
, bir teklif grafik temsiline alternatif: Yeni koordinatlar elde etmek yerine bunları kendi uzaylarında temsil edebilir ve grafiği temsil etmek istediğiniz formata uyacak şekilde dönüştürebilirsiniz.
Grafiğe referanslar ekleyin
Artık grafiğin ana kısmı, değerlerin profil ve dolu alanla çizilmesiyle çözüldüğüne göre, okunmasına yardımcı olacak referanslarla tamamlanabilir. Örnek olarak, istenen değerin yanı sıra kabul edilebilir maksimum ve minimum değerleri işaretleyen bazı yatay referanslar (çizgiler) çizerek başlayalım. Açıklandığı gibi, nesneleri listeye eklemeyi seçebilirsiniz. SVG doğrudan JavaScript veya bunları manuel olarak koda ekleyin HTML ve bunları daha sonra şununla değiştirin: 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(); |
Bu yatay referansları temsil ettikleri değeri açıklayan bir metinle etiketlemek mantıklı görünüyor. Metni vurgulamak için arka plandan ve grafikten öne çıkacak dikdörtgenler kullanabilirsiniz. Deformasyonu telafi etmek için metinlerin ölçeklendirilmesi gerekeceğinden, bunların tümü ölçeğin uygulanacağı bir nesne halinde gruplandırılabilir; Bunu bu şekilde yapmanın temel avantajı, grafik kabı (tarayıcı penceresi) yeniden boyutlandırıldığında ve ölçeğin düzelttiği oranı değiştirdiğinde bunları tek bir işlemle değiştirebilmektir.
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(); |
Yukarıdaki örnek kodda birkaç ilginç yön vardır. Her şeyden önce, örneği programlamadan gelen kullanıcılar için daha okunaklı hale getirmek için sabitlerin (global değişkenler) kullanıldığını yorumlayın. mikrodenetleyiciler en C içinde C + +. Daha sonra görüleceği gibi, onu programlamanın en uygun yolu JavaScript Bir üretim sisteminde bu değerleri içerecek nesnelerin ve bu örnekteki referansları veya genel olarak grafiği yönetecek yöntemlerin kullanılması olacaktır.
Öte yandan, daha genel bir kod geliştirilerek, metni ayarlamak için grafiğin oranını düzelten farklı katsayıları hesaplayan ayrı işlevler geliştirilmiştir. proporcion_grafico()
, aralıklarına bağlı olarak değerlerin ölçeği escala()
ve referanslardaki ölçümler gibi mutlak değeri bilinen ölçümler için bir düzeltme faktörü medida_grafico()
.
Bu kodun okunması, grafikleri gerçek zamanlı olarak çizen ve çeşitli grafik bağlamlarında (en azından çeşitli boyut ve oranlarda) sunulmak üzere esnek olması gereken bunun gibi bir uygulamanın çalıştığı bağlamın netleştirilmesine yardımcı olacaktır. Her şeyden önce nesnelerin oluşturulması gerekir. SVG, kodda "manuel olarak" HTML, kod aracılığıyla JavaScript ve her durumda, bu nesnelere yapılan referanslar, bunları manipüle etmek için daha sonra elde edilmelidir. JavaScript böylece yeni grafikler çizilebilir ve önceden çizilmiş bir grafiğin temsili, sunulduğu ortamdaki bir değişikliğe uyarlanabilir.
Bir grafiğin kolayca yorumlanmasına yardımcı olabilecek diğer bir referans, belirli değerleri temsil eden noktalardır (doğrunun düğümleri). Tek bir büyüklüğü temsil ettiğimiz bu örnekte, bir sembolün seçimi kritik değildir, ancak korelasyon aramak için birkaç farklı değer üst üste bindirilirse, renk gibi diğer kaynakları kullanmanın yanı sıra ayırt etmek ilginç olabilir. , farklı semboller çizerek. Çizgi düğümü için kullanılan grafiklerin boyutları ve oranları, örneğin metinlerde olduğu gibi değiştirilmelidir, böylece boyutları mutlak olur ve içerdiği kutunun oranları grafiği değiştirse bile oranları korunur.
Önceki örnekte, çizimin oranını yeniden ölçeklendirmek ve düzeltmek için farklı katsayıların nasıl hesaplanacağını zaten gördük; Grafiğin düğümlerinin veya köşelerinin sembollerinin yönetiminin nasıl uygulanacağına ilişkin olası bir çözüm, nesnelerin saklanması olabilir. SVG bir vektöre dönüştürün ve grafik yeni bir değer okunarak güncellendiğinde veya kapsayıcı yeniden boyutlandırılarak yeniden çizildiğinde konumunu değiştirin. İlk durumda konumunun değiştirilmesi, ikinci durumda ise mülkle olan oranının değiştirilmesi gerekecektir. transform
ve değeri scale
. Aşağıdaki kod işlevin bir modifikasyonudur actualizar_grafico()
grafiğin köşe sembollerinin yeniden konumlandırılmasını dahil etmek.
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); } } |
Fonksiyonda yapılan değişiklikler actualizar_grafico()
yeni işlevi almak için actualizar_grafico_puntos()
Bunlar önceki örneğin kodunda vurgulananlardır. İlk olarak 5. satırda nesnelerin bir vektörünü alıyoruz SVG parametre olarak. Bu vektör, grafiğin yeni düğümlerinde yeniden konumlandırılması gereken sembolleri içerecektir.
39. ve 40. satırlarda merkezin yeni koordinatları atanır, cx
y cy
, temsil edilen değerlerden olanlara. Sembol merkeze dayalı değilse muhtemelen bir uzaklık eklemek gerekli olacaktır. cx
genişliğin yarısı kadar ve cy
bunları tam olarak grafik düğümünde yeniden konumlandırmak için yüksekliğin yarısı kadar.
57'den 61'e kadar olan satırlarda, sol kenar tarafından kesildiği için çizilmeyen koordinatlara karşılık gelen noktalar grafiğin dışında yeniden konumlandırılır. Koordinatı cy
sıfıra ve buna cx
grafiğin sol kısmı gibi pencere tarafından kesildiğinde gösterilmemesi için herhangi bir negatif sayıya (noktadan büyük) SVG.
Grafiği JavaScript ile bir nesneden yönetin
Şu ana kadar açıklanan tüm işlemler, grafiğin yeni sürümlerine daha tipik bir stille yönetmek için bir nesneye entegre edilebilir. JavaScript. Bu uygulama alternatifi, farklı değerlere sahip birçok grafiğin aynı web sayfasına dahil edilmesini basitleştirme avantajına sahiptir.
Uygulamayı tartışmadan önce, nesneler oluşturmanın en yaygın yollarını gözden geçirelim. JavaScript ve IoT sensör grafiklerinin çizilmesine yönelik öneriyi etkileyen fonksiyonların bazı özellikleri.
Nesneleri yaratmanın yeni yolunun zaten açıklanmıştı. JavaScript (versiyon 5'ten beri mevcut) ECMAScript) kullanmaktan oluşur Object.create
"klasik" yerine kullanılmaya alışılması gereken new
Tabii ki hala doğru çalışıyor, ancak amacı daha çok dillerin stilini sınıf tabanlı nesnelerle simüle etmek olsa da (JavaScript (nesnelerin oluşturulmasını prototiplere dayandırır) çalışan bir alternatiften ziyade.
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(); } |
Önceki kod, nesneleri oluşturma arasındaki farkları hatırlamanıza olanak tanır. Object.create
o con new
. Aynı zamanda nesnenin yaratıldığı işlevin de vurgulanmasına hizmet eder. new
Kodun herhangi bir yerinde olabilir, nesnenin başlatılabilmesi için nesnenin zaten mevcut olması gerekir. Object.create
(ES5_Object nesnesi bir işlev değildir).
3. ve 4. satırlarda, nesneyi oluşturan fonksiyondaki özelliklere varsayılan bir değer ayarlamak için new
, her özellik karşılık gelen bağımsız değişkenin değerine atanır veya (||
), eğer hiçbir argüman aktarılmadıysa, yani bunlar tanımsızsa (undefined
), bu durum şu şekilde değerlendirilmektedir: false
varsayılan değer atanır.
Bir fonksiyonun yürütüldüğü bağlam JavaScript akılda tutulması gereken ve başkalarıyla çalıştıktan sonra bu programlama dilini kullanırken kafa karıştırıcı olabilecek iki konuyu gündeme getiriyor; C o C + +, bizim durumumuzda. Bağlam, fonksiyonun kapsamında tanımlanan değişkenleri (ve global olanları) içerir; bu arada, ilginç bir kavramı gündeme getirir, tüm bir programlama stilini oluşturan "kapanışlar". JavaScript. Bununla birlikte, beklenebilir this
Onu tanımlayan kod içinde kullanıldığında nesneye atıfta bulunan, tanımlandığı yürütme bağlamı korunur, ancak kullandığı bağlam, işlevin çağrıldığı bağlamdır. Bu davranış çoğu durumda şeffaftır ancak kafa karıştırıcı olabileceği iki durum vardır: başka bir işlevin içinde tanımlanan bir işlev ve bir nesne olayından çağrılan bir yöntem. 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 */ |
Önceki kodu çalıştırırken, sondaki yorumlu metin konsolda görüntülenir. İşaretli iki çizgi kafa karıştırıcı olabilecek davranışı yansıtır: işlev yürütme bağlamı probar_dentro()
değil probar()
beklenebileceği gibi, ancak window
, aynı adı taşıyan özellikleri değil, genel değişkenleri gösterir. Bu davranışı istemiyorsanız, en üst düzey fonksiyonda bir değişken oluşturup onu atamanız yeterlidir. this
, aşağıdaki kodda olduğu gibi.
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 */ |
Bir olaydan bir yöntem çağrıldığında yürütme içeriğini kontrol etmek için window
örneğin tarayıcı penceresini yeniden boyutlandırmak, başka bir özelliktir. JavaScript: "işlev fabrikalarını", yani başka işlevler üreten işlevleri programlama ve bunları geri döndürme olanağı 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 |
Yukarıdaki örnek kodda yöntem llamar()
de los objeler Contexto
İşi yapmaz ancak işle ilgilenen anonim bir işlev döndürür. Her şeyin beklendiği gibi çalıştığını doğrulamak için işlevin konsolda görüntülediği özellikle aynı adı taşıyan bir genel değişken vardır; Bağlam doğruysa, genel değişkenin değeri değil, özelliğin değeri görüntülenecektir.
JavaScript Cümle sonlarında atladığımız noktalı virgül işaretlerini düzeltmeye çalışın. Bu, rahat bir yazı stili sağlar ancak dikkatli kullanılması gereken iki ucu keskin bir kılıçtır. Çoğu durumda, bunun birkaç satır kaplayan ifadelerde yarattığı istenmeyen etkilerden kaçınmak için parantez kullanabilir veya ifadenin önüne geçebilirsiniz. JavaScript kodu yorumlayacak; Bu nedenle örneğin 8. satırı şunları içerir: function
arka bölgesindeki return
Başka bir satır kullansaydım anlamı çok farklı olurdu. Bana göre en okunabilir çözüm aşağıdaki versiyondaki gibi bir ara (vazgeçilebilir) değişken kullanmaktır; Açıkçası, davranış anlaşıldıktan sonra karar programcıya karşılık gelir.
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); |
Bir ifadeyi işlev olarak değerlendirmek, yani işlevin döndürdüğü değeri değil, işlevi döndürmekle aynı anlamda; son örneğin 21. satırında (önceki örneğin 19. satırındaydı) ile durur clearInterval
ile çağrılan fonksiyon setInterval
. 30 saniye süreyle etki edebilmesi için durdurma ertelenir. setTimeout
, bu da ilk argüman olarak bir fonksiyona ihtiyaç duyar; yürütmeyi parametre olarak teslim etmek clearInterval
periyodik çağrıyı içeren değişkenle (işlevle değil) clearInterval
), son satırdaki anonim işlevin ne için yaratıldığıdır.
İşlev tanımını entegre eden kodun daha kompakt şekilde yazılması (21. satırdaki gibi) veya bana göre daha okunabilir bir yardımcı değişken kullanılması (19. ve 20. satırdaki gibi) arasındaki seçim, performans açısından çok az farklılık gösterir ve daha fazla stile ve okunabilirliğe bağlıdır. Bakım.
Kodu test etmek için, sunucuda veri bulundurmadan önce, istenilen aralıkta rastgele değerler üreteci kullanabilir veya istenen koşullar altında çalışmayı simüle eden kontrollü değerlere sahip tablolar hazırlayabilirsiniz. Aşağıdaki örnekte tüm aralıkta basit bir veri oluşturucu kullanılmaktadır, bu nedenle biraz abartılı görünmektedirler.
Test etmek için şunları yapabilirsiniz: örneğin tam kodunu indirin yazılmış bir web sayfası tarafından oluşturulmuş HTML, stil CSS ve kod JavaScript. İkincisi en alakalı olanıdır, çünkü diğer bileşenler yalnızca minimum düzeyde destek sağlar, çok basitleştirilmiştir ve ilgili bölümlerdeki makalelerde çok daha fazla geliştirilmiştir.
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); } |
Yorum Ekle