สร้างและแก้ไขกราฟิก SVG ของข้อมูลจากเซ็นเซอร์ที่เชื่อมต่อกับ IoT ด้วย JavaScript
ในส่วนสุดท้ายของชุดบทความเกี่ยวกับการวาดภาพ กราฟิกพร้อมข้อมูลจากเซ็นเซอร์ที่เชื่อมต่อกับ Internet of Thingsถึงเวลาที่จะพูดถึงวิธีการสร้างหรือแก้ไขด้วย JavaScript ภาพวาดในรูปแบบ SVG และองค์ประกอบบางส่วน HTML ที่ทำหน้าที่เป็นคอนเทนเนอร์หรือที่นำเสนอข้อมูลเสริมให้กับกราฟิก
ผู้ใช้เป้าหมายของบทช่วยสอนนี้ควรจะสร้างโปรไฟล์การเขียนโปรแกรมอิเล็กทรอนิกส์และคอมพิวเตอร์ ไมโครคอนโทรลเลอร์พวกเขาอาจจะไม่คุ้นเคย HTML, CSS o SVG; ด้วยเหตุนี้ในภาคก่อนหน้านี้จึงมีการแนะนำภาษาหรือเทคโนโลยีที่เกี่ยวข้องโดยย่อ ในส่วนสุดท้ายนี้ วิธีการจะแตกต่างออกไปเล็กน้อย เนื่องจากผู้อ่านรู้วิธีการเขียนโปรแกรมอย่างแน่นอน จึงเป็นไปได้ที่การใช้ภาษา C + + อะไรอย่างไร JavaScriptแบ่งปันไวยากรณ์พื้นฐานด้วย C และสามารถใช้เป็นข้อมูลอ้างอิงเพื่อข้ามแนวคิดการเขียนโปรแกรมพื้นฐานส่วนใหญ่ได้ และมุ่งเน้นไปที่ความแตกต่างและการใช้งานเฉพาะที่เราสนใจในการสร้างกราฟิกเซ็นเซอร์ใน IoT
ชื่อนี้ให้เบาะแสถึงความแตกต่างแรก: JavaScript มันเป็นภาษาโปรแกรม ต้นฉบับ (ยัติภังค์) และเป็นเช่นนั้น ตีความไม่จำเป็นต้องคอมไพล์มัน บริบทที่ ต้นฉบับ (เช่น เว็บเบราว์เซอร์) จะอ่าน แปล และดำเนินการตามคำสั่งซื้อ พูดให้ถูกคือ ในกรณีส่วนใหญ่จะมีก การรวบรวมรันไทม์ (JIT)แต่สำหรับกระบวนการเขียนโค้ด JavaScript มันไม่ส่งผลกระทบต่อเรา เราเพียงแค่เขียนโค้ดและมันก็สามารถทำงานได้
ชื่อนี้ยังมีความสับสนครั้งแรก: JavaScript ไม่มีความสัมพันธ์ใดๆ เลยแม้แต่น้อย ชวา. ในขั้นต้นเมื่อมีการพัฒนา Netscape สำหรับเบราว์เซอร์ มันถูกเรียกว่า Mocha ตัวแรก จากนั้นจึงเรียกว่า LiveScript ที่สับสนน้อยกว่า หลังจากที่ประสบความสำเร็จในการใช้งานในเบราว์เซอร์และก้าวข้ามมันไป มันก็ได้รับมาตรฐานเป็น ECMAScript (ในการ ECMA-262 เวอร์ชัน 6 ในขณะที่เขียน) เพื่อให้เป็นกลางเกี่ยวกับเบราว์เซอร์ที่ใช้งาน ปัจจุบันยังมีมาตรฐาน มาตรฐาน ISO จากเวอร์ชัน 5, 2011 (ISO / IEC 16262: 2011 ในขณะที่เขียนบทความ)
ตัวแปร ชนิดข้อมูลพื้นฐาน และออบเจ็กต์ใน JavaScript
ไม่เหมือนสิ่งที่เกิดขึ้น เช่น ใน C + +, en JavaScript ชนิดข้อมูลไม่รวมอยู่ในการประกาศตัวแปร และประเภทที่เกี่ยวข้องกับตัวแปรไม่ได้รับการแก้ไข คุณสามารถกำหนดค่าประเภทอื่นได้ตลอดการทำงานของโปรแกรม
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
|
ในตัวอย่างก่อนหน้านี้ มีการประกาศตัวแปร "thing" (โดยไม่ระบุประเภทข้อมูล) จากนั้นจึงกำหนดข้อมูลประเภทอื่นและปรึกษากับ typeof
ประเภทนั้น JavaScript ที่เขาตีความแล้ว หากต้องการดีบั๊กโค้ด คุณสามารถเขียนลงในคอนโซลตรวจสอบของเว็บเบราว์เซอร์ (ซึ่งจะไม่ส่งผลต่อการนำเสนอของเว็บ) ด้วย console.log()
.
หากต้องการบังคับให้แปลงข้อมูลเป็นประเภทใดประเภทหนึ่ง โดยเฉพาะข้อความเป็นตัวเลข คุณสามารถใช้ฟังก์ชันต่างๆ เช่น parseInt()
o parseFloat()
ซึ่งแปลงเป็นจำนวนเต็มหรือเลขทศนิยมตามลำดับ การแปลงที่ตรงกันข้ามสามารถทำได้ด้วย String()
แม้ว่าจะไม่น่าจะจำเป็นเนื่องจากการแปลงอัตโนมัติก็เพียงพอแล้ว กับ parseFloat()
ตัวอย่างเช่น คุณสามารถรับค่าของคุณสมบัติเว็บเพจ เช่น ความกว้างหรือความสูงของออบเจ็กต์ที่มีหน่วยรวมอยู่ด้วย ในลักษณะนี้การแสดงออก parseFloat("50px");
จะส่งคืนค่า 50 ซึ่งเป็นค่าตัวเลข
En JavaScript ไม่มีความแตกต่างระหว่างเครื่องหมายคำพูดคู่และเดี่ยว; ชนิดข้อมูลในทั้งสองกรณีคือ string
และแต่ละรายการสามารถรวมอีกรายการหนึ่งได้โดยไม่ต้องใช้โค้ด Escape
1
2
3
4
5
6
7
8
9
10
|
var texto;
console.log(typeof texto); // Debería mostrar string en la undefined
texto=“esto es un texto”;
console.log(typeof texto); // Debería mostrar string en la consola
texto=‘A’;
console.log(typeof texto); // Debería mostrar string en la consola
texto=“esto es un ‘texto'”;
console.log(typeof texto); // Debería mostrar string en la consola
texto=‘”A”‘;
console.log(typeof texto); // Debería mostrar string en la consola
|
ในตัวอย่างก่อนหน้านี้ จะเห็นได้ว่าเมื่อมีการประกาศตัวแปร (มีอยู่) แต่ไม่ได้กำหนดค่าใดๆ ตัวแปรจะมีประเภทข้อมูลที่ไม่ได้กำหนดไว้ (undefined
). วัตถุที่ไม่ได้กำหนดมีค่า null
; นั่นคือวัตถุนั้นมีอยู่แต่ไม่มีค่า ตัวแปรที่อ้างอิงถึงจะไม่มี typeof
undefined
แต่ object
. วัตถุยังสามารถว่างเปล่าได้ กล่าวคือ ไม่ใช่ null แต่ไม่มีคุณสมบัติใดๆ
ไปยัง กำหนดวัตถุใน JavaScript ถูกปิดด้วยเครื่องหมายปีกกา ({
y }
) คุณสมบัติหรือวิธีการคั่นด้วยเครื่องหมายโคลอน (:
) ชื่อคุณสมบัติ ค่าคุณสมบัติ และด้วยเครื่องหมายจุลภาค (,
) คุณสมบัติที่แตกต่างกัน คุณสามารถค้นหาข้อมูลเพิ่มเติมเกี่ยวกับวิธีการแสดงวัตถุนี้ได้ในบทความเรื่อง รูปแบบ JSON.
แม้ว่าคุณจะสามารถใช้ไวยากรณ์ที่อาจทำให้คุณคิดอย่างอื่นได้ en JavaScript ไม่มีคลาสใดนอกจากต้นแบบนั่นคือเพื่อให้อ็อบเจ็กต์สืบทอดคุณสมบัติและวิธีการ อ็อบเจ็กต์อื่นจะถูกสร้างขึ้น (ต้นแบบ) ที่อ็อบเจ็กต์อื่น (ลูก) ใช้เป็นข้อมูลอ้างอิง ไวยากรณ์ที่ใกล้เคียงกับสไตล์ของ JavaScript ที่จะใช้ต้นแบบก็คือ Object.create
แม้ว่ามันจะเป็นไปได้ (และบางครั้งก็มีประโยชน์) ด้วยเช่นกัน new
เช่นเดียวกับภาษาเชิงวัตถุอื่นๆ
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));
|
ไปยัง แบบสอบถามว่าวัตถุหนึ่งเป็นอินสแตนซ์ของอีกวัตถุหนึ่งหรือไม่หากคุณใช้มันเป็นต้นแบบ หรือหากคุณสืบทอดคุณสมบัติของมัน พูดง่ายๆ ก็คือคุณสามารถใช้ได้ instanceof
(สร้างด้วย. new
) หรือ isPrototypeOf
(สร้างด้วย. Object.create
) ซึ่งจะประเมินเป็นจริงเมื่อวัตถุใช้ต้นแบบและเป็นเท็จเมื่อไม่ได้ใช้
เมื่อวัตถุถูกสร้างขึ้นโดยใช้วัตถุอื่นเป็นต้นแบบ นั่นคือ เมื่อวัตถุได้รับการสร้างอินสแตนซ์แล้ว ก็สามารถทำได้ เพิ่มคุณสมบัติใหม่หรือแทนที่คุณสมบัติต้นแบบ ใช้ไวยากรณ์จุดเหมือนใน gato.peso=2.5
.
La อาร์เรย์ใน JavaScript พวกเขาแตกต่างจากที่คุณอาจรู้จัก C. ขั้นแรก มีการประกาศโดยไม่จำเป็นต้องระบุความยาว มีเพียงเครื่องหมายเปิดและปิดวงเล็บเหลี่ยมเท่านั้น ([
y ]
) ส่วนประกอบสามารถมีความหลากหลายได้ (ประเภทข้อมูลที่แตกต่างกันในอาร์เรย์เดียวกัน) และสามารถเพิ่มองค์ประกอบใหม่ได้โดยไม่มีขีดจำกัด เมทริกซ์ของ 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
|
// 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
|
ดังที่เห็นในตัวอย่างก่อนหน้านี้ หากต้องการทราบว่าตัวแปรสอดคล้องกับอินสแตนซ์ของอาร์เรย์หรือไม่ (ซึ่งเป็นวัตถุอาร์เรย์) คุณสามารถใช้ instanceof
ตามที่ได้ถูกนำมาใช้กับอ็อบเจ็กต์ทั่วไปแล้ว หรือในเวอร์ชันล่าสุดของ JavaScript คุณสามารถหันไป Array.isArray()
ในการเข้าถึงองค์ประกอบของอาร์เรย์คุณสามารถใช้ดัชนีของมัน (matriz[7]
) หรือตามชื่อคุณสมบัติที่มีชื่ออยู่ในวงเล็บเหลี่ยม (matriz["nombre"]
) หรือด้วยไวยากรณ์จุดปกติสำหรับวัตถุ (matriz.nombre
). เนื่องจากชื่อเป็นสตริงข้อความ จึงสามารถใช้นิพจน์รวมถึงตัวแปรในการเขียนได้ หากต้องการวนซ้ำอาร์เรย์ด้วยคุณสมบัติ สามารถใช้การวนซ้ำที่มีรูปแบบได้ 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
*/
|
เป็นเรื่องที่น่าสนใจสำหรับวัตถุประสงค์ของเราในการรักษา วัตถุ Date
โดยทำหน้าที่เป็นตัวแทนและจัดการวันและเวลา JavaScript. วัตถุสามารถสร้างอินสแตนซ์ได้โดยไม่ต้องใช้ข้อมูล ดังนั้น จะใช้วันที่และเวลาปัจจุบัน หรืออาจสร้างขึ้นโดยระบุวันที่เป็นค่าก็ได้ ทั้งในหน่วยมิลลิวินาทีตั้งแต่วันที่ 1 มกราคม 1970 (เช่น เวลายูนิกซ์หรือเวลา POSIX แต่แสดงเป็นมิลลิวินาทีแทนวินาที) หรือระบุค่าแยกปี เดือน วัน ชั่วโมง...
วัตถุประกอบด้วยชุดที่สมบูรณ์ของ วิธีการสอบถามหรือตั้งวันที่และเวลา:
-
now()
ส่งกลับวันที่และเวลาปัจจุบันแสดงเป็นมิลลิวินาทีตั้งแต่วันที่ 1 มกราคม 1970 -
getTime()
|setTime()
รับหรือเปลี่ยนแปลงค่าเวลาเป็นมิลลิวินาทีตามลำดับตั้งแต่วันที่ 1 มกราคม 1970 การใช้valueOf()
ซึ่งเป็นวิธีการที่มีอยู่ในออบเจ็กต์ส่วนใหญ่ โดยจะได้รับค่าของออบเจ็กต์ Date ที่สอดคล้องกันด้วย เช่นgetTime()
กับ เวลายูนิกซ์หรือเวลา POSIX แสดงเป็นนางสาว -
getMilliseconds()
|setMilliseconds()
ใช้เพื่อค้นหาหรือตั้งค่าส่วนเศษส่วนของมิลลิวินาทีของออบเจ็กต์Date
ซึ่งมันจะถูกดำเนินการ หากพิจารณาแล้วค่าที่ได้รับจะอยู่ระหว่าง 0 ถึง 999 แต่สามารถกำหนดค่าที่มากกว่าได้ซึ่งจะสะสมเป็นวันที่และเวลาทั้งหมด ดังนั้นเช่นเดียวกับวิธี get ที่เหลือก็ทำหน้าที่เพิ่มมูลค่าของวัตถุDate
(หรือลดลงหากใช้ค่าลบ) -
getSeconds()
|setSeconds()
ส่งกลับหรือเปลี่ยนแปลงค่าวินาทีของวัตถุตามลำดับDate
. -
getMinutes()
|setMinutes()
ใช้เพื่อปรึกษาหรือกำหนดนาทีของวัตถุDate
. -
getHours()
|setHours()
ช่วยให้คุณสามารถปรึกษาหรือแก้ไขชั่วโมง (ตั้งแต่ 0 ถึง 23) ของวัตถุDate
. -
getDay()
ส่งกลับวันในสัปดาห์สำหรับวันที่ ซึ่งแสดงเป็นค่าตั้งแต่ 0 ถึง 6 (วันอาทิตย์ถึงวันเสาร์) -
getDate()
|setDate()
ส่งกลับหรือเปลี่ยนวันของเดือนของออบเจ็กต์Date
ที่มันถูกนำไปใช้ -
getMonth()
|setMonth()
ใช้เพื่อปรึกษาหรือแก้ไขหมายเลขเดือนของวัตถุDate
. -
getFullYear()
|setFullYear()
ค้นหาหรือตั้งค่าปีบนวัตถุที่มีวันที่และเวลา
วิธีการก่อนหน้านี้ของ Date
รวมเวอร์ชัน UTC เพื่อให้สามารถทำงานได้โดยตรงกับเวลาสากลโดยไม่ต้องคำนวณระหว่างกาล ในความหมายนั้น เช่น getHours()
มีเวอร์ชัน getUTCHours()
o getMilliseconds()
ทางเลือก getUTCMilliseconds()
เพื่อทำงานแทนเวลาราชการ (กฎหมาย) หรือเวลาสากล กับ getTimezoneOffset()
คุณสามารถทราบความแตกต่างระหว่างเวลาสากลกับเวลาราชการในท้องถิ่นได้
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;
|
ฟังก์ชันจาวาสคริปต์
หากคุณกำลังอ่านข้อความนี้ แสดงว่าคุณรู้วิธีการเขียนโปรแกรมอย่างแน่นอน ไมโครคอนโทรลเลอร์ en C en o C + + และรู้แนวคิดของฟังก์ชัน แม้ว่าแนวคิดพื้นฐานจะเหมือนกันก็ตามค่ะ JavaScript วิธีกำหนดและใช้งานแตกต่างกันเล็กน้อย เริ่มแรกมีกล่าวไว้แล้วว่า JavaScript ไม่ได้ใช้ชนิดข้อมูลอย่างชัดเจน ดังนั้นคุณไม่จำเป็นต้องระบุเมื่อกำหนดฟังก์ชัน. เพื่อติดตาม ฟังก์ชันไม่จำเป็นต้องมีชื่อ แต่สามารถระบุชื่อได้. สามารถเชื่อมโยงกับตัวแปรเพื่อเรียกใช้ได้ แต่ก็อาจไม่จำเป็นเช่นกัน เนื่องจากในบางครั้ง การเรียกใช้ทันทีจึงมีประโยชน์ โดยจะมีการเพิ่มวงเล็บและพารามิเตอร์ไว้หลังคำจำกัดความของฟังก์ชัน
หากต้องการกำหนดฟังก์ชัน ให้นำหน้า function
ถ้ามี ให้เขียนชื่อ อาร์กิวเมนต์ (พารามิเตอร์ที่ส่งไปยังฟังก์ชัน) ในวงเล็บ และโค้ดที่จะดำเนินการเมื่อมีการเรียกใช้ฟังก์ชันในวงเล็บปีกกา
1
2
3
4
5
|
function doble(numero)
{
var resultado=numero*2;
return resultado;
}
|
แน่นอนว่าในตัวอย่างก่อนหน้านี้ ตัวแปร "ผลลัพธ์" ไม่จำเป็นเลย แต่เป็นข้อแก้ตัวที่ดีที่จะจดจำ ขอบเขตตัวแปรซึ่งทำงานได้ตามที่คุณคาดหวัง: ตัวแปร "result" มีอยู่ภายในฟังก์ชัน "double" เท่านั้น ใน JavaScript ยังสามารถใช้ได้ let
แทน var
เพื่อกำหนดขอบเขตตัวแปรตามบริบทของบล็อกโค้ด (อยู่ในวงเล็บปีกกา {
y }
)
เมื่อพูดถึงอ็อบเจ็กต์ในส่วนที่แล้ว พื้นฐานบางอย่างขาดหายไป: คุณสมบัติถูกกำหนดไว้แล้ว แต่ยังไม่ได้กำหนดวิธีการ อย่างที่คาดไว้, วิธีการวัตถุเป็นฟังก์ชันไม่มีชื่อและใช้ (เรียกใช้) จากชื่อ (คุณสมบัติ) ที่กำหนดโดยคำจำกัดความของวัตถุ
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”);
}
}
|
ในตัวอย่างก่อนหน้านี้ มีเมธอด "view_temperature" อยู่แล้ว ซึ่งแสดงค่าของคุณสมบัติ "current_temperature" ผ่านคอนโซล มันไม่มีประโยชน์มากนัก แต่มันให้แนวคิดที่สมบูรณ์ยิ่งขึ้นว่าคำจำกัดความของวัตถุเป็นอย่างไร JavaScript.
ในการเข้าถึงวิธีการของวัตถุ (ฟังก์ชัน) ไปยังคุณสมบัติของมัน ให้ใช้ this
ดังตัวอย่างก่อนหน้าในบรรทัดที่ 11 เมื่อใช้คุณสมบัติ "current_temperature"
เข้าถึง Document Object Model (DOM) ด้วย JavaScript
จาก JavaScript คุณสามารถเข้าถึงเนื้อหาของหน้าเว็บที่เพจนั้นทำงานอยู่ รวมถึงบางแง่มุมของเบราว์เซอร์ที่แสดงเพจนั้น แม้ว่าจะไม่ใช่ทรัพยากรระบบก็ตาม โครงสร้างข้อมูลที่รองรับคุณสมบัติและวิธีการเข้าถึงจาก JavaScript ส่วนหนึ่งของวัตถุหน้าต่างโดยเฉพาะเนื้อหาของออบเจ็กต์ (เอกสาร HTML) สอดคล้องกับวัตถุ document
. แม้ว่าบางครั้งจะใช้เพื่อความชัดเจน แต่ก็ไม่จำเป็นต้องนำหน้าหน้าต่างไปยังวิธีการหรือคุณสมบัติเพื่ออ้างอิงถึงสิ่งเหล่านั้น แต่ก็เพียงพอแล้ว เช่น ใช้ document
ไม่จำเป็นต้องเขียนชื่อของวัตถุรูทเหมือนใน window.document
ตราบใดที่หน้าต่างปัจจุบันถูกอ้างอิง
รูปแบบที่ใช้มากที่สุดของ ค้นหาวัตถุภายในเอกสาร HTML มันเป็นไปตามวิธีการ getElementById()
ซึ่งรหัสที่ระบุเมื่อสร้างโค้ดถูกส่งผ่านเป็นอาร์กิวเมนต์ HTML. จากสิ่งที่อธิบายไว้ในส่วนก่อนหน้านี้ มันง่ายที่จะสรุปว่าคุณสามารถเข้าถึงส่วนประกอบภายในออบเจ็กต์ได้เช่นกัน document
ใช้ไวยากรณ์จุด (document.componente
) หรือวงเล็บเหลี่ยมที่ใช้ทั้งชื่อ (document["componente"]
) มีประโยชน์มากที่สุด เช่น ดัชนีตัวเลข ใช้งานยากและใช้งานไม่ได้เมื่อเข้าถึงเนื้อหาของหน้าเว็บที่เขียนด้วยตนเอง
กับ JavaScript คุณสามารถ รับองค์ประกอบที่มีองค์ประกอบอื่น (องค์ประกอบหรือโหนดหลัก) ให้คำปรึกษาเกี่ยวกับทรัพย์สินของคุณ parentNode
หรือทรัพย์สินของคุณ parentElement
ความแตกต่างก็คือองค์ประกอบหลัก (parentElement
) ขององค์ประกอบสุดท้ายของสตริง DOM มันเป็นโมฆะ (null
) และโหนดพาเรนต์ (parentNode
) คือตัวเอกสารเอง (document
).
ไปยัง แก้ไขเนื้อหาขององค์ประกอบ HTMLเช่น ฉลาก <div>
,ก็สามารถใช้ได้ innerHTML
และหากต้องการเปลี่ยนคุณสมบัติคุณสามารถเลือกมอบหมายคลาสอื่นให้กับมันได้ className
หรือเปลี่ยนแปลงคุณสมบัติเป็นรายบุคคลด้วย style
. การดูสไตล์ที่แสดงโดยองค์ประกอบบนหน้าเว็บนั้นไม่ได้มีประโยชน์เสมอไป style
เนื่องจากอาจขึ้นอยู่กับหลายปัจจัยหรือไม่ได้ระบุไว้อย่างชัดเจน หากต้องการตรวจสอบสไตล์ขององค์ประกอบที่แสดงบนหน้าเว็บในที่สุด จะใช้เมธอด getComputedStyle.
ไปยังองค์ประกอบเอกสาร HTML สามารถกำหนดคลาสได้หลายคลาสเพื่อกำหนดลักษณะและพฤติกรรมของมัน จัดการรายการคลาสของวัตถุจาก JavaScript คุณสามารถหันไป classList
ที่นำเสนอวิธีการต่างๆ add
เพื่อเพิ่มคลาสใหม่ในรายการ remove
เพื่อเอามันออก toggle
เพื่อแทนที่หรือศึกษาเนื้อหาของรายการคลาสขององค์ประกอบด้วย item
และ contains
ซึ่งส่งคืนคลาสที่ครอบครองตำแหน่งที่แน่นอนในรายการและค่า true
o false
มีคลาสใดคลาสหนึ่งอยู่ในรายการหรือไม่
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”)
}
|
ในตัวอย่างก่อนหน้านี้จะอยู่ด้วย getElementById
วัตถุที่คุณต้องการจัดการ (องค์ประกอบ <div>
สำหรับเขา id
) ก่อนที่จะเปลี่ยนรูปลักษณ์ เนื้อหาจะถูกลบโดยกำหนดด้วย innerHTML
สตริงข้อความว่าง จะถูกกำหนดคลาสใหม่ด้วย className
และมีการปรับเปลี่ยนสไตล์ด้วย style
ขึ้นอยู่กับค่าของเนื้อหา (อุณหภูมิ) การเปลี่ยนสี (ถ้ามี) ผ่านคุณสมบัติ color
. เมื่อกำหนดลักษณะแล้ว ค่าจะถูกเขียนโดยใช้อีกครั้ง innerHTML
.
ในส่วนที่สองของตัวอย่างด้านบน (บรรทัดที่ 9 ถึง 19) มีการเข้าถึงองค์ประกอบโค้ด HTML โดยใช้ไวยากรณ์ document[]
และทรัพย์สิน id
ขององค์ประกอบเพื่อแก้ไขรายการคลาสด้วยวิธี classList.remove()
และด้วยวิธีการclassList.add()
ขึ้นอยู่กับผลลัพธ์ของการสืบค้นหลายอย่างที่ดำเนินการในการดำเนินการแบบมีเงื่อนไข ซึ่งการเปรียบเทียบโดยใช้ classList.contains()
.
จะไปเมื่อไหร่ อ้างถึงองค์ประกอบ HTML หลาย ครั้งตลอดทั้งโค้ด JavaScript, นิดหน่อย มีประสิทธิภาพมากขึ้นในการกำหนดให้กับตัวแปร หรือใช้ดัชนีแทนชื่อเนื่องจากมิฉะนั้นจะเป็นวิธีการที่คุณจะใช้ JavaScript เพื่อให้ได้มาในแต่ละครั้งจะต้องค้นหาชื่อ ซึ่งใช้เวลานานกว่าการเข้าถึงตัวแปรเล็กน้อย
ไปยัง เพิ่มวัตถุใหม่ให้กับเอกสาร HTMLสามารถสร้างได้ก่อนด้วยวิธี createElement
de document
แล้วนำมารวมเข้ากับองค์ประกอบที่เหลือตรงจุดต้นไม้ที่จำเป็นด้วย appendChild
. เพื่อสร้างวัตถุ XMLเหมือนกับวัตถุ SVG ที่เราใช้วาดกราฟของเซ็นเซอร์ IoT คุณก็สามารถใช้ได้ createElementNS
(NS สำหรับ พื้นที่ชื่อ). ตามที่อธิบายไว้เมื่อพูดถึงรูปแบบ SVGเนมสเปซที่สอดคล้องกับเนมสเปซ (สำหรับเวอร์ชันปัจจุบัน) คือ http://www.w3.org/2000/svg
ซึ่งควรจะส่งต่อไปยัง createElementNS
เป็นอาร์กิวเมนต์พร้อมกับประเภทองค์ประกอบ svg
, ในกรณีนี้.
Una ทางเลือกในการ innerHTML
เพื่อเพิ่มข้อความเป็นเนื้อหาให้กับองค์ประกอบเอกสาร HTML คือวิธีการ createTextNode()
วัตถุ document
. ด้วยทางเลือกนี้คุณสามารถทำได้ สร้างข้อความใหม่ (ซึ่งจะเข้าถึงได้ในภายหลังหากถูกกำหนดให้กับตัวแปร) ที่รวมอยู่ในแผนผังวัตถุด้วยวิธี appendChild()
. ในขณะที่ ทางเลือกในการ appendChild()
ซึ่งเพิ่มเนื้อหาใหม่ต่อท้ายสิ่งที่มีอยู่แล้วในโหนดที่เพิ่มเข้าไป คุณสามารถใช้ วิธีการ insertBefore()
ซึ่งเพิ่มวัตถุใหม่ข้างหน้าวัตถุที่มีอยู่ สวมใส่ insertBefore()
แทนที่ appendChild()
จัดเตรียมวิธีการที่ทำหน้าที่ เช่น เพื่อ จัดเรียงวัตถุใหม่ต่อหน้าวัตถุที่มีอยู่ เมื่อองค์ประกอบต้องอยู่ข้างหน้าอีกองค์ประกอบหนึ่ง (ดังในรายการ) หรือปกปิดหรือถูกบดบังในโครงสร้างกราฟิกซึ่งมีองค์ประกอบใกล้กับพื้นหน้าหรือพื้นหลังมากขึ้น
ตอบสนองต่อเหตุการณ์ด้วย JavaScript
เมื่อถึงทางของ ใช้หน้าเว็บเป็นคอนเทนเนอร์สำหรับกราฟเซ็นเซอร์ที่เชื่อมต่อกับ IoT มันถูกนำมาใช้ onload
ในฉลาก <body>
เพื่อเริ่มวาดกราฟ คุณสมบัตินี้เชื่อมโยงกับวัตถุรหัส HTML, หมายถึง เหตุการณ์ที่เกิดขึ้น JavaScript. ตามที่อธิบายไปแล้ว มันจะรันฟังก์ชันเมื่อโหลดเพจแล้ว แม้ว่าจะมีการเชื่อมโยงกับรหัสก็ตาม HTML เพื่อให้จำไว้มากขึ้น มันสามารถเขียนเป็นโค้ดได้ JavaScript ในขณะที่ body.onload=dibujar;
กำลัง dibujar
ชื่อของฟังก์ชันที่ควรเริ่มต้นเมื่อโหลดหน้าเว็บ
ในเวอร์ชันล่าสุดของ JavaScript เหตุการณ์สามารถเชื่อมโยงกับฟังก์ชันที่ใช้ได้ addEventListener
ด้วยรูปแบบ objeto.addEventListener(evento,función);
หรือใช้ไวยากรณ์ objeto.evento=función;
ซึ่งใช้งานได้กับการใช้งานแบบเก่าด้วย หากต้องการยกเลิกการเชื่อมโยงฟังก์ชันที่เกี่ยวข้องกับกิจกรรม คุณต้องมี removeEventListener
ซึ่งมีรูปแบบเดียวกับ addEventListener
.
JavaScript สามารถตอบสนองต่อเหตุการณ์ต่างๆ มากมายที่อาจเกิดขึ้นบนหน้าเว็บได้ ตัวอย่างเช่น สามารถตรวจจับได้เมื่อมีการคลิกองค์ประกอบ HTML กับ onmousedown
หรือเมื่อคลิกด้วย onclick
เมื่อมีการกดปุ่ม onkeydown
โดยใช้งานแถบเลื่อนด้วย onscroll
. เพื่อจุดประสงค์ของเราก็เพียงพอแล้วสำหรับเรา ตรวจจับการโหลดหน้าเว็บด้วย onload
และปรับขนาดด้วย onresize
. เราจะเชื่อมโยงเหตุการณ์เหล่านี้กับวัตถุต่างๆ body
y window
เดล DOM ตามลำดับ คนแรกสามารถกำหนดได้ในรหัส HTMLตามที่เห็นและอันที่สองภายในโค้ด JavaScript ภายในฟังก์ชันที่เรียกโดยตัวแรกและด้วยรูปแบบ window.onresize=redimensionar;
กำลัง redimensionar
ฟังก์ชั่นที่จะเรียกทุกครั้งที่หน้าต่างเปลี่ยนขนาด
วิ่งหลังจากช่วงเวลาหนึ่ง
JavaScript มีแหล่งข้อมูลสองแห่งสำหรับ การดำเนินการเลื่อนออกไป: setTimeout
ซึ่งดำเนินการฟังก์ชันหลังจากช่วงเวลาหนึ่งและ setInterval
ซึ่งจะรันฟังก์ชันทุกๆ ช่วงเวลาหนึ่ง. ทั้งสองวิธีต้องการเป็นพารามิเตอร์ (1) ฟังก์ชันที่เรียกใช้และ (2) ช่วงเวลาที่แสดงเป็นมิลลิวินาที หากต้องการหยุดการดำเนินการ คุณสามารถกำหนดผลลัพธ์ที่ส่งคืนโดยฟังก์ชันเหล่านี้ให้กับตัวแปรและส่งผ่านเป็นอาร์กิวเมนต์ให้ clearTimeout
หรือเพื่อ clearInterval
เมื่อคุณไม่ต้องการเรียกใช้อีกครั้ง (หรือเมื่อคุณไม่ต้องการให้ดำเนินการเป็นครั้งแรก) setTimeout
o setInterval
ตามลำดับ
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
}
|
ในตัวอย่างก่อนหน้านี้ มีการแนะนำวิธีการ alert
ซึ่งทำหน้าที่แสดงป้ายเตือน แม้ว่าในอดีตจะมีการใช้กันอย่างแพร่หลาย แต่ปัจจุบันเกือบจะถูกแบนจากโค้ดแล้ว JavaScript เนื่องจากความก้าวร้าว (ล่วงล้ำ) การปิดบังหน้าเว็บด้วยกล่องโต้ตอบ
ในโปรแกรมที่เขียนขึ้นเพื่อ ไมโครคอนโทรลเลอร์ ของชุดเล็กๆ (เช่น ชุดที่อยู่ในจาน) Arduino Uno) เป็นเรื่องปกติที่จะใช้ตัวแปรร่วม ดังตัวอย่างก่อนหน้านี้ JavaScriptเนื่องจากโค้ดนั้นสั้นและไม่ทำให้เกิดความสับสนเป็นพิเศษ เนื่องจากหลายครั้งมีการใช้งานฟังก์ชันเฉพาะกิจและเนื่องจากการใช้ตัวแปรโกลบอลทำให้สามารถคาดการณ์การใช้หน่วยความจำด้วยวิธีที่ง่ายและใช้งานง่าย ซึ่งมีความสำคัญอย่างยิ่งในระบบที่มีทรัพยากรน้อย . แทน, en JavaScript เป็นเรื่องปกติที่จะลดการใช้ตัวแปรร่วมให้เหลือน้อยที่สุด เนื่องจากไม่จำเป็นต้องเร่งการใช้หน่วยความจำ เนื่องจากทำงานตามปกติบน ซีพียู ด้วยทรัพยากรที่เหนือกว่ามาก MCUเนื่องจากมีแนวโน้มที่จะอยู่ร่วมกับโค้ดของบุคคลที่สามจำนวนมากซึ่งจะต้องทำงานโดยไม่รบกวนและเนื่องจากเป็นระบบเปิด บริบทการดำเนินการในอนาคตจึงไม่สามารถคาดเดาได้ (โปรแกรมของ ไมโครคอนโทรลเลอร์ Small กำหนดการทำงานของมันโดยสมบูรณ์โดยไม่ต้องเพิ่มโค้ดเพิ่มเติมเมื่อเปิดใช้งาน) และเนื่องจากขนาดของแอปพลิเคชันอาจทำให้การอ่านยากหากโค้ดไม่ได้ห่อหุ้มการทำงานของมัน ทำให้วิธีการต่างๆ มีอยู่ในตัวเองมากที่สุด
การดำเนินการทางคณิตศาสตร์ด้วยวัตถุ JavaScript Math
การดำเนินการทางคณิตศาสตร์ของการคำนวณทางคณิตศาสตร์ที่ซับซ้อนมากขึ้นจะถูกจัดกลุ่มไว้ในวัตถุ Math
. วัตถุนี้ถูกใช้โดยตรง ไม่จำเป็นต้องยกตัวอย่างเพื่อใช้วิธีการหรือคุณสมบัติ (ค่าคงที่) ที่รวมอยู่
Math.abs(n)
ค่าสัมบูรณ์ของพารามิเตอร์ nMath.acos(n)
อาร์คโคไซน์ของพารามิเตอร์ n (ผลลัพธ์เป็นเรเดียน)Math.asin(n)
อาร์กไซน์ของพารามิเตอร์ n (ผลลัพธ์เป็นเรเดียน)Math.atan(n)
อาร์กแทนเจนต์ของพารามิเตอร์ n (ผลลัพธ์เป็นเรเดียน)Math.atan2(n,m)
อาร์กแทนเจนต์ของ n/m (ผลลัพธ์เป็นเรเดียน)Math.ceil(n)
ปัดเศษพารามิเตอร์ให้เป็นจำนวนเต็มที่ใกล้ที่สุดขึ้นMath.cos(α)
โคไซน์ของพารามิเตอร์ α (α เป็นเรเดียน)Math.E
หมายเลขอี (≃2.718281828459045)Math.exp(n)
e ยกให้เป็นพารามิเตอร์ n: enMath.floor(n)
ปัดเศษพารามิเตอร์ n ให้เป็นจำนวนเต็มที่ใกล้ที่สุดลงMath.log(n)
ลอการิทึมธรรมชาติ (ฐาน e) ของพารามิเตอร์ nMath.LN2
ลอการิทึมธรรมชาติ (ฐาน e) ของ 2 (≃0.6931471805599453)Math.LN10
ลอการิทึมธรรมชาติ (ฐาน e) ของ 10 (≃2.302585092994046)Math.LOG2E
ลอการิทึมฐาน 2 ของ e (≃1.4426950408889634)Math.LOG10E
ลอการิทึมฐาน 10 ของ e (≃0.4342944819032518)Math.max(a,b,c,…)
ค่าสูงสุดของรายการพารามิเตอร์ที่ส่งผ่านMath.min(a,b,c,…)
ค่าที่น้อยที่สุดของรายการพารามิเตอร์ที่ส่งผ่านMath.PI
หมายเลข π (≃3.141592653589793)Math.pow(n,m)
พารามิเตอร์แรก n ยกให้เป็นพารามิเตอร์ตัวที่สอง m: nmMath.random()
(เกือบ) ตัวเลขสุ่มระหว่าง 0.0 ถึง 1.0Math.round(n)
ปัดเศษพารามิเตอร์ n เป็นจำนวนเต็มที่ใกล้ที่สุดMath.sin(α)
ไซน์ของพารามิเตอร์ α (α เป็นเรเดียน)Math.sqrt(n)
รากที่สองของพารามิเตอร์ nMath.SQRT1_2
รากที่สองของ 1/2 (≃0.7071067811865476)Math.SQRT2
รากที่สองของ 2 (≃1.4142135623730951)Math.tan(α)
แทนเจนต์ของพารามิเตอร์ α (α ในหน่วยเรเดียน)
โหลดข้อมูลจากเซิร์ฟเวอร์ด้วย AJAX
วิธีการที่ใช้เพื่อดึงข้อมูลที่จัดเก็บไว้ใน IoT ประกอบด้วยการโหลดข้อมูลจากเซิร์ฟเวอร์เป็นครั้งคราวและวาดกราฟใหม่ที่ใช้แสดงข้อมูลเหล่านั้น ในการอ่านข้อมูลจากเซิร์ฟเวอร์จะใช้เทคโนโลยี AJAX (จาวาสคริปต์แบบอะซิงโครนัสและ XML) ผ่านวัตถุ XMLHttpRequest
de JavaScript. การพล็อตกราฟข้อมูลทำได้โดยการนำวัตถุกลับมาใช้ใหม่ SVG ซึ่งมีอยู่ในโค้ดอยู่แล้ว HTML และมีพล็อตซึ่งมีการแก้ไขพิกัดเพื่อให้สอดคล้องกับข้อมูลใหม่ที่โหลด
ในตัวอย่างของข้อเสนอนี้ นอกเหนือจากการอัปเดตภาพวาดแล้ว ข้อความบนหน้าเว็บยังได้รับการอัปเดตซึ่งแสดงวันที่และค่าของข้อมูลที่วัดล่าสุดสำหรับแต่ละกราฟด้วย
ทางฝั่งเซิร์ฟเวอร์จะมีฐานข้อมูลที่ประกอบด้วยข้อมูล ที่เซ็นเซอร์ที่เชื่อมต่อกับ IoT ได้รับการตรวจสอบแล้ว ฐานข้อมูลนี้ถูกอ่านโดยคำขอวัตถุ XMLHttpRequest
ตอบสนองด้วยข้อมูลที่เข้ารหัสใน รูปแบบ JSONแม้ว่าชื่อของวิธีการที่ใช้จะบ่งบอกถึงความสัมพันธ์กับรูปแบบก็ตาม XML.
ในบทช่วยสอน polaridad.es แรกเกี่ยวกับ การจัดเก็บข้อมูลไอโอที คุณสามารถดูตัวอย่างโครงสร้างพื้นฐานในการจัดการข้อมูลจากฝั่งเซิร์ฟเวอร์โดยอุปกรณ์ที่เชื่อมต่อกับ Internet of Things ในชุดบทความนี้ เซิร์ฟเวอร์ถูกใช้เป็นทรัพยากร อาปาเช่ ซึ่งคุณสามารถใช้ภาษาการเขียนโปรแกรมได้ PHP เพื่อเข้าถึงฐานข้อมูล MySQL o MariaDB. บนเซิร์ฟเวอร์ที่ใช้เพื่อรองรับ IoT การค้นหาฐานข้อมูลเป็นเรื่องปกติมาก MongoDB (NoSQL) และภาษาการเขียนโปรแกรม JavaScript บน Node.js เป็นโครงสร้างพื้นฐานซอฟต์แวร์
ฟังก์ชั่นต่อไปมีหน้าที่ในการขอข้อมูลล่าสุดจากเซ็นเซอร์ตัวใดตัวหนึ่งจากเซิร์ฟเวอร์ ในการเรียกใช้ฟังก์ชัน วัตถุจะถูกใช้เป็นอาร์กิวเมนต์ JavaScript ที่รองรับข้อมูลที่วาดออกมา หากกราฟเดียวกันแสดงค่าหลายค่า เช่น เพื่อค้นหาความสัมพันธ์ด้วยภาพ สามารถส่งคำขอไปยังเซิร์ฟเวอร์เพื่อส่งคืนหลายค่าพร้อมกัน ซึ่งเป็นวิธีการที่เหมาะสมที่สุดเนื่องจากวิธีการทำงานของเซิร์ฟเวอร์ โปรโตคอล HTTP.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
function consultar_ultimo_valor_sensores(objeto_grafico)
{
var consulta=‘zona=”+objeto_grafico.sufijo_nombre;
var pagina=“ultimo_valor_sensor.php”;
var resultado;
var ajax;
if(window.XMLHttpRequest)
{
ajax=new XMLHttpRequest(); // ajax=Object.create(XMLHttpRequest);
}
else // Versiones antiguas de MS Internet Explorer
{
ajax=new ActiveXObject(“Microsoft.XMLHTTP”);
}
ajax.onreadystatechange=
function()
{
if(ajax.readyState==4&&ajax.status==200&&ajax.responseType==“json”)
{
resultado=JSON.parse(ajax.responseText);
if(resultado.fecha>objeto_grafico.fecha[objeto_grafico.fecha.length–1])
{
// Normalmente se gestionará la respuesta utilizando el objeto
redibujar_grafico(objeto_grafico,resultado);
// Si los datos son sencillos y tienen una estructura clara puede ser más práctico usarla directamente
// redibujar_grafico(objeto_grafico,[resultado.fecha,resultado.temperatura]);
}
}
}
ajax.open(“POST”,pagina);
ajax.setRequestHeader(“Method”,“POST “+pagina+” HTTP/1.1″);
ajax.setRequestHeader(“Content-type”,“application/x-www-form-urlencoded”);
ajax.setRequestHeader(“Content-length”,consulta.length);
ajax.setRequestHeader(“Connection”,“close”);
ajax.send(consulta);
}
|
ในบรรทัดที่สามของตัวอย่างก่อนหน้านี้ มีการจัดเตรียมแบบสอบถามที่จะทำกับเซิร์ฟเวอร์โดยอาร์กิวเมนต์ "โซน" จะถูกส่งผ่านค่าซึ่งจะเป็นชื่อหรือรหัสของสถานที่ที่ถูกตรวจสอบเนื่องจากข้อมูลเกี่ยวกับ พื้นที่อาจอยู่ร่วมกันในฐานข้อมูลเดียวกันเซ็นเซอร์ต่างกัน (เช่น เครื่องวัดอุณหภูมิที่วัดอุณหภูมิในห้องต่างกัน) พารามิเตอร์ที่ส่งผ่านไปยังฟังก์ชันก่อนหน้า ซึ่งเป็นออบเจ็กต์ที่มีข้อมูลแผนภูมิ คาดว่าจะรวมคุณสมบัติที่มีชื่อของห้อง ("name_suffix")
ระหว่างบรรทัดที่ 7 ถึง 14 ของโค้ดก่อนหน้า วัตถุ XMLHttpRequest
ซึ่งถูกเก็บไว้ในตัวแปร "ajax" ก่อนที่จะเลือกวิธีสร้างออบเจ็กต์ คุณต้องค้นหา window
ถ้า XMLHttpRequest
ไม่พร้อมใช้งาน (สิ่งที่เกิดขึ้นใน explorer ของ Microsoft เวอร์ชันเก่าและแม้ว่าจะยังล้าหลังอยู่มาก แต่ก็ทำหน้าที่เป็นตัวอย่างทางเลือกในการสร้างวัตถุโดยใช้ไวยากรณ์ (เนทิฟมากกว่า)) Object.create
o new
คล้ายกับภาษาเชิงวัตถุอื่นๆ
เพื่อให้สามารถจัดการการตอบสนองได้ทันที โค้ดที่จัดการจะถูกจัดเตรียมไว้ในบรรทัดที่ 15 ถึง 26 ก่อนที่จะทำการร้องขอไปยังเซิร์ฟเวอร์
ทางของ ดำเนินการสอบถาม HTTP ไปยังเซิร์ฟเวอร์ประกอบด้วย เปิดการเชื่อมต่อ กับ open
ระบุประเภทและหน้า (เป็นทางเลือกชื่อผู้ใช้และรหัสผ่าน) เตรียมส่วนหัว ของโปรโตคอลด้วย setRequestHeader
y ส่งคำขอ กับ send
. ส่วนหัว HTTP Content-length
คุณจะต้องทราบความยาวของแบบสอบถาม (จำนวนอักขระ) ที่คำนวณโดยใช้ length
.
เมื่อมีการร้องขอ AJAX พร้อมแล้ว ฟังก์ชันที่เกี่ยวข้องกับเหตุการณ์จะถูกดำเนินการ onreadystatechange
. แทนที่จะกำหนดฟังก์ชัน ในตัวอย่างก่อนหน้านี้ ฟังก์ชันที่ไม่ระบุชื่อจะถูกกำหนดทันทีซึ่งจะจัดการการรับข้อมูลที่มาจากเซิร์ฟเวอร์ ก่อนอื่นในบรรทัดที่ 18 มีการตรวจสอบว่าสถานะของคำขอเป็น "เสร็จสิ้น" ซึ่งสอดคล้องกับค่า 4
ของทรัพย์สิน readyState
ว่าสถานะเป็น "ตกลง" ของ โปรโตคอล HTTP (รหัส 200
) ที่สามารถหาได้จากทรัพย์สิน status
และข้อมูลที่ได้มานั้นก็คือ รูปแบบ JSON,ปรึกษาเรื่องทรัพย์สิน responseType
.
เมื่อตรวจสอบแล้วว่าสถานะของการตอบกลับเป็นไปตามที่คาดไว้ในบรรทัดที่ 20 ของตัวอย่างก่อนหน้า สร้างออบเจ็กต์พร้อมผลลัพธ์ โดยแปลงข้อความ JSON. การตอบกลับระบุวันที่ที่จะส่งคืนซึ่งช่วยให้เราดูว่าผลลัพธ์ที่เซิร์ฟเวอร์ส่งไปนั้นเคยแสดงไว้ในกราฟก่อนหน้านี้หรือไม่ซึ่งตรวจสอบแล้วในบรรทัดที่ 21 หากข้อมูลเป็นข้อมูลใหม่ ในบรรทัดที่ 23 ฟังก์ชันที่ มีหน้าที่รับผิดชอบในการวาดกราฟใหม่โดยเรียกข้อมูลใหม่ว่า
แนวคิดในการนำเสนอวิธีการอ่านนี้คือข้อมูลจะถูกรีเฟรชบ่อยมาก หากข้อมูลที่นำเสนอสอดคล้องกับระยะยาว (เช่น อุณหภูมิของวันหรือหนึ่งสัปดาห์) คุณสามารถดำเนินการคำขอเริ่มแรกเพื่อรวบรวมข้อมูลที่มีอยู่ทั้งหมด จากนั้นคำขอหนึ่งรายการจะอัปเดตในลักษณะเดียวกับในตัวอย่าง นักข่าวประจำเดือน
สร้างข้อมูลสุ่มเพื่อการทดสอบ
เมื่อโครงสร้างพื้นฐานเซิร์ฟเวอร์และไคลเอนต์ทั้งหมดพร้อม ฟังก์ชันเหมือนกับในส่วนก่อนหน้าจะทำหน้าที่อ่านข้อมูลและวาดกราฟด้วย แต่ ในขั้นตอนการทดสอบ การใช้ตัวเลขสุ่มภายในช่วงที่มีการควบคุมอาจเป็นประโยชน์มากกว่า เพื่อดูว่าโค้ดที่เขียนนั้นถูกต้องหรือไม่ ฟังก์ชันต่อไปนี้สามารถใช้เป็นตัวอย่างในการรับข้อมูลขณะสร้างแอปพลิเคชันขั้นสุดท้าย
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);
}
|
แทนที่จะอ่านข้อมูลจากฐานข้อมูล ตัวอย่างด้านบนจะสร้างข้อมูลเหล่านั้นแบบสุ่มและส่งต่อไปยังฟังก์ชันที่รับผิดชอบในการวาดกราฟ ข้อมูลที่ประดิษฐ์ขึ้นเป็นเวกเตอร์ที่เกิดขึ้นจากวันที่ที่แสดงเป็นค่าเป็นมิลลิวินาที โมเมนต์ของการบันทึกข้อมูลเซ็นเซอร์ และข้อมูลที่ถูกตรวจสอบ ซึ่งอยู่ระหว่างค่าสูงสุดและค่าต่ำสุด
ในตัวอย่างนี้ เมื่อสร้างวันที่อาจล่าช้าได้ถึงหนึ่งวินาที (1000 มิลลิวินาที) เมื่อเทียบกับวันที่ ณ เวลาที่ประดิษฐ์ เช่น Math.random()
สร้างตัวเลขระหว่าง 0.0 ถึง 1.0 เมื่อคูณด้วย 1000 จะสร้างตัวเลขระหว่าง 0 ถึง 1000 ซึ่งจะถูกแปลงเป็นจำนวนเต็ม ในทำนองเดียวกัน ค่าจะได้จากการคูณตัวเลขสุ่มด้วยช่วง (สูงสุดลบต่ำสุด) แล้วบวกค่าต่ำสุด
วาดกราฟเซ็นเซอร์ IoT ด้วยพล็อต SVG
เนื่องจากเราได้เห็นแล้วว่าเราสามารถรับค่าที่เราต้องการแสดง (อุณหภูมิในตัวอย่าง) และตำแหน่งชั่วคราวซึ่งสามารถแสดงร่วมกันในรูปแบบของพิกัดได้อย่างไร ตัวอย่างด้านล่างแสดงฟังก์ชันในการวาดเส้นทาง ที่เชื่อมจุดเหล่านั้นและอาจเลือกพื้นที่สีที่คั่นด้วยเส้นนั้นที่ด้านบน ผลลัพธ์จะเป็นเช่นภาพต่อไปนี้
แกนนอน (X) ของกราฟแสดงเวลาและแกนตั้ง (Y) ค่าที่เซ็นเซอร์ที่เชื่อมต่อกับ IoT ติดตามอยู่ ช่วงเวลาในแนวนอนคือไม่กี่วินาที เนื่องจากในข้อเสนอนี้ กราฟได้รับการอัปเดตบ่อยมาก (เช่น ทุกวินาที) เพื่อให้ข้อมูลที่เกือบจะเรียลไทม์เกี่ยวกับสถานะของเซ็นเซอร์
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
}
|
ในโค้ดก่อนหน้านี้มีสองประเด็นที่น่าสนใจ ประการแรกคือการคำนวณที่อนุญาต ปรับช่วงของค่าที่แสดง และประการที่สอง การก่อสร้างทรัพย์สิน d
ซึ่งระบุพิกัดของจุดบนเค้าโครง (path
).
เพื่อปรับช่วงของค่าที่แสดง ค่าเหล่านั้นจะถูกย้ายจากค่าต่ำสุดและปรับขนาดเพื่อให้ขนาดที่มองเห็นสอดคล้องกับขนาดของกราฟ. ในกรณีของเวลา ค่าชดเชยจะได้มาจากการลบช่วงที่คุณต้องการแสดงออกจากเวลาที่ยาวที่สุด (วันที่และเวลาที่ใกล้เคียงกับเวลาปัจจุบันมากที่สุด) (ในตัวอย่าง 20 วินาที) การกระจัดของค่าอุณหภูมิจะเป็นค่าของช่วงล่าง (หนึ่งองศา) ลบด้วยค่าต่ำสุด ดังนั้นข้อมูลที่แสดงด้านล่างนี้จึงใกล้เคียงกับค่าต่ำสุดที่อนุญาตมากที่สุด แต่เหลือระยะขอบที่ทำให้เราสามารถชื่นชมค่าที่ทำ . ผ่าน
ค่าสัมประสิทธิ์ที่คูณค่าเวลาเพื่อให้ได้พิกัดแนวนอนของกราฟนั้นได้มาจากหารความกว้างรวมของกราฟ (ในตัวอย่าง 100 หน่วย) ด้วยช่วงเวลาที่แสดง (20 วินาทีในตัวอย่าง) เพื่อให้ได้ค่าสัมประสิทธิ์ที่มีค่าอุณหภูมิสเกลาร์ จะต้องจำไว้ว่าช่วงที่แสดงไปจากระยะขอบที่ต่ำกว่าค่าต่ำสุดไปจนถึงระยะขอบที่สูงกว่าค่าสูงสุด หนึ่งองศาในทั้งสองกรณี ด้วยวิธีนี้ ค่าสัมประสิทธิ์สเกลแนวตั้งเป็นผลมาจากการหารความสูงของกราฟ (100 หน่วยในตัวอย่าง) ด้วยค่าสูงสุด ลบค่าต่ำสุดบวกกับระยะขอบบนและล่าง เนื่องจากค่าเหล่านี้สามารถพัฒนาได้อย่างสมบูรณ์ที่อุณหภูมิติดลบ เราจึงใช้ Math.abs()
เพื่อใช้ค่าสัมบูรณ์ของผลต่าง
สถานที่ให้บริการ d
วัตถุ path
มันถูกสร้างขึ้นโดยการต่อพิกัดของจุดต่างๆ เข้าด้วยกันในข้อความ. พิกัดแต่ละคู่จะมีรหัสนำหน้า SVG L
ซึ่งลากเส้นจากตำแหน่งปัจจุบันไปยังค่าสัมบูรณ์ที่ระบุโดยพิกัด ค่า X และ Y คั่นด้วยเครื่องหมายจุลภาคและการดำเนินการแต่ละรายการ SVG ถูกคั่นด้วยช่องว่างจากถัดไป
หากต้องการเริ่มเค้าโครง ให้ใช้โค้ด M
(ย้ายไปที่พิกัดสัมบูรณ์). ในกรณีของพล็อตที่ปิดและเต็ม คุณจะเริ่มต้นที่มุมขวาล่าง ในกรณีของพล็อตที่เปิดซึ่งดึงโปรไฟล์ข้อมูล คุณจะเริ่มต้นด้วยค่าสุดท้ายที่แสดง (ค่าล่าสุด) เพื่อเสร็จสิ้นโครงร่างแบบปิด ให้ใช้โค้ด Z
เพิ่มเป็นจุดสุดท้ายของจุดที่มีค่าพิกัด X เดียวกันกับจุดสุดท้ายของเส้นและเมื่อพิกัด Y จะแสดงค่าที่เล็กที่สุด
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
);
}
|
ในตัวอย่างนี้ ฟังก์ชัน dibujar_grafico()
ซึ่งเป็นการเรียกใช้การโหลดเพจ รับค่าเริ่มต้นเพื่อทดสอบ (ไม่ใช่ค่าเรียลไทม์ล่าสุด) และเตรียมช่วงที่ข้อมูลจะแสดงผล: 20 วินาที (20000 ms) ในแนวนอน และ 15°C ใน แนวตั้งตั้งแต่ -5°C ถึง +10°C โดยมีขอบบนและล่าง XNUMX องศา โทรไปสองครั้ง actualizar_grafico()
ในรอบแรก true
เป็นอาร์กิวเมนต์ ซึ่งบ่งชี้ว่าควรปิดแผนภูมิเพื่อแสดงพื้นที่ที่ถูกเติม และในการเรียกครั้งที่สองก็ผ่านไป false
เพื่อวาดเส้น ในแต่ละกรณีวัตถุ path
modified คืออันที่มีลักษณะที่สอดคล้องกัน โดยมีการเติมและไม่มีเส้นขอบในกรณีแรก และมีความหนาของเส้นที่แน่นอนและไม่มีการเติมในกรณีที่สอง
ฟังก์ชั่น actualizar_grafico()
ทำงานบนวัตถุ SVG ซึ่งใช้โค้ดต่อไปนี้เป็นคอนเทนเนอร์ HTML. วัตถุ SVG มีสองเส้นทาง เส้นทางหนึ่งสำหรับลากเส้น และอีกเส้นทางหนึ่งสำหรับวาดพื้นที่ที่เต็ม เมื่อโหลดหน้าเว็บจากองค์ประกอบ <body>
ฟังก์ชั่นก่อนหน้าจะถูกเรียกโดยอัตโนมัติ dibujar_grafico()
ขอบคุณเหตุการณ์ 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>
|
ในบรรทัดที่ 10 ของรหัส HTML ด้านบนมีการกำหนดความกว้าง (เป็นตัวอย่าง) 820 px และความสูง 150 px ในสไตล์ (สิ่งที่ในเวอร์ชันสุดท้ายจะแนะนำให้ทำกับคลาสและเอกสาร CSS). ดูเหมือนแปลกที่บรรทัดที่ 13 และ 14 กำหนดขนาดของวัตถุ SVG เช่น ความกว้างและความสูง 100% (ซึ่งตรงกับขนาดหน้าต่างมากที่สุด คือ 100×100) ดังที่ได้กล่าวไปแล้ว เหตุผลในการทำเช่นนี้คือการทำงานกับมิติข้อมูลที่ทราบอยู่เสมอและปรับค่าที่แสดงให้เหมาะสม อีกทางเลือกหนึ่งคือการคำนวณพื้นที่ของกราฟในแต่ละครั้งแล้วปรับค่าใหม่หรือบังคับขนาดคงที่ของกราฟซึ่งเอกสารจะต้องยึดตาม
เลือกใช้กราฟที่มีขนาดเปลี่ยนแปลงตามรหัส HTMLจำเป็นต้องรวมทรัพย์สินด้วย vector-effect
ด้วยค่า non-scaling-stroke
เพื่อป้องกันไม่ให้ความหนาของเส้นผิดรูปเมื่อกราฟไม่รักษาสัดส่วน 1:1 ที่เลือกไว้บนหน้าเว็บที่แสดงกราฟนั้น ดังที่เกิดขึ้นในข้อเสนอก่อนหน้า
หากต้องการ "ครอบตัด" กราฟและแสดงเฉพาะพื้นที่ที่คุณเลือก ให้ใช้ viewBox
. ในกรณีนี้ เราได้เลือกที่จะดูส่วนของกราฟที่เริ่มต้นที่ 0,0 (มุมซ้ายบน) และวัดขนาด 100x100 ลงและไปทางขวา ส่วนของภาพวาดที่อยู่ในพิกัดที่มีค่าลบหรือมากกว่า 100 จะไม่ปรากฏบนหน้าเว็บแม้ว่าจะมีอยู่ในวัตถุก็ตาม SVG
เพิ่มองค์ประกอบใหม่ให้กับการวาด SVG
ในตัวอย่างก่อนหน้านี้ ฟังก์ชัน actualizar_grafico()
ใช้เค้าโครง SVG ซึ่งมีการเปลี่ยนแปลงความเป็นเจ้าของ d
ซึ่งเป็นสิ่งที่แสดงออกถึงลูกโซ่พิกัด ทางเลือกอื่นคือสร้างวัตถุทั้งหมดทุกครั้งที่วาดใหม่ ข้อดีของตัวเลือกแรกคือลักษณะกราฟิก (เช่น ความหนาหรือสี) ถูกกำหนดไว้ในโค้ด HTMLข้อจำกัดคือต้องสร้างออบเจ็กต์ไว้ก่อนหน้านี้
หากต้องการสร้างวัตถุ SVG ให้ใช้ createElementNS()
ซึ่งช่วยให้รวมถึง เนมสเปซ. ในตัวอย่างด้านล่าง ออบเจ็กต์ข้อความใหม่จะถูกสร้างขึ้น (text
) และเชื่อมโยงกับองค์ประกอบ SVG ซึ่งมีอยู่แล้วในโค้ด HTML ของเว็บไซต์ เมื่อสร้างองค์ประกอบใหม่แล้ว คุณสมบัติจะถูกกำหนดด้วย setAttribute()
และถูกเพิ่มเข้าไป SVG กับ 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]);
|
ปรับเปลี่ยนสัดส่วนขององค์ประกอบการวาด
หากคุณได้ลองติดป้ายกำกับด้วยฟังก์ชันตามตัวอย่างในส่วนที่แล้ว คุณจะเห็นว่าข้อความดูผิดรูปเมื่อสัดส่วนของวัตถุบนหน้าเว็บ (width
y height
ของรหัส HTML) ไม่เท่ากับพื้นที่ที่แสดง (viewBox
). เพื่อปรับสัดส่วน จำเป็นต้องรู้การวัดของวัตถุ SVG ซึ่งคุณสามารถปรึกษารูปแบบของวัตถุหรือภาชนะได้ HTMLถ้าวัตถุ SVG โอนทรัพย์สินนี้ การมอบหมายความเป็นเจ้าของ transform
เพื่อวัตถุ SVG ซึ่งขึ้นอยู่กับสัดส่วน การเสียรูปสามารถแก้ไขได้โดยการปรับขนาด scale()
โดยที่สัมประสิทธิ์ใน X แตกต่างจากค่าสัมประสิทธิ์ใน Y
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
function
rotular
(
objeto_grafico,
texto,
inicio=[0,0],
altura=10.0,
proporcion=1.0,
tipo_letra=“SircuitoRegularMedium”,
color_texto=“#000000”,
color_fondo=“#FFFFFF”
)
{
var escala_horizontal=parseFloat(getComputedStyle(objeto_grafico).height)/parseFloat(getComputedStyle(objeto_grafico).width);
nuevo_objeto_svg=document.createElementNS(“http://www.w3.org/2000/svg”,‘text’);
nuevo_objeto_svg.setAttribute(“transform”,“scale(“+escala_horizontal+“,1.0)”); // scale permite cambiar la escala en X e Y
//nuevo_objeto_svg.setAttribute(“transform”,”scaleX(“+escala_horizontal+”)”); // Como se sabe que sólo cambia la escala en X, se puede usar scaleX
nuevo_objeto_svg.setAttribute(“x”,inicio[0]);
nuevo_objeto_svg.setAttribute(“y”,inicio[1]);
nuevo_objeto_svg.setAttribute(“font-family”,tipo_letra);
nuevo_objeto_svg.setAttribute(“font-size”,altura);
nuevo_objeto_svg.setAttribute(“fill”,color_texto);
nuevo_objeto_svg.textContent=texto;
objeto_grafico.appendChild(nuevo_objeto_svg);
}
//rotular(document.getElementById(“cosa_svg”),”HOLA”,[10,10]);
|
SVG อนุญาตให้จัดกลุ่มวัตถุหลายรายการเพื่อสร้างองค์ประกอบคอมโพสิตใหม่ที่รองรับคุณสมบัติด้วยเหมือนกับวัตถุธรรมดาๆ หากต้องการใช้การแปลงแบบเดียวกันกับชุดของออบเจ็กต์ในคราวเดียวแทนที่จะแยกแต่ละออบเจ็กต์ คุณสามารถจัดกลุ่มตามทรัพยากรนี้และใช้คุณสมบัติเดียว transform
ถึงพวกเขาทั้งหมด
ดังที่ได้อธิบายไว้เมื่อกล่าวถึง รูปแบบ SVGองค์ประกอบของกลุ่มจะอยู่ภายในป้ายกำกับ <g>
y </g>
. เพื่อเพิ่มจาก JavaScript องค์ประกอบให้กับกลุ่ม SVG ถูกใช้ดังที่เห็นในตัวอย่างก่อนหน้านี้ appendChild()
เมื่อกำหนดวัตถุใหม่แล้ว
ในการสร้างจุดเริ่มต้นเมื่อใช้การแปลง สามารถใช้คุณสมบัติกับออบเจ็กต์ได้ SVG transform-origin
ซึ่งค่าคือพิกัด X และ Y ของจุดที่การแปลงเริ่มต้นขึ้น หากไม่ได้ระบุค่าสำหรับต้นกำเนิดของการแปลงอย่างชัดเจน (ในเว็บเบราว์เซอร์) ระบบจะใช้จุดศูนย์กลางของพิกัด น่าเสียดายที่ในขณะที่เขียนนี้ การระบุพฤติกรรมของการแปลงโดยใช้แหล่งที่มาอื่นที่ไม่ใช่ค่าเริ่มต้นนั้นไม่เหมือนกันในเบราว์เซอร์ทุกตัว และควรใช้ด้วยความระมัดระวัง
พร้อมกับการเปลี่ยนแปลงขนาดด้วย scale
ยังมีอย่างอื่นอีกเช่นการหมุนด้วย rotation
และการเคลื่อนไหวด้วย translate
ซึ่งเสนอก ทางเลือกแทนการแสดงกราฟ: แทนที่จะได้รับพิกัดใหม่ คุณสามารถแสดงพิกัดในพื้นที่ของตนเองและแปลงกราฟให้พอดีกับรูปแบบที่คุณต้องการแสดง
เพิ่มการอ้างอิงไปยังแผนภูมิ
ตอนนี้ส่วนหลักของกราฟได้รับการแก้ไขแล้วโดยการวางแผนค่าด้วยโปรไฟล์และพื้นที่ที่กรอกข้อมูลแล้ว ก็สามารถกรอกข้อมูลอ้างอิงที่ช่วยในการอ่านได้ ตามตัวอย่าง เริ่มต้นด้วยการวาดเส้นอ้างอิงแนวนอน (เส้น) ที่ทำเครื่องหมายค่าสูงสุดและต่ำสุดที่ยอมรับได้ตลอดจนค่าที่ต้องการ ตามที่อธิบายไว้ คุณสามารถเลือกเพิ่มออบเจ็กต์ลงในได้ SVG ตรงจาก JavaScript หรือรวมไว้ในรหัสด้วยตนเอง HTML และแก้ไขในภายหลังด้วย 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();
|
ดูเหมือนสมเหตุสมผลที่จะติดป้ายกำกับการอ้างอิงแนวนอนเหล่านี้ด้วยข้อความที่ชี้แจงค่าที่เป็นตัวแทน หากต้องการเน้นข้อความ คุณสามารถใช้สี่เหลี่ยมที่โดดเด่นจากพื้นหลังและกราฟิกได้ เนื่องจากข้อความจะต้องได้รับการปรับขนาดเพื่อชดเชยการเสียรูป ข้อความทั้งหมดจึงสามารถจัดกลุ่มเป็นวัตถุที่จะใช้มาตราส่วนได้ ข้อได้เปรียบหลักของการทำเช่นนี้คือสามารถปรับเปลี่ยนได้ในการดำเนินการครั้งเดียว หากคอนเทนเนอร์กราฟ (หน้าต่างเบราว์เซอร์) ถูกปรับขนาดและเปลี่ยนสัดส่วนที่มาตราส่วนถูกต้อง
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();
|
มีแง่มุมที่น่าสนใจหลายประการในโค้ดตัวอย่างข้างต้น ก่อนอื่น ให้แสดงความคิดเห็นว่ามีการใช้ค่าคงที่ (ตัวแปรส่วนกลาง) เพื่อให้ผู้ใช้ที่มาจากการเขียนโปรแกรมสามารถอ่านตัวอย่างได้ง่ายขึ้น ไมโครคอนโทรลเลอร์ en C en o C + +. ดังที่จะเห็นในภายหลัง วิธีที่ดีที่สุดในการตั้งโปรแกรมมัน JavaScript มันจะเป็นการใช้วัตถุที่มีค่าและวิธีการเหล่านี้ที่จะจัดการการอ้างอิงในตัวอย่างนี้หรือกราฟโดยทั่วไปในระบบการผลิต
ในทางกลับกัน การพัฒนาโค้ดทั่วไปให้ก้าวหน้ายิ่งขึ้น มีการพัฒนาฟังก์ชันแยกต่างหากที่คำนวณค่าสัมประสิทธิ์ต่างๆ ที่แก้ไขสัดส่วนของกราฟเพื่อปรับข้อความ proporcion_grafico()
ขนาดของค่าขึ้นอยู่กับช่วงของพวกเขา escala()
และปัจจัยการแก้ไขสำหรับการวัดที่ทราบเป็นค่าสัมบูรณ์ เช่น การวัดในการอ้างอิง medida_grafico()
.
การอ่านโค้ดนี้ควรช่วยชี้แจงบริบทที่แอปพลิเคชันประเภทนี้ใช้งานได้ ซึ่งวาดกราฟิกแบบเรียลไทม์ และต้องมีความยืดหยุ่นในการนำเสนอในบริบทกราฟิกต่างๆ (อย่างน้อยที่สุดขนาดและสัดส่วนต่างๆ) ก่อนอื่นต้องสร้างวัตถุขึ้นมา SVGไม่ว่าจะ "ด้วยตนเอง" ในโค้ด HTMLไม่ว่าจะผ่านรหัส JavaScript และไม่ว่าในกรณีใด จะต้องได้รับการอ้างอิงถึงวัตถุเหล่านี้ในภายหลังเพื่อจัดการกับวัตถุเหล่านั้น JavaScript เพื่อให้สามารถวาดกราฟใหม่ได้ และการแสดงกราฟที่วาดไว้แล้วสามารถปรับให้เข้ากับการเปลี่ยนแปลงของสื่อที่นำเสนอได้
การอ้างอิงอื่นที่สามารถช่วยตีความกราฟได้ง่ายคือจุดที่แสดงถึงค่าเฉพาะ (โหนดของเส้น) ในตัวอย่างนี้ ซึ่งเราแสดงขนาดเดียว การเลือกสัญลักษณ์นั้นไม่สำคัญ แต่หากค่าที่แตกต่างกันหลายค่าถูกซ้อนทับเพื่อค้นหาความสัมพันธ์ ก็น่าสนใจที่จะแยกแยะ นอกเหนือจากการใช้ทรัพยากรอื่น เช่น สี โดยการวาดสัญลักษณ์ต่างๆ กราฟิกที่ใช้สำหรับโหนดบรรทัดจะต้องได้รับการแก้ไขในขนาดและสัดส่วนตามที่เกิดขึ้น เช่น กับข้อความ เพื่อให้มิติของมันเป็นแบบสัมบูรณ์และเพื่อรักษาสัดส่วนของมันไว้แม้ว่าส่วนของกล่องนั้นจะมีการเปลี่ยนแปลงก็ตาม กราฟิก
ในตัวอย่างก่อนหน้านี้ เราได้เห็นวิธีการคำนวณค่าสัมประสิทธิ์ต่างๆ เพื่อขยายขนาดและแก้ไขสัดส่วนของรูปวาดแล้ว เกี่ยวกับวิธีการจัดการสัญลักษณ์ของโหนดหรือจุดยอดของกราฟ วิธีแก้ปัญหาที่เป็นไปได้อาจเป็นการจัดเก็บวัตถุ SVG ให้เป็นเวกเตอร์และแก้ไขตำแหน่งเมื่อกราฟได้รับการอัปเดตโดยการอ่านค่าใหม่ หรือเมื่อวาดใหม่โดยการปรับขนาดคอนเทนเนอร์ ในกรณีแรกจะต้องแก้ไขตำแหน่ง และประการที่สองตำแหน่งจะต้องเป็นสัดส่วนกับทรัพย์สิน transform
และค่าของ scale
. รหัสต่อไปนี้เป็นการปรับเปลี่ยนฟังก์ชัน actualizar_grafico()
เพื่อรวมการเปลี่ยนตำแหน่งของสัญลักษณ์จุดยอดกราฟ
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);
}
}
|
การปรับเปลี่ยนฟังก์ชั่น actualizar_grafico()
เพื่อรับฟังก์ชันใหม่ actualizar_grafico_puntos()
สิ่งเหล่านี้คือสิ่งที่เน้นไว้ในโค้ดของตัวอย่างก่อนหน้า ขั้นแรก ในบรรทัดที่ 5 เราใช้เวกเตอร์ของวัตถุ SVG เป็นพารามิเตอร์ เวกเตอร์นี้จะมีสัญลักษณ์ที่ต้องเปลี่ยนตำแหน่งในโหนดใหม่ของกราฟ
ในบรรทัดที่ 39 และ 40 มีการกำหนดพิกัดใหม่ของศูนย์กลาง cx
y cy
ให้กับค่าต่างๆ ที่ถูกนำเสนอ หากสัญลักษณ์ไม่ได้อยู่ตรงกลาง อาจจำเป็นต้องเพิ่มออฟเซ็ตเข้าไป cx
ครึ่งหนึ่งของความกว้างและนิ้ว cy
ครึ่งหนึ่งของความสูงเพื่อเปลี่ยนตำแหน่งให้ตรงกับโหนดกราฟ
ในบรรทัดที่ 57 ถึง 61 จุดที่สอดคล้องกับพิกัดที่ไม่ได้วาดเนื่องจากถูกตัดออกด้วยขอบด้านซ้ายจะถูกเปลี่ยนตำแหน่งใหม่นอกกราฟ พิกัดของ cy
เป็นศูนย์และของ cx
ไปยังจำนวนลบใดๆ (มากกว่าจุด) เพื่อไม่ให้แสดงเมื่อตัด เช่น ส่วนด้านซ้ายของกราฟ ที่ข้างหน้าต่างของ SVG.
จัดการแผนภูมิจากวัตถุด้วย JavaScript
การดำเนินการทั้งหมดที่ได้รับการอธิบายจนถึงตอนนี้สามารถรวมเข้ากับออบเจ็กต์เพื่อจัดการกราฟด้วยสไตล์ตามแบบฉบับของเวอร์ชันใหม่ JavaScript. ทางเลือกในการใช้งานนี้มีข้อได้เปรียบเพิ่มเติมในการทำให้การรวมกราฟหลายๆ อันที่มีค่าต่างกันบนเว็บเพจเดียวกันง่ายขึ้น
ก่อนที่จะหารือเรื่องการนำไปปฏิบัติ เรามาทบทวนวิธีทั่วไปที่สุดในการสร้างออบเจ็กต์ด้วย JavaScript และลักษณะเฉพาะบางประการของฟังก์ชันที่ส่งผลต่อข้อเสนอในการวาดกราฟิกเซ็นเซอร์ IoT
ได้มีการอธิบายไปแล้วว่าวิธีการสร้างวัตถุแบบใหม่นั้น JavaScript (มีตั้งแต่เวอร์ชัน 5 ของ ECMAScript) ประกอบด้วยการใช้ Object.create
ซึ่งน่าจะคุ้นเคยกับการใช้แทน "คลาสสิค" new
ซึ่งแน่นอนว่ายังคงทำงานได้อย่างถูกต้องแม้ว่าจะมีจุดประสงค์มากกว่าเพื่อจำลองรูปแบบของภาษาด้วยวัตถุตามคลาส (JavaScript สร้างวัตถุบนต้นแบบ) มากกว่าทางเลือกอื่นที่ใช้ได้
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();
}
|
รหัสก่อนหน้านี้ช่วยให้คุณจดจำความแตกต่างระหว่างการสร้างวัตถุด้วย Object.create
con o new
. นอกจากนี้ยังทำหน้าที่เน้นย้ำว่าในขณะที่ฟังก์ชันที่ใช้สร้างวัตถุด้วย new
สามารถอยู่ที่ใดก็ได้ในโค้ด วัตถุต้องมีอยู่แล้วก่อนจึงจะสามารถสร้างอินสแตนซ์ได้ Object.create
(วัตถุ ES5_Object ไม่ใช่ฟังก์ชัน)
ในบรรทัดที่ 3 และ 4 เพื่อตั้งค่าเริ่มต้นให้กับคุณสมบัติในฟังก์ชันที่สร้างวัตถุด้วย new
แต่ละคุณสมบัติถูกกำหนดให้กับค่าของอาร์กิวเมนต์ที่เกี่ยวข้องหรือ (||
) หากไม่มีการส่งผ่านอาร์กิวเมนต์ นั่นคือถ้าอาร์กิวเมนต์เหล่านั้นไม่ได้ถูกกำหนดไว้ (undefined
) เนื่องจากสถานการณ์นั้นได้รับการประเมินเป็น false
ค่าเริ่มต้นจะถูกกำหนด
บริบทที่ฟังก์ชันถูกดำเนินการ JavaScript ทำให้เกิดประเด็นสำคัญสองประเด็นที่ต้องจำไว้และอาจทำให้สับสนเมื่อใช้ภาษาการเขียนโปรแกรมนี้หลังจากได้ร่วมงานกับผู้อื่นแล้ว เช่น C o C + +ในกรณีของเรา บริบทประกอบด้วยตัวแปรที่กำหนดไว้ในขอบเขตของฟังก์ชัน (และตัวแปรส่วนกลาง) ซึ่งทำให้เกิดแนวคิดที่น่าสนใจ นั่นคือ "การปิด" ที่สร้างรูปแบบการเขียนโปรแกรมทั้งหมด JavaScript. ที่กล่าวมาก็คาดหวังได้เช่นนั้น this
ซึ่งอ้างถึงอ็อบเจ็กต์เมื่อใช้ภายในโค้ดที่กำหนด บริบทการดำเนินการที่ถูกกำหนดไว้จะถูกคงไว้ แต่บริบทที่ใช้คือบริบทที่เรียกใช้ฟังก์ชัน พฤติกรรมนี้มีความโปร่งใสในกรณีส่วนใหญ่ แต่มีสองสถานการณ์ที่อาจทำให้เกิดความสับสน: ฟังก์ชันที่กำหนดภายในฟังก์ชันอื่น และวิธีที่เรียกจากเหตุการณ์อ็อบเจ็กต์ 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
*/
|
เมื่อรันโค้ดก่อนหน้า ข้อความแสดงความคิดเห็นที่ส่วนท้ายจะแสดงในคอนโซล บรรทัดที่ทำเครื่องหมายสองบรรทัดสะท้อนถึงพฤติกรรมที่อาจทำให้เกิดความสับสน: บริบทการดำเนินการฟังก์ชัน probar_dentro()
ES ไม่มี probar()
อย่างที่คาดไว้แต่. window
ซึ่งแสดงตัวแปรร่วมและไม่ใช่คุณสมบัติของชื่อเดียวกัน หากคุณไม่ต้องการให้มีพฤติกรรมเช่นนี้ เพียงสร้างตัวแปรในฟังก์ชันระดับสูงสุดแล้วกำหนดให้กับ this
ดังเช่นในโค้ดต่อไปนี้
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
*/
|
เพื่อควบคุมบริบทการดำเนินการเมื่อมีการเรียกวิธีการจากเหตุการณ์ window
ตัวอย่างเช่นโดยการปรับขนาดหน้าต่างเบราว์เซอร์ซึ่งเป็นลักษณะเฉพาะอีกอย่างหนึ่งของ JavaScript: ความเป็นไปได้ของการเขียนโปรแกรม "โรงงานฟังก์ชั่น" นั่นคือฟังก์ชั่นที่สร้างฟังก์ชั่นอื่น ๆ โดยส่งคืนด้วย 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
|
ในโค้ดตัวอย่างข้างต้นคือวิธีการ llamar()
เด ลอส ออบเจโตส Contexto
มันไม่ได้ทำงาน แต่ส่งคืนฟังก์ชันที่ไม่ระบุตัวตนที่ดูแลมัน เพื่อตรวจสอบว่าทุกอย่างทำงานได้ตามที่คาดไว้ จะมีตัวแปรโกลบอลที่มีชื่อเดียวกันกับคุณสมบัติที่ฟังก์ชันแสดงในคอนโซล หากบริบทถูกต้อง ค่าของคุณสมบัติจะถูกแสดง ไม่ใช่ค่าของตัวแปรร่วม
JavaScript พยายามแก้ไขเครื่องหมายอัฒภาคที่เราละเว้นไว้ท้ายประโยค สิ่งนี้ทำให้มีรูปแบบการเขียนที่ผ่อนคลาย แต่เป็นดาบสองคมที่ต้องปฏิบัติอย่างระมัดระวัง ในกรณีส่วนใหญ่ เพื่อหลีกเลี่ยงผลกระทบที่ไม่พึงประสงค์ซึ่งเกิดขึ้นในนิพจน์ที่มีหลายบรรทัด คุณสามารถใช้วงเล็บหรือนำหน้าวิธีที่ JavaScript จะตีความโค้ด นั่นเป็นเหตุผลว่าทำไมบรรทัดที่ 8 ของตัวอย่างจึงรวมไว้ด้วย function
ด้านหลังของ return
ถ้าฉันใช้บรรทัดอื่นความหมายก็จะแตกต่างออกไปมาก ในความคิดของฉัน วิธีแก้ปัญหาที่อ่านได้มากที่สุดคือการใช้ตัวแปรระดับกลาง (แบบจ่ายได้) เหมือนในเวอร์ชันต่อไปนี้ แน่นอนว่าเมื่อเข้าใจพฤติกรรมแล้ว การตัดสินใจจะสอดคล้องกับโปรแกรมเมอร์
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);
|
ในความหมายเดียวกันกับการประเมินนิพจน์เป็นฟังก์ชัน นั่นคือ ส่งคืนฟังก์ชัน ไม่ใช่ค่าที่ฟังก์ชันส่งคืน ในบรรทัดที่ 21 ของตัวอย่างสุดท้าย (อยู่ในบรรทัดที่ 19 ของตัวอย่างก่อนหน้า) และหยุดด้วย clearInterval
ฟังก์ชั่นที่ถูกเรียกด้วย setInterval
. เพื่อให้มันทำงานเป็นเวลา 30 วินาที ให้เลื่อนการหยุดออกไปด้วย setTimeout
ซึ่งจะต้องมีฟังก์ชันเป็นอาร์กิวเมนต์แรก เพื่อส่งการดำเนินการเป็นพารามิเตอร์ clearInterval
ด้วยตัวแปรที่มีการเรียกเป็นระยะ (ไม่ใช่ฟังก์ชัน clearInterval
) คือสิ่งที่สร้างฟังก์ชันที่ไม่ระบุชื่อในบรรทัดสุดท้าย
ตัวเลือกระหว่างการเขียนโค้ดที่รวมคำจำกัดความของฟังก์ชัน ให้กะทัดรัดยิ่งขึ้น (ดังในบรรทัดที่ 21) หรือใช้ตัวแปรเสริม ในความคิดของฉัน ความสามารถในการอ่านได้มากขึ้น (เช่นในบรรทัดที่ 19 และ 20) จะแตกต่างกันเล็กน้อยในด้านประสิทธิภาพ และขึ้นอยู่กับสไตล์และความสามารถในการอ่านที่มากขึ้น การซ่อมบำรุง.
ในการทดสอบโค้ดก่อนที่จะมีข้อมูลบนเซิร์ฟเวอร์คุณสามารถใช้ตัวสร้างค่าสุ่มในช่วงที่ต้องการหรือเตรียมตารางที่มีค่าควบคุมที่จำลองการทำงานภายใต้เงื่อนไขที่ต้องการ ตัวอย่างต่อไปนี้ใช้ตัวสร้างข้อมูลอย่างง่ายทั่วทั้งช่วง ซึ่งเป็นสาเหตุที่ทำให้ดูเกินจริงไปเล็กน้อย
หากต้องการทดสอบคุณสามารถทำได้ ดาวน์โหลดโค้ดเต็มของตัวอย่าง สร้างขึ้นจากหน้าเว็บที่เขียนใน HTML, รูปแบบ CSS และรหัส JavaScript. อย่างหลังมีความเกี่ยวข้องมากที่สุด เนื่องจากองค์ประกอบอื่น ๆ เป็นเพียงการสนับสนุนเพียงเล็กน้อย ง่ายมาก และพัฒนามากขึ้นในบทความในส่วนที่เกี่ยวข้อง
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);
}
|
แสดงความคิดเห็น