JavaScript를 사용하여 IoT에 연결된 센서의 데이터에 대한 SVG 그래픽을 생성하고 수정합니다.
드로잉에 관한 기사 시리즈의 마지막 부분에서 사물 인터넷에 연결된 센서의 데이터가 포함된 그래픽이제 를 생성하거나 수정하는 방법에 대해 이야기할 시간입니다. 자바 스크립트 형식의 그림 SVG 그리고 일부 요소 HTML 컨테이너 역할을 하거나 그래픽에 보완적인 정보를 제공하는 것입니다.
이 튜토리얼의 대상 사용자는 전자 및 컴퓨터 프로그래밍 프로필을 형성해야 합니다. 마이크로 컨트롤러, 그들은 익숙하지 않을 수도 있습니다 HTML, CSS o SVG; 이러한 이유로 이전 회에서는 해당 언어나 해당 기술에 대한 간략한 소개가 이루어졌습니다. 이 마지막 부분에서는 접근 방식이 약간 다릅니다. 독자는 프로그래밍 방법을 확실히 알고 있기 때문에 언어를 사용하는 것이 가능합니다. C + + 그, 같은 자바 스크립트, 기본 구문을 다음과 공유합니다. C 이는 대부분의 기본 프로그래밍 개념을 건너뛰고 IoT에서 센서 그래픽을 생성하는 데 관심이 있는 차이점과 구체적인 용도에 초점을 맞추는 참고 자료로 간주될 수 있습니다.
이름은 첫 번째 차이점에 대한 단서를 제공합니다. 자바 스크립트 프로그래밍 언어이다 스크립트 (하이픈) 따라서 다음과 같습니다. 해석, 컴파일할 필요가 없습니다. 그 맥락은 스크립트 (예를 들어 웹 브라우저)는 주문을 읽고 번역하고 실행합니다. 정확히 말하면 대부분의 경우 런타임 컴파일(JIT), 그러나 코드 작성 과정에서는 자바 스크립트 그것은 우리에게 영향을 미치지 않습니다. 우리는 단지 코드를 작성하기만 하면 작동할 수 있습니다.
이름에는 첫 번째 혼란도 포함되어 있습니다. 자바 스크립트 와는 조금도 관계가 없다 자바. 처음에 개발 당시에는 넷스케이프 브라우저의 경우 먼저 Mocha라고 불렸고 그 다음에는 덜 혼란스러운 LiveScript라고 불렸습니다. 브라우저에서 성공적으로 구현하고 이를 초월한 후 다음과 같이 표준화되었습니다. ECMAScript를 (시 ECMA-262, 버전 6 작성 당시) 이를 구현하는 브라우저에 대해 중립적이 되도록 했습니다. 현재 표준도 있습니다. ISO 5년 버전 2011부터(ISO / IEC 16262 : 2011 글을 쓰는 시점에서)
JavaScript의 변수, 기본 데이터 유형 및 객체
예를 들어, 다음과 같은 상황과는 다릅니다. C + +, en 자바 스크립트 변수 선언 시 데이터 유형이 포함되지 않음 또한 변수와 관련된 유형이 고정되어 있지 않으므로 프로그램 실행 전반에 걸쳐 다른 유형의 값을 할당하는 것이 가능합니다.
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
그 유형 자바 스크립트 그가 해석한 것입니다. 코드를 디버그하려면 다음을 사용하여 웹 브라우저의 검사기 콘솔(웹 표시에 영향을 주지 않음)에 코드를 작성할 수 있습니다. console.log()
.
데이터를 특정 유형으로, 특히 텍스트를 숫자로 강제로 변환하려면 다음과 같은 함수를 사용할 수 있습니다. parseInt()
o parseFloat()
이는 각각 정수 또는 부동 소수점 숫자로 변환됩니다. 다음과 같이 반대 변환을 수행할 수 있습니다. String()
, 일반적으로 자동 변환으로 충분하므로 꼭 필요한 것은 아닙니다. 와 함께 parseFloat()
예를 들어, 단위가 포함된 개체의 너비나 높이와 같은 웹 페이지 속성의 값을 얻을 수 있습니다. 이런 식으로 표현은 parseFloat("50px");
결과적으로 숫자 값인 50이 반환됩니다.
En 자바 스크립트 큰따옴표와 작은따옴표 사이에는 구분이 없습니다.; 두 경우 모두 데이터 유형은 다음과 같습니다. string
, 각각은 이스케이프 코드 없이도 다른 것을 포함할 수 있습니다.
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이 아니지만 속성이 없을 수도 있습니다.
에 객체를 정의하다 자바 스크립트 중괄호({
y }
) 콜론 기호()로 구분된 속성 또는 메서드:
) 속성 이름 속성 값 및 쉼표(,
) 다른 속성. 개체를 표현하는 이러한 방법에 대한 자세한 내용은 다음 기사에서 찾을 수 있습니다. JSON 형식.
다르게 생각하게 만드는 구문을 사용할 수도 있지만, en 자바 스크립트 프로토타입 외에는 클래스가 없습니다.즉, 객체가 속성과 메서드를 상속하기 위해 다른 객체(자식)가 참조로 사용하는 또 다른 객체(프로토타입)가 생성됩니다. 스타일에 가장 가까운 구문 자바 스크립트 프로토타입을 사용하는 것은 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
) 객체가 프로토타입을 사용하면 true로 평가되고 그렇지 않으면 false로 평가됩니다.
다른 객체를 프로토타입으로 사용하여 객체가 생성되면, 즉 객체가 인스턴스화되면 해당 객체는 다음과 같이 생성될 수 있습니다. 새 속성을 추가하거나 프로토타입 속성을 재정의합니다. 다음과 같이 도트 구문을 사용합니다. gato.peso=2.5
.
La 배열 자바 스크립트 그들은 당신이 알고 있는 것과는 다릅니다. C. 우선, 길이를 표시할 필요 없이 대괄호 열기 및 닫기 기호만 사용하여 선언됩니다([
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
|
// 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
, 이미 일반 객체와 함께 사용되었거나 최신 버전의 자바 스크립트 당신은 의지 할 수 있습니다 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
, 날짜와 시간을 표현하고 관리하는 데 사용됩니다. 자바 스크립트. 개체는 데이터 없이 인스턴스화될 수 있으므로 현재 날짜와 시간을 사용하거나 날짜를 1년 1970월 XNUMX일 이후의 밀리초 단위 값으로 표시하여 생성할 수 있습니다(예: Unix 시간 또는 POSIX 시간 초 대신 밀리초로 표시) 또는 연, 월, 일, 시 등의 별도 값을 지정하는 등의 작업을 수행합니다.
객체에는 완전한 시리즈가 포함됩니다. 날짜와 시간을 쿼리하거나 설정하는 방법:
-
now()
1년 1970월 XNUMX일 이후의 현재 날짜와 시간을 밀리초 단위로 반환합니다. -
getTime()
|setTime()
1년 1970월 XNUMX일 이후의 시간 값(밀리초)을 각각 가져오거나 변경합니다.valueOf()
, 대부분의 객체에 존재하는 메소드인 경우 해당 Date 객체의 값도 얻습니다.getTime()
와 Unix 시간 또는 POSIX 시간 ms로 표현됩니다. -
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
버전을 포함하다 세계 협정시 중간 계산을 할 필요 없이 표준시를 사용하여 직접 작업할 수 있습니다. 그런 의미에서 예를 들어, 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 O 전용 C + + 그리고 함수의 개념을 안다. 기본적인 아이디어는 동일하지만, 자바 스크립트 정의하고 사용하는 방식은 약간 다릅니다. 우선, 이미 다음과 같이 말했습니다. 자바 스크립트 데이터 유형을 명시적으로 사용하지 않으므로 함수 정의 시 이를 표시할 필요가 없습니다.. 따라가려면, 함수에 이름이 필수는 아니며 익명일 수 있습니다.. 변수와 연결하여 호출할 수 있지만 때로는 즉시 호출하는 것이 유용하기 때문에 필요하지 않을 수도 있습니다. 괄호와 매개변수는 함수 정의 뒤에 추가됩니다.
함수를 정의하려면 접두사 function
, 해당되는 경우 괄호 안에 이름, 인수(함수에 전달되는 매개변수), 중괄호 안에 함수 호출 시 실행될 코드를 적습니다.
1
2
3
4
5
|
function doble(numero)
{
var resultado=numero*2;
return resultado;
}
|
확실히 이전 예에서는 "result" 변수가 전혀 필요하지 않았지만 다음을 기억하는 것은 좋은 변명입니다. 가변 범위, 예상한 대로 작동합니다. "result" 변수는 "double" 함수 내에만 존재합니다. ~ 안에 자바 스크립트 또한 사용할 수 있습니다 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”);
}
}
|
이전 예에는 콘솔을 통해 "current_temp" 속성의 값을 표시하는 "view_temp"라는 메서드가 이미 있습니다. 별로 유용하지는 않지만 객체의 정의가 어떤 것인지에 대한 더 완전한 아이디어를 제공합니다. 자바 스크립트.
객체(함수)의 속성에 대한 메소드에 액세스하려면 다음을 사용하십시오. this
, "current_temp" 속성을 사용하는 경우 11행의 이전 예와 같습니다.
JavaScript를 사용하여 DOM(문서 개체 모델)에 액세스
부터 자바 스크립트 귀하는 해당 페이지가 실행되는 웹 페이지의 콘텐츠와 해당 페이지를 표시하는 브라우저의 일부 측면에 액세스할 수 있지만 시스템 리소스에는 액세스할 수 없습니다. 다음에서 액세스되는 속성과 메서드를 지원하는 데이터 구조 자바 스크립트 창 개체의 일부, 특히 객체의 내용(문서 HTML)는 객체에 해당합니다 document
. 명확성을 위해 때때로 사용되기도 하지만 이를 참조하기 위해 메서드나 속성에 대한 창을 앞에 둘 필요는 없습니다. 예를 들어 다음과 같이 사용하면 충분합니다. document
, 다음과 같이 루트 개체의 이름을 쓸 필요가 없습니다. window.document
, 현재 창이 참조되는 한.
가장 많이 사용되는 형태는 문서 내에서 개체 찾기 HTML 방법을 통해서 입니다 getElementById()
, 코드 생성 시 지정한 id가 인수로 전달됩니다. HTML. 이전 섹션에서 설명한 내용을 보면 객체 내부의 구성 요소에도 액세스할 수 있다고 가정하기 쉽습니다. document
도트 구문 사용(document.componente
) 또는 이름(document["componente"]
)는 숫자 색인과 같은 가장 유용하지만 수동으로 구성된 웹 페이지의 콘텐츠에 액세스할 때 사용하기 어렵고 비실용적입니다.
와 자바 스크립트 할 수있다 다른 요소(요소 또는 부모 노드)를 포함하는 요소를 가져옵니다. 귀하의 부동산에 대한 상담 parentNode
아니면 당신의 재산 parentElement
, 차이점은 상위 요소(parentElement
) 문자열의 마지막 요소 DOM null입니다(null
) 및 상위 노드(parentNode
)는 문서 자체입니다(document
).
에 요소의 콘텐츠 수정 HTML, 예를 들어 라벨의 경우 <div>
, 사용할 수 있습니다 innerHTML
속성을 변경하려면 다음을 사용하여 다른 클래스를 할당하도록 선택할 수 있습니다. className
또는 다음을 사용하여 속성을 개별적으로 변경합니다. style
. 웹페이지의 요소에 의해 표시되는 스타일을 참조하는 것이 반드시 유용한 것은 아닙니다. style
여러 요인에 따라 달라질 수 있거나 명시적으로 지정되지 않았을 수 있기 때문입니다. 웹 페이지에 최종적으로 표시되는 요소의 스타일을 확인하기 위해 getComputedStyle 메소드를 사용합니다..
문서 요소로 HTML 모양과 동작을 결정하기 위해 여러 클래스를 할당할 수 있습니다. 객체의 클래스 목록을 관리합니다. 자바 스크립트 당신은 의지 할 수 있습니다 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 varias 코드 전반에 걸친 횟수 자바 스크립트, 조금 변수에 할당하는 것이 더 효율적입니다. 또는 이름 대신 색인을 사용하십시오. 그렇지 않으면 사용하는 방법이 자바 스크립트 매번 이를 얻으려면 이름을 검색해야 하므로 변수에 액세스할 때보다 약간 더 많은 시간이 소요됩니다.
에 문서에 새 개체 추가 HTML, 메소드를 사용하여 먼저 생성될 수 있습니다. createElement
de document
나중에 필요한 트리 지점의 나머지 요소에 통합합니다. appendChild
. 객체를 생성하려면 XML, 객체와 같은 SVG IoT 센서의 그래프를 그리는 데 사용하는 createElementNS
(NS의 경우 이름 공간). 형식에 대해 이야기할 때 설명했듯이 SVG, 이에 해당하는 네임스페이스(현재 버전의 경우)는 다음과 같습니다. http://www.w3.org/2000/svg
, 이는 다음으로 전달되어야 합니다. createElementNS
요소 유형과 함께 인수로 svg
,이 경우.
우나 에 대한 대안 innerHTML
문서 요소에 텍스트를 내용으로 추가하려면 HTML 방법이다 createTextNode()
목적 document
. 이 대안을 사용하면 다음을 수행할 수 있습니다. 새 텍스트 만들기 (나중에 변수에 할당되면 액세스됨) 메소드를 사용하여 객체 트리에 통합됩니다. appendChild()
. As 에 대한 대안 appendChild()
, 추가된 노드에 이미 존재하는 콘텐츠의 끝에 새 콘텐츠를 추가하는 경우 다음을 사용할 수 있습니다. 방법 insertBefore()
, 기존 개체 앞에 새 개체를 추가합니다. 입다 insertBefore()
대신 appendChild()
예를 들어 다음과 같은 기능을 제공하는 방법을 제공합니다. 기존 개체 앞에 새 개체 정렬 요소가 다른 요소 앞에 있어야 하거나(목록에서와 같이) 전경이나 배경에 더 가까운 요소가 있는 그래픽 구조에서 덮어야 하는 경우입니다.
JavaScript로 이벤트에 반응
방법은 언제 웹 페이지를 IoT 연결 센서 그래프의 컨테이너로 사용 그것은 사용되었다 onload
라벨에서 <body>
그래프 그리기를 시작합니다. 코드 객체와 관련된 이 속성 HTML, 은 다음을 가리킨다. 이벤트 자바 스크립트. 이미 설명했듯이 페이지가 로드되면 함수를 실행합니다. 코드와 연결되어 있지만 HTML 더 염두에 두려면 코드로 작성했을 수도 있습니다. 자바 스크립트 으로 body.onload=dibujar;
것 dibujar
웹페이지가 로드될 때 시작되어야 하는 함수의 이름입니다.
최신 버전의 자바 스크립트 이벤트는 다음을 사용하여 함수와 연관될 수 있습니다. addEventListener
형식으로 objeto.addEventListener(evento,función);
또는 구문을 사용하여 objeto.evento=función;
이는 이전 구현에서도 작동합니다. 이벤트와 관련된 기능의 연결을 해제하려면 다음을 수행해야 합니다. removeEventListener
이는 다음과 같은 형식을 갖습니다. addEventListener
.
자바 스크립트 이는 웹 페이지에서 발생할 수 있는 다양한 이벤트에 반응할 수 있습니다. 예를 들어 요소를 클릭하면 이를 감지할 수 있습니다. HTML 와 onmousedown
, 또는 onclick
, 키를 눌렀을 때 onkeydown
, 스크롤 막대를 조작하여 onscroll
. 우리의 목적을 위해서는 이것으로 충분합니다. 페이지로드 감지 onload
그리고 그것의 크기 조정 onresize
. 우리는 이러한 이벤트를 객체와 연관시킬 것입니다 body
y window
델 DOM 각기. 첫 번째는 코드에서 할당될 수 있습니다. HTML, 본 바와 같이 코드 내에서 두 번째 자바 스크립트 첫 번째로 호출된 함수 내부와 형식 window.onresize=redimensionar;
것 redimensionar
창 크기가 변경될 때마다 호출되는 함수입니다.
일정 시간 간격 후에 실행
자바 스크립트 두 가지 리소스가 있습니다. 지연된 실행: setTimeout
, 일정 시간 간격 후에 함수를 실행하고 setInterval
특정 시간 간격마다 기능을 실행합니다.. 두 방법 모두 매개변수로 (1) 호출된 함수와 (2) 밀리초로 표현된 시간 간격이 필요합니다. 해당 작업을 중지하려면 이러한 함수에서 반환된 결과를 변수에 할당하고 이를 인수로 전달할 수 있습니다. clearTimeout
OA 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
경고 표시를 표시하는 역할을 합니다. 과거에는 널리 사용되었지만 현재는 코드에서 거의 금지되어 있습니다. 자바 스크립트 대화 상자로 웹 페이지를 덮는 것이 얼마나 공격적인(침해적인) 것인지 때문입니다.
다음을 위해 작성된 프로그램에서 마이크로 컨트롤러 작은 시리즈(예: 접시 위의 시리즈) 아두 이노 우노) 이전 예제와 같이 전역 변수를 사용하는 것이 일반적입니다. 자바 스크립트코드가 간단하고 특별히 혼란스럽지 않기 때문에, 함수가 임시로 구현되는 경우가 많고, 전역 변수를 사용하면 매우 간단하고 직관적인 방식으로 메모리 사용을 예측할 수 있기 때문에 리소스가 거의 없는 시스템에서 매우 중요합니다. . 대신에, en 자바 스크립트 전역 변수의 사용을 가능한 한 최소한으로 줄이는 것이 일반적입니다. 왜냐하면 정상적으로 실행되기 때문에 메모리 사용량을 급히 늘릴 필요가 없기 때문입니다. CPU 다른 나라보다 훨씬 뛰어난 자원을 가지고 MCU, 방해 없이 작동해야 하는 많은 타사 코드와 공존할 가능성이 높으며 개방형 시스템이므로 향후 실행 컨텍스트를 예측할 수 없습니다(프로그램의 프로그램). 마이크로 컨트롤러 small은 일단 작동되면 더 많은 코드를 추가하지 않고도 작동을 완전히 결정합니다. 코드가 작동을 캡슐화하지 않으면 응용 프로그램의 크기로 인해 읽기가 어려워질 수 있으므로 메소드를 가능한 한 독립적으로 만듭니다.
JavaScript Math 객체를 사용한 수학 연산
더 복잡한 수학적 계산의 수학적 연산이 개체에 그룹화되어 있습니다. Math
. 이 개체는 직접 사용되며, 포함된 메서드나 속성(상수)을 사용하기 위해 인스턴스화할 필요가 없습니다.
Math.abs(n)
매개변수 n의 절대값Math.acos(n)
매개변수 n의 아크코사인(결과는 라디안)Math.asin(n)
매개변수 n의 아크사인(결과는 라디안)Math.atan(n)
매개변수 n의 아크탄젠트(결과는 라디안)Math.atan2(n,m)
n/m의 아크탄젠트(결과는 라디안)Math.ceil(n)
매개변수를 가장 가까운 정수로 반올림합니다.Math.cos(α)
매개변수 α의 코사인(라디안 단위의 α)Math.E
e 번호 (≃2.718281828459045)Math.exp(n)
e를 매개변수 n: e로 올렸습니다.nMath.floor(n)
매개변수 n을 가장 가까운 정수로 내림합니다.Math.log(n)
매개변수 n의 자연 로그(밑 e)Math.LN2
2의 자연 로그(밑 e)(≃0.6931471805599453)Math.LN10
10의 자연 로그(밑 e)(≃2.302585092994046)Math.LOG2E
e의 밑이 2인 로그(≃1.4426950408889634)Math.LOG10E
e의 밑이 10인 로그(≃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.0 사이의 난수Math.round(n)
매개변수 n을 가장 가까운 정수로 반올림합니다.Math.sin(α)
매개변수 α의 사인(라디안 단위의 α)Math.sqrt(n)
매개변수 n의 제곱근Math.SQRT1_2
1/2의 제곱근 (≃0.7071067811865476)Math.SQRT2
2의 제곱근 (≃1.4142135623730951)Math.tan(α)
매개변수 α의 탄젠트(라디안 단위의 α)
AJAX를 사용하여 서버에서 데이터 로드
IoT에 저장된 정보를 그리는 방법은 서버에서 수시로 데이터를 불러와서 이를 표현하는 그래프를 다시 그리는 방식이다. 서버에서 데이터를 읽으려면 기술이 사용됩니다. AJAX(비동기 JavaScript 및 XML) 객체를 통해 XMLHttpRequest
de 자바 스크립트. 데이터 그래프 그리기는 객체를 재사용하여 수행됩니다. SVG 이는 이미 코드에 있습니다. HTML 여기에는 로드된 새 데이터와 일치하도록 좌표가 수정된 플롯이 포함되어 있습니다.
이 제안의 예에서는 도면을 업데이트하는 것 외에도 각 그래프에 대해 마지막으로 측정된 데이터의 날짜와 값을 표시하는 웹 페이지의 텍스트도 업데이트됩니다.
서버 측에는 정보가 포함된 데이터베이스가 있습니다. IoT에 연결된 센서가 모니터링을 하고 있다는 것입니다. 이 데이터베이스는 개체 요청으로 읽혀집니다. XMLHttpRequest
인코딩된 정보로 응답 JSON 형식, 사용된 메소드의 이름은 형식과의 관계를 암시하지만 XML.
첫 번째 polaridad.es 튜토리얼에서 IoT 데이터 저장 사물인터넷에 연결된 기기들이 제공하는 정보를 서버측에서 관리하기 위한 인프라의 예를 볼 수 있습니다. 이 기사 시리즈에서는 서버가 리소스로 사용됩니다. 아파치 프로그래밍 언어를 사용할 수 있는 곳 PHP 데이터베이스에 액세스하려면 MySQL의 o MariaDB. IoT를 지원하는 데 사용되는 서버에서는 데이터베이스를 찾는 것이 매우 일반적입니다. MongoDB의 (NoSQL) 및 프로그래밍 언어 자바 스크립트 에 Node.js를 소프트웨어 인프라로서.
다음 기능은 서버의 센서 중 하나에서 최신 데이터를 요청하는 역할을 합니다. 함수 호출에서는 객체가 인수로 사용됩니다. 자바 스크립트 그려지는 데이터를 지원하는 것입니다. 예를 들어 상관 관계를 시각적으로 검색하기 위해 동일한 그래프가 여러 값을 나타내는 경우 서버 작동 방식으로 인해 더 최적의 방법인 여러 값을 동시에 반환하도록 서버에 요청할 수 있습니다. 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);
}
|
이전 예의 세 번째 줄에서는 서버에 대한 쿼리가 준비됩니다. 여기서 "zone" 인수가 전달되며 그 값은 모니터링되는 장소의 이름 또는 코드가 됩니다. 영역은 동일한 데이터베이스에 공존할 수 있습니다. 서로 다른 센서(예: 서로 다른 방의 온도를 측정하는 온도계) 이전 함수에 전달된 매개변수인 차트 데이터가 포함된 개체에는 방 이름("name_suffix")이 포함된 속성이 포함될 것으로 예상됩니다.
이전 코드의 7행과 14행 사이에는 대상 XMLHttpRequest
변수 "ajax"에 저장됩니다. 객체 생성 방법을 선택하기 전에 검색합니다. window
만약 XMLHttpRequest
사용할 수 없습니다(이전 버전의 Microsoft 탐색기에서 발생하는 현상이며 훨씬 뒤떨어져 있지만 (더 원시적인) 구문을 사용하여 개체를 생성하는 대안의 예 역할을 합니다. Object.create
o new
, 다른 객체 지향 언어와 유사합니다.
응답을 즉시 관리할 수 있도록 서버에 요청하기 전에 이를 처리하는 코드를 15~26번째 줄에 작성합니다.
방법 쿼리를 수행 HTTP 서버는 다음과 같이 구성됩니다. 연결을 열어 와 open
유형 및 페이지 표시(선택적으로 사용자 이름 및 비밀번호) 헤더를 준비하세요 프로토콜의 setRequestHeader
y 요청을 보내다 와 send
. 헤더 HTTP Content-length
다음을 사용하여 계산되는 쿼리 길이(문자 수)를 알아야 합니다. length
.
요청 시 AJAX 준비가 되면 이벤트와 관련된 기능이 실행됩니다. onreadystatechange
. 이전 예제에서는 함수를 할당하는 대신 서버에서 도착하는 데이터 수신을 관리하는 익명 함수를 즉시 정의했습니다. 먼저 18번째 줄에서는 요청 상태가 "finished"라는 값에 해당하는지 확인합니다. 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초(XNUMX밀리초)까지 지연할 수 있습니다. 처럼 Math.random()
0.0에서 1.0 사이의 숫자를 생성하고, 여기에 1000을 곱하면 0에서 1000 사이의 숫자가 생성되고, 이 숫자가 정수로 변환됩니다. 같은 방식으로 난수에 범위(최대값 - 최소값)를 곱하고 최소값을 더하여 값을 얻습니다.
SVG 플롯을 사용하여 IoT 센서 그래프 그리기
우리가 표현하고자 하는 값(예제에서는 온도)과 그 시간적 위치를 좌표로 함께 표현할 수 있는 방법을 살펴보았으므로, 아래 예에서는 경로를 그리는 함수를 보여줍니다. 해당 점을 결합하고 선택적으로 상단의 해당 선으로 구분된 색상 영역을 결합합니다. 결과는 다음 이미지와 같습니다.
그래프의 가로축(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초)에서 표시하고 싶은 범위를 뺀 값이 오프셋이 됩니다. 온도 값의 변위는 낮은 범위(XNUMX도)에서 가장 낮은 값을 뺀 값이므로 아래에 표시된 데이터는 허용되는 가장 낮은 값과 가장 유사하지만 이를 평가할 수 있는 여백을 남깁니다. . 통과하다
그래프의 가로 좌표를 얻기 위해 시간 값을 곱하는 계수는 그래프의 전체 너비(예제에서는 100단위)를 표현되는 시간 범위(예제에서는 20초)로 나누어 얻습니다. 스칼라 온도 값으로 계수를 얻으려면 표시된 범위가 최소값 아래의 여유에서 최대값 위의 여유(두 경우 모두 100도)까지라는 점을 기억해야 합니다. 이러한 방식으로 수직 스케일 계수는 그래프의 높이(예제에서는 XNUMX단위)를 최대값으로 나누고 최소값을 뺀 값에 위쪽 및 아래쪽 여백을 더한 결과입니다. 이 값은 음의 온도에서 완전히 나타날 수 있으므로 다음을 사용합니다. 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초(20000ms), 세로로 15°C 수직 -5°C ~ +10°C, 상단 및 하단 여백 XNUMX도. 두 번 전화를 걸어 actualizar_grafico()
, 첫 번째 패스에서 true
채워진 영역을 나타내기 위해 차트를 닫아야 함을 나타내는 인수로, 두 번째 호출에서는 통과합니다. false
선을 그리려고. 각각의 경우에 객체는 path
수정된 것은 첫 번째 경우에는 테두리가 없고 채우기가 있고 두 번째 경우에는 특정 선 두께가 있고 채우기가 없는 해당 모양을 갖는 것입니다.
함수 actualizar_grafico()
물체에 대한 작업 SVG 다음 코드를 컨테이너로 사용합니다. HTML. 그 물체 SVG 두 개의 경로가 포함되어 있습니다. 하나는 선을 그리는 경로이고 다른 하나는 채워진 영역을 그리는 경로입니다. 웹 페이지를 로드할 때 요소에서 <body>
이전 함수가 자동으로 호출됩니다. dibujar_grafico()
이벤트 덕분에 자바 스크립트 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 위에서는 너비(예를 들어) 820px, 높이 150px가 스타일에 설정되어 있습니다(최종 버전에서는 클래스 및 문서와 관련하여 수행하는 것이 좋습니다). 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>
. 에서 추가하려면 자바 스크립트 요소를 그룹으로 SVG 이전 예에서 볼 수 있듯이 사용됩니다. appendChild()
새 개체가 정의되면.
변환을 적용할 때 원점을 설정하기 위해 개체에 속성을 사용할 수 있습니다. SVG transform-origin
, 그 값은 변환이 시작되는 지점의 X 및 Y 좌표입니다. 변환 원점 값이 명시적으로 표시되지 않은 경우(웹 브라우저에서) 좌표 중심이 사용됩니다. 불행하게도 이 글을 쓰는 시점에서 기본 소스가 아닌 다른 소스를 사용하여 변환 동작을 지정하는 것은 브라우저 전체에서 동일하지 않으므로 주의해서 사용해야 합니다.
규모의 변화와 함께 scale
회전과 같은 다른 것들도 있습니다 rotation
그리고 움직임은 translate
, 이는 그래프 표현의 대안: 새로운 좌표를 얻는 대신, 자신만의 공간에 표현하고, 표현하려는 형식에 맞게 그래프를 변환할 수 있습니다.
차트에 참조 추가
이제 그래프의 주요 부분은 프로파일과 채워진 영역으로 값을 플롯하여 해결되었으므로 읽기에 도움이 되는 참고 자료를 사용하여 완성할 수 있습니다. 예를 들어, 허용되는 최대 및 최소 값과 원하는 값을 표시하는 몇 가지 수평 참조(선)를 그리는 것부터 시작해 보겠습니다. 설명된 대로 개체를 SVG 바로 자바 스크립트 또는 코드에 수동으로 포함시키세요. 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
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 O 전용 C + +. 나중에 살펴보겠지만, 이를 프로그래밍하는 최적의 방법은 자바 스크립트 일반적으로 프로덕션 시스템에서 이 예나 그래프의 참조를 관리하는 이러한 값과 메서드를 포함하는 개체를 사용하게 됩니다.
반면, 좀 더 일반적인 코드를 발전시키면서 텍스트를 조정하기 위해 그래프의 비율을 수정하는 다양한 계수를 계산하는 별도의 함수가 개발되었습니다. proporcion_grafico()
, 범위에 따른 값의 규모 escala()
참조 측정과 같이 절대값으로 알려진 측정에 대한 보정 계수 medida_grafico()
.
이 코드를 읽으면 실시간으로 그래픽을 그리고 다양한 그래픽 컨텍스트(적어도 다양한 크기와 비율)에서 유연하게 표시될 수 있어야 하는 이와 같은 애플리케이션이 작동하는 컨텍스트를 명확히 하는 데 도움이 됩니다. 먼저 객체를 생성해야 합니다. SVG, 코드에서 "수동으로" HTML, 코드를 통해 자바 스크립트 그리고 어떤 경우에도 이러한 개체에 대한 참조는 나중에 개체를 조작하기 위해 얻어야 합니다. 자바 스크립트 새로운 그래프를 그릴 수 있고 이미 그려진 그래프의 표현을 그것이 표시되는 매체의 변화에 맞게 조정할 수 있습니다.
그래프를 쉽게 해석하는 데 도움을 줄 수 있는 또 다른 참고 자료는 특정 값을 나타내는 점(선의 노드)입니다. 단일 크기를 표현하는 이 예에서는 기호의 선택이 중요하지 않지만, 상관관계를 찾기 위해 여러 개의 다른 값을 중첩하는 경우 색상과 같은 다른 리소스를 사용하는 것 외에도 구별하는 것이 흥미롭습니다. , 다양한 기호를 그려서. 선 노드에 사용되는 그래픽은 예를 들어 텍스트에서 발생하는 것처럼 크기와 비율이 수정되어 해당 크기가 절대적이고 포함된 상자의 크기가 변경되더라도 비율이 유지되도록 해야 합니다.
이전 예에서 우리는 도면의 비율을 재조정하고 수정하기 위해 다양한 계수를 계산하는 방법을 이미 살펴보았습니다. 그래프의 노드 또는 정점 기호 관리를 구현하는 방법과 관련하여 가능한 해결책은 객체를 저장하는 것입니다. 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
0과 그것의 cx
그래프의 왼쪽 부분처럼 창으로 잘릴 때 표시되지 않도록 점 자체보다 큰 음수로 변환합니다. SVG.
JavaScript를 사용하여 개체의 차트 관리
지금까지 설명한 모든 작업을 개체에 통합하여 새 버전의 보다 일반적인 스타일로 그래프를 관리할 수 있습니다. 자바 스크립트. 이 구현 대안은 동일한 웹 페이지에서 서로 다른 값을 갖는 여러 그래프의 통합을 단순화하는 추가 이점이 있습니다.
구현에 대해 논의하기 전에 다음을 사용하여 객체를 생성하는 가장 일반적인 방법을 검토해 보겠습니다. 자바 스크립트 IoT 센서 그래픽 그리기 제안에 영향을 미치는 기능의 몇 가지 특성.
객체를 생성하는 새로운 방법에 대해서는 이미 설명했습니다. 자바 스크립트 (버전 5부터 사용 가능) ECMAScript를)는 다음을 사용하여 구성됩니다. Object.create
, "클래식" 대신 사용하는 데 익숙해져야 합니다. new
, 물론 여전히 올바르게 작동하지만 그 목적은 클래스 기반 객체를 사용하여 언어 스타일을 시뮬레이션하는 것입니다(자바 스크립트 작업 대안이 아닌 프로토타입을 기반으로 객체 생성을 기반으로 합니다.
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
O 콘 new
. 또한 객체가 생성되는 기능을 강조하는 역할도 합니다. new
코드의 어느 곳에나 있을 수 있으며, 객체를 인스턴스화하려면 먼저 객체가 이미 존재해야 합니다. Object.create
(ES5_Object 객체는 함수가 아닙니다).
3행과 4행에서는 객체를 생성하는 함수의 속성에 기본값을 설정합니다. new
, 각 속성은 해당 인수의 값에 할당되거나 (||
), 전달된 인수가 없는 경우, 즉 정의되지 않은 경우(undefined
), 그 상황은 다음과 같이 평가됩니다. false
, 기본값이 할당됩니다.
함수가 실행되는 컨텍스트 자바 스크립트 명심해야 할 중요한 두 가지 문제가 발생하며 이는 다른 사람과 함께 작업한 후 이 프로그래밍 언어를 사용할 때 혼란스러울 수도 있습니다. C o C + +, 우리의 경우. 컨텍스트에는 함수 범위(및 전역 변수)에 정의된 변수가 포함되어 있는데, 이는 전체 프로그래밍 스타일을 설정하는 "클로저"라는 흥미로운 개념을 불러일으킵니다. 자바 스크립트. 즉, 예상할 수 있는 것은 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()
아니 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
, 예를 들어 브라우저 창의 크기를 조정하면 자바 스크립트: "함수 팩토리", 즉 다른 함수를 생성하는 함수를 프로그래밍하고 이를 반환하는 가능성 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
작업을 수행하지는 않지만 작업을 처리하는 익명 함수를 반환합니다. 모든 것이 예상대로 작동하는지 확인하기 위해 함수가 콘솔에 표시하는 속성과 동일한 이름을 가진 전역 변수가 있습니다. 컨텍스트가 올바른 경우 전역 변수의 값이 아닌 속성 값이 표시됩니다.
자바 스크립트 문장 끝에 생략된 세미콜론 기호를 수정해 보세요. 이는 편안한 글쓰기 스타일을 허용하지만 신중하게 다뤄야 하는 양날의 검입니다. 대부분의 경우 여러 줄을 차지하는 표현식에서 이로 인해 발생하는 바람직하지 않은 효과를 피하기 위해 괄호를 사용하거나 다음 방식보다 앞에 괄호를 사용할 수 있습니다. 자바 스크립트 코드를 해석합니다. 이것이 바로 예제의 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 그리고 코드 자바 스크립트. 다른 구성 요소는 최소한의 지원일 뿐이고 매우 단순화되었으며 해당 섹션의 기사에서 훨씬 더 개발되었기 때문에 후자가 가장 관련성이 높습니다.
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);
}
|
코멘트 남기기