Генерирайте и модифицирайте SVG графики на данни от сензори, свързани към IoT с JavaScript

Генерирайте и модифицирайте SVG графики на данни от сензори, свързани към IoT с JavaScript

Генерирайте и модифицирайте SVG графики на данни от сензори, свързани към IoT с JavaScript

В тази последна част от поредицата статии за рисуване графики с данни от сензори, свързани с Интернет на нещата, време е да поговорим за това как да генерираме или модифицираме с JavaScript чертежи във формат SVG и някои от елементите HTML които служат като контейнер или които представят допълнителна информация към графиките.

Съдържание

    Графики на данни от сензори, свързани към контейнера на Интернет на нещата (IoT) в HTMLГрафики на данни от сензори, свързани с Интернет на нещата (IoT), дефиниране на външния вид в CSSГрафики на данни от сензори, свързани с интернет на нещата (IoT), чертаят с SVGГрафики на данни от сензори, свързани с Интернет на нещата (IoT) Генериране и модифициране с JavaScript

    Целевите потребители на този урок трябва да формират профил по електроника и компютърно програмиране. микроконтролери, те може да не са запознати с HTML, CSS o SVG; Поради тази причина в предишните части беше направено кратко въведение в езика или съответната технология. В тази последна част подходът е малко по-различен, тъй като читателите със сигурност знаят как да програмират, възможно е използването на езика C + + какво как JavaScript, споделя основен синтаксис с C и може да се използва като справка, за да пропуснете повечето от основните концепции за програмиране и по този начин да се съсредоточите върху разликите и специфичната употреба, която ни интересува, за да създадем сензорна графика в IoT.

    Името дава представа за първата разлика: JavaScript Това е език за програмиране писменост (тире) и като такъв е тълкува, няма нужда да го компилираме; контекстът, в който писменост (уеб браузър, например) ще прочете, преведе и изпълни поръчките. За да бъдем точни, в повечето случаи има a компилация по време на изпълнение (JIT), но за процеса на писане на код JavaScript Това не ни засяга, ние просто пишем кода и той може да работи.

    Името съдържа и първото объркване: JavaScript няма ни най-малко отношение към Ява. Първоначално, когато е разработен Netscape за своя браузър той се нарича първо Mocha, а след това по-малко объркващия LiveScript. След успешното му внедряване в браузърите и надхвърлянето им, той беше стандартизиран като ECMAScript (За ECMA-262, версия 6 към момента на писане), за да стане неутрален по отношение на браузърите, които го прилагат. В момента има и стандарт ISO от версия 5, 2011 (ISO / IEC 16262: 2011 към момента на писане на статията)

    Променливи, основни типове данни и обекти в JavaScript

    За разлика от това, което се случва например в C + +, en JavaScript типът данни не е включен при деклариране на променлива и също така типът, свързан с променливата, не е фиксиран, възможно е да се присвои стойност от различен тип по време на изпълнението на програмата.

    В предишния пример променливата "thing" е декларирана (без да се посочва типа на данните), след което се присвояват данни от различен тип и се консултира с typeof типът, който JavaScript че той е интерпретирал. За отстраняване на грешки в кода можете да го напишете в инспекторската конзола на уеб браузъра (което няма да повлияе на представянето на мрежата) с console.log().

    За да принудите преобразуването на данни в определен тип, особено текстови в числови, можете да използвате функции като parseInt() o parseFloat() които се преобразуват съответно в цели числа или числа с плаваща запетая. Обратното преобразуване може да се направи с String(), въпреки че е малко вероятно да е необходимо, тъй като автоматичното преобразуване обикновено е достатъчно. с parseFloat()Например, можете да получите стойността на свойство на уеб страница, като ширина или височина на обект, което включва единици; По този начин изразът parseFloat("50px"); ще върне 50, числова стойност, като резултат.

    En JavaScript няма разлика между двойни и единични кавички; Типът данни и в двата случая е string, като всеки от тях може да включва другия без нужда от кодове за изход.

    В предишния пример може да се види, че променлива, когато е декларирана (съществува), но не й е присвоена никаква стойност, съдържа недефиниран тип данни (undefined). Неприсвоен обект има стойност null; Тоест обектът съществува, но без стойност; променлива, която го препраща, няма да има a typeof undefined сино object. Един обект също може да бъде празен, тоест да не е нулев, но да няма никакви свойства.

    за дефинирайте обект в JavaScript са оградени в скоби ({ y }) свойствата или методите, разделени със знака двоеточие (:) име на свойство стойност на свойство и със запетая (,) различните свойства. Можете да намерите повече информация за този начин на изразяване на обект в статията за JSON формат.

    Въпреки че можете да използвате синтаксис, който може да ви накара да мислите по друг начин, en JavaScript Няма класове, а прототипиТоест, за да може даден обект да наследи свойства и методи, се създава друг обект (прототипът), който останалите (децата) използват като референция. Синтаксисът, който е най-близък до стила на JavaScript да се използва прототип е Object.create въпреки че също е възможно (и понякога полезно) да се използва new както и в други обектно-ориентирани езици.

    за запитване дали един обект е екземпляр на друг, ако го използвате като прототип, ако наследите свойствата му, накратко, можете да използвате instanceof (създадено с new) o isPrototypeOf (създадено с Object.create), което ще се оцени като true, когато обектът използва прототипа и false, когато не го прави.

    След като един обект е създаден, използвайки друг като прототип, т.е. след като един обект е инстанциран, той може да бъде добавете нови свойства или заменете свойствата на прототипа използвайки синтаксис на точка, както в gato.peso=2.5.

    La масиви в JavaScript Те са различни от тези, които вероятно познавате C. Като начало те се декларират без да е необходимо да се посочва дължината им, само със знаците за отваряне и затваряне на квадратни скоби ([ y ]), компонентите могат да бъдат разнородни (различни типове данни в един и същи масив) и могат да се добавят нови елементи, без да бъдат ограничени до ограничение. Матриците на JavaScript всъщност са списъци (колекции) от елементи, към които посочени с цифров индекс или с име. Един масив може едновременно да съдържа числови индекси и имена на елементи, но е обичайно да се използват обекти (свойства) за използване на втория тип.

    Както може да се види в предишния пример, за да разберете дали дадена променлива съответства на екземпляр на масив (това е обект на масив), можете да използвате instanceof, както вече е използвано с общи обекти или в по-нови версии на JavaScript можете да прибегнете до Array.isArray()

    За достъп до елементите на масива можете да използвате неговия индекс (matriz[7]) или по името на свойството с името в квадратни скоби (matriz["nombre"]) или с обичайния синтаксис на точки за обекти (matriz.nombre). Тъй като името е текстов низ, за ​​съставянето му може да се използва израз, включително променливи. За да преминете през масив със свойства, може да се използва цикъл с формата for(propiedad in matriz).

    За нашата цел е интересно да лекуваме предметът Date, с който да представяте и управлявате дата и час в JavaScript. Обектът може да бъде инстанциран без данни, така че ще вземе текущите дата и час, или може да бъде създаден чрез посочване на дата като стойност или в милисекунди от 1 януари 1970 г. (като напр. Unix време или POSIX време но изразени в милисекунди вместо секунди) или посочване на отделни стойности на година, месец, ден, час...

    Обектът включва пълна серия от методи за запитване или задаване на дата и час:

    • now()
      Връща текущите дата и час, изразени в милисекунди от 1 януари 1970 г

    • getTime() | setTime()
      Получава или променя, съответно, времевата стойност в милисекунди от 1 януари 1970 г. Използване valueOf(), който е метод, присъстващ в повечето обекти, стойността на съответния обект Date също се получава, като напр getTime() с Unix време или POSIX време изразено в мс.

    • getMilliseconds() | setMilliseconds()
      Използва се за запитване или задаване на дробната част от милисекундата на обекта Date върху който се изпълнява. Ако се направи справка, получената стойност е между 0 и 999, но могат да бъдат присвоени по-големи стойности, които ще се натрупат в общата дата и час, така че, подобно на останалите методи за получаване, тя служи за увеличаване на стойността на обекта 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() Можете да знаете разликата, която съществува между универсалното време и местното официално време.

    JavaScript функции

    Ако четете това, със сигурност знаете как да програмирате. микроконтролери en C о EN C + + и познава концепцията за функция. Въпреки че основната идея е същата, в JavaScript Начинът, по който се дефинират и използват, е малко по-различен. Като начало вече беше казано, JavaScript Той не използва изрично типове данни, така че не е необходимо да го посочвате, когато дефинирате функцията. Да последвам, Не е задължително функцията да има име, те могат да бъдат анонимни. Те могат да бъдат свързани с променлива, за да ги извикат, но може също да не е необходимо, тъй като понякога е полезно да ги извикате незабавно, за което скобите и параметрите се добавят след дефиницията на функцията.

    За да дефинирате функция, префикс function, ако е приложимо, напишете името, аргументите (параметрите, предадени на функцията) в скоби и кода, който ще бъде изпълнен, когато функцията бъде извикана, в скоби.

    Разбира се, в предишния пример променливата "резултат" изобщо не беше необходима, но е добро извинение да запомните променлив обхват, който работи както очаквате: променливата "result" съществува само в рамките на функцията "double". в JavaScript също може да се използва let, вместо var, за обхват на променлива в контекст на кодов блок (ограден във фигурни скоби, { y })

    Когато говорихме за обекти в предишния раздел, нещо фундаментално липсваше: свойствата бяха дефинирани, но методите не бяха дефинирани. Както се очаква, обектните методи са функции, те нямат име и се използват (извикват) от името (свойство), присвоено от дефиницията на обекта.

    В предишния пример вече има метод, "view_temperature", който показва стойността на свойството "current_temperature" през конзолата. Не е много полезно, но дава по-пълна представа за това каква е дефиницията на даден обект JavaScript.

    За достъп до методите на обект (функции) до неговите свойства, използвайте this, както в предишния пример на ред 11, когато използвате свойството “current_temperature”.

    Достъп до обектния модел на документа (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 дали определен клас е в списъка или не.

    В предишния пример се намира с 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 (НС за пространство на имената). Както е обяснено, когато говорим за формата SVG, пространството от имена, което съответства на него (за текущата версия), е http://www.w3.org/2000/svg, които трябва да бъдат предадени на createElementNS като аргумент заедно с типа на елемента, svg, в такъв случай.

    а алтернатива на 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 съответно.

    В предишния пример методът е въведен alert който служи за показване на предупредителен знак. Въпреки че беше широко използван в миналото, в момента е почти забранен от кода JavaScript поради това колко агресивно (натрапчиво) е покриването на уеб страницата с диалогов прозорец.

    В програма, написана за a микроконтролер от малка серия (като тази на чинията Arduino Uno) обичайно е да се използват глобални променливи, както в предишния пример в JavaScript, тъй като кодът е кратък и не е особено объркващ, тъй като много пъти функциите се изпълняват ad hoc и тъй като използването на глобални променливи позволява да се предвиди използването на паметта по много прост и интуитивен начин, което е критично в системи с малко ресурси . Вместо, en JavaScript Обичайно е да се намали използването на глобални променливи до възможния минимум. тъй като не трябва да бърза с използването на паметта, тъй като работи нормално на a процесор с ресурси, далеч по-добри от тези на a 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: en
    • Math.floor(n) Закръглете параметър n до най-близкото цяло число надолу
    • Math.log(n) Натурален логаритъм (основа e) на параметър n
    • Math.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: nm
    • Math.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 JavaScript. Начертаването на графиката с данни се извършва чрез повторно използване на обект SVG което вече е в кода HTML и това съдържа диаграма, чиито координати са променени, за да съответстват на новите заредени данни.

    В примера на това предложение, в допълнение към актуализирането на чертежа, се актуализира и текст на уеб страницата, който показва датата и стойността на последните измерени данни за всяка графика.

    От страната на сървъра има база данни, която съдържа информацията че сензорите, свързани към IoT, са наблюдавали. Тази база данни се чете от заявката за обект XMLHttpRequest отговаряйки с информация, кодирана в JSON формат, въпреки че името на използвания метод предполага връзка с формата XML.

    В първия урок polaridad.es за IoT съхранение на данни Можете да видите пример за инфраструктура за управление от страна на сървъра на информацията, предоставена от устройства, свързани към Интернет на нещата. В тази серия от статии като ресурс се използва сървър Apache от който можете да използвате езика за програмиране PHP за достъп до база данни MySQL o MariaDB. На сървъри, използвани за поддръжка на IoT, е много често да се намират бази данни MongoDB (NoSQL) и езика за програмиране JavaScript за Node.js като софтуерна инфраструктура.

    Следващата функция е отговорна за изискване на най-новите данни от един от сензорите от сървъра. При извикването на функцията обектът се използва като аргумент JavaScript който поддържа изтеглените данни. Ако една и съща графика представлява няколко стойности, например за визуално търсене на корелация, може да се направи заявка към сървъра да върне няколко едновременно, по-оптимален метод поради начина, по който сървърът работи. HTTP протокол.

    В третия ред от предишния пример се подготвя заявката, която ще бъде отправена към сървъра, в която ще бъде подаден аргументът "зона", чиято стойност ще бъде името или кода на наблюдаваното място, тъй като информацията за област може да съществува едновременно в една и съща база данни различни сензори (например термометри, които измерват температурата в различни стаи). Параметърът, предаден на предишната функция, обектът с данните от диаграмата, се очаква да включва свойство с името на стаята ("name_suffix").

    Между редове 7 и 14 от предишния код, the обект 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 Функцията, която отговаря за преначертаването на графиката с новата информация.

    Идеята, когато се предлага този метод на четене, е данните да се опресняват много често. Ако представената информация съответства на дългосрочен период (като температурите за ден или седмица), може да се приложи първоначална заявка, която събира всички налични данни и след това такава, подобна на тази в примера, която ги актуализира в периодичният кореспондент.

    Генерирайте произволни данни за тестване

    Когато цялата сървърна и клиентска инфраструктура е готова, функция като тази в предишния раздел ще отговаря за четенето на данните и чертането на графиката с тях, но Във фазата на тестване може да е по-практично да се използват произволни числа в рамките на контролиран диапазон за да видите дали написаният код е правилен. Следната функция може да служи като пример за получаване на данни при изграждането на крайното приложение.

    Вместо да чете информацията от база данни, примерът по-горе ги генерира на случаен принцип и ги предава на функцията, която отговаря за изчертаването на графиката. Измислените данни са вектор, образуван от дата, изразена като стойност в милисекунди, моментът на запис на информацията от сензора и наблюдаваните данни, които са между максимална стойност и минимална стойност.

    В този пример, когато генерирате дата, тя може да бъде забавена до една секунда (1000 милисекунди) по отношение на датата към момента на изобретението. Като Math.random() генерира число между 0.0 и 1.0, умножаването му по 1000 произвежда число между 0 и 1000, което след това се преобразува в цяло число. По същия начин стойността се получава чрез умножаване на произволното число по диапазона (максимум минус минимум) и добавяне на минимума.

    Начертайте графиката на IoT сензорите със SVG диаграма

    Тъй като видяхме как можем да получим стойностите, които искаме да представим (температура, в примера) и тяхното временно местоположение, което може да бъде изразено заедно под формата на координати, примерът по-долу показва функция за чертане на път който свързва тези точки и по желание цветна област, ограничена от тази линия в горната част. Резултатът ще бъде като следното изображение.

    Пример за графика, генерирана с SVG и JavaScript за представяне на данни от IoT сензори

    Хоризонталната ос (X) на графиката представлява времето, а вертикалната ос (Y) - стойностите, които сензорите, свързани към IoT, са наблюдавали. Хоризонталният интервал е няколко секунди, тъй като в това предложение графиката се актуализира много често (на всяка секунда, например), за да предостави информация почти в реално време за състоянието на сензорите.

    В предишния код има два интересни аспекта, първо изчислението, което позволява адаптирайте диапазона от стойности, които са представени и второ, имотно строителство d което показва координатите на точките на оформлението (path).

    За да се адаптира диапазонът от представени стойности, те се преместват от минимум и се мащабират, така че видимата величина да съответства на размера на графиката. В случай на време, отместването се получава чрез изваждане на диапазона, който искате да покажете от най-дългото време (датата и часът, които са най-близки до текущия) (20 секунди в примера). Изместването на температурните стойности е това на долния диапазон (един градус) минус най-ниската стойност, така че данните, показани по-долу, са най-близки до най-ниската позволена стойност, но оставят граница, която ни позволява да оценим тези, които правят , пас

    Коефициентът, който умножава времевите стойности за получаване на хоризонталните координати на графиката, се получава чрез разделяне на общата ширина на графиката (100 единици в примера) на представения времеви диапазон (20 секунди в примера). За да се получи коефициентът със скаларните температурни стойности, трябва да се помни, че представеният диапазон варира от граница под минималната стойност до граница над максималната, един градус и в двата случая. По този начин коефициентът на вертикалната скала е резултат от разделянето на височината на графиката (100 единици в примера) на максималната стойност, минус минималната плюс горното и долното поле. Тъй като тези стойности могат да се развият напълно при отрицателни температури, ние използваме Math.abs() да се използва абсолютната стойност на разликата.

    Собствеността d на обекта path Конструира се чрез свързване на координатите на точките в текст. Всяка двойка координати се предхожда от код SVG L, който чертае линия от текущата позиция до абсолютна стойност, която е посочена от координатите. Стойностите X и Y са разделени със запетаи и всяка операция SVG е отделен с интервал от следващия.

    За да стартирате оформлението, използвайте кода M (преместете се в абсолютна координата). В случай на затворена и запълнена диаграма, започвате от долния десен ъгъл, в случай на отворена диаграма, която чертае профила на данните, започвате с последната представена стойност (най-новата). За завършване на затвореното оформление се използва кодът Z добавяйки като последна точка тази, която има същата стойност на координатата X като последната точка на линията и като координата Y най-малката представена стойност.

    В този пример функцията dibujar_grafico(), което е извикването при зареждане на страницата, получава първоначалните стойности за тестване (не последната стойност в реално време) и подготвя диапазона, в който данните ще бъдат изобразени: 20 секунди (20000 15 ms) хоризонтално и 5°C в вертикално от -10°C до +XNUMX°C с един градус горно и долно поле. Направете две обаждания до actualizar_grafico(), при първото преминаване true като аргумент, който показва, че диаграмата трябва да бъде затворена, за да представлява запълнена област, и при второто извикване преминава false да тегли чертата. Във всеки случай обектът path модифицирана е тази, която има съответния вид, със запълване и без рамка в първия случай и с определена дебелина на линията и без запълване във втория случай.

    Функцията actualizar_grafico() работа върху обект SVG който използва следния код като контейнер HTML. Предметът SVG съдържа два пътя, един за изчертаване на линията и друг за изчертаване на запълнената област. При зареждане на уеб страницата, от елемента <body> предишната функция се извиква автоматично, dibujar_grafico() благодарение на събитието JavaScript onload.

    На ред 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().

    Променете пропорцията на елементите на чертежа

    Ако сте опитали да маркирате с функцията в примера в предишния раздел, ще видите, че текстът изглежда деформиран, когато пропорцията на обекта на уеб страницата (width y height На код HTML) не е равно на това на представената площ (viewBox). За да се адаптира пропорцията е необходимо да се знаят размерите на обекта SVG за които можете да се консултирате със стила на обекта или контейнера HTML, ако обектът SVG прехвърлете този имот. Прехвърляне на собственост transform към обекти SVG които зависят от пропорцията, деформацията може да бъде коригирана чрез прилагане на операция за мащабиране scale() в който коефициентът в X е различен от този в Y.

    SVG позволява няколко обекта да бъдат групирани, образувайки нов съставен елемент, който също поддържа свойства, като прости предмети. За да приложите една и съща трансформация към поредица от обекти наведнъж, вместо към всеки обект поотделно, можете да ги групирате според този ресурс и да приложите едно свойство transform на всички тях.

    Както е обяснено, когато говорим за SVG формат, елементите на групата са затворени в етикетите <g> y </g>. За добавяне от JavaScript елементи към група SVG се използва, както се вижда в предишния пример, appendChild() след като новият обект е дефиниран.

    За установяване на произход при прилагане на трансформации, свойството може да се използва върху обекти SVG transform-origin, чиято стойност е координатите X и Y на точката, от която започва трансформацията. Ако стойността за произхода на трансформацията не е изрично посочена (в уеб браузъра), се използва центърът на координатите. За съжаление, към момента на писане, уточняването на поведението на трансформации, използващи източник, различен от този по подразбиране, не е хомогенно в различните браузъри и трябва да се използва с повишено внимание.

    Наред с мащабната трансформация с scale Има и други, като ротация с rotation и движението с translate, които предлагат а алтернатива на графичното представяне: вместо да получавате нови координати, можете да ги представите в тяхното собствено пространство и да трансформирате графиката, за да пасне на формата, в който искате да ги представите.

    Добавете препратки към диаграмата

    Сега, когато основната част от графиката е разрешена чрез начертаване на стойностите с профил и запълнена област, тя може да бъде допълнена с препратки, които помагат за нейното четене. Като пример, нека започнем с начертаване на някои хоризонтални препратки (линии), които отбелязват максималните и минималните приемливи стойности, както и желаната стойност. Както беше обяснено, можете да изберете да добавите обектите към SVG направо от JavaScript или ги включете ръчно в кода HTML и да ги промените по-късно с JavaScript.

    Изглежда логично тези хоризонтални препратки да бъдат етикетирани с текст, който изяснява стойността, която представляват. За да подчертаете текста, можете да използвате правоъгълници, които ще се открояват от фона и графиката. Тъй като текстовете ще трябва да бъдат мащабирани, за да компенсират деформацията, всички те могат да бъдат групирани в обект, към който ще бъде приложен мащабът; Основното предимство да го направите по този начин е да можете да ги модифицирате с една операция, ако графичният контейнер (прозорецът на браузъра) бъде преоразмерен и промени тази пропорция, която скалата коригира.

    Има няколко интересни аспекта в горния примерен код. На първо място, коментирайте, че са използвани константи (глобални променливи), за да направят примера по-четлив за потребителите, идващи от програмирането. микроконтролери en C о EN C + +. Както ще се види по-късно, оптималният начин за програмирането му JavaScript Би било използването на обекти, които биха съдържали тези стойности и методи, които биха управлявали препратките в този пример или графиката, като цяло, в производствена система.

    От друга страна, напредвайки в това, което би бил по-генеричният код, бяха разработени отделни функции, които изчисляват различните коефициенти, които коригират пропорцията на графиката, за да коригират текста proporcion_grafico(), скалата на стойностите в зависимост от техния диапазон escala() и корекционен коефициент за измервания, които са известни в абсолютна стойност, като измервания в референтни стойности medida_grafico().

    Четенето на този код трябва да помогне за изясняване на контекста, в който работи приложение като това, което рисува графики в реално време и трябва да бъде гъвкаво, за да бъде представено в различни графични контексти (най-малкото различни размери и пропорции). На първо място, обектите трябва да бъдат генерирани SVG, или "ръчно" в кода HTML, или чрез код JavaScript и във всеки случай впоследствие трябва да се получат препратки към тези обекти, за да се манипулират от тях JavaScript така че да могат да се чертаят нови графики и представянето на вече изчертана графика може да се адаптира към промяна в средата, в която е представена.

    Друга справка, която може да помогне за лесното тълкуване на графика, са точките, които представляват конкретни стойности (възлите на линията). В този пример, в който представяме една величина, изборът на символ не е критичен, но ако няколко различни стойности се наслагват, за да се търси корелация, е интересно да се разграничат, в допълнение към използването на други ресурси като цвят , чрез рисуване на различни символи. Графиката, използвана за линейния възел, трябва да бъде променена по размер и пропорция, както се случва например с текстовете, така че нейните размери да са абсолютни и така че нейните пропорции да се запазят, дори ако тези на кутията, която съдържа, се променят.

    В предишния пример вече видяхме как да изчислим различните коефициенти за промяна на мащаба и коригиране на пропорцията на чертежа; По отношение на това как да се приложи управлението на символите на възлите или върховете на графиката, възможно решение може да бъде съхраняването на обектите SVG във вектор и променя позицията му, когато графиката се актуализира чрез четене на нова стойност или когато се преначертае чрез преоразмеряване на контейнера. В първия случай ще трябва да се промени положението му, а във втория - съотношението му с имота transform и стойността на scale. Следният код е модификация на функцията actualizar_grafico() за да включва препозициониране на символите на върха на графиката.

    Направени промени във функцията 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 базира създаването на обекти върху прототипи), отколкото работеща алтернатива.

    Предишният код ви позволява да запомните разликите между създаването на обектите с Object.create или с new. Той също така служи за подчертаване на това, докато функцията, с която е създаден обектът new може да бъде навсякъде в кода, обектът трябва вече да съществува, преди да може да бъде инстанциран с него Object.create (Обектът ES5_Object не е функция).

    На редове 3 и 4, за да зададете стойност по подразбиране на свойствата във функцията, с която създава обекта new, всяко свойство се присвоява на стойността на съответния аргумент или (||), ако не са предадени аргументи, тоест ако са недефинирани (undefined), като това обстоятелство се оценява като false, се присвоява стойността по подразбиране.

    Контекстът, в който се изпълнява дадена функция JavaScript повдига два въпроса, които е важно да имате предвид и които също могат да бъдат объркващи, когато използвате този език за програмиране, след като сте работили с други, като напр. C o C + +, в нашия случай. Контекстът включва променливите, дефинирани в обхвата на функцията (и глобалните), което между другото повдига интересна концепция, "затварянията", които установяват цял ​​стил на програмиране в JavaScript. Това каза, може да се очаква това this, който се отнася до обекта, когато се използва в кода, който го дефинира, контекстът на изпълнение, в който е дефиниран, се поддържа, но този, който използва, е контекстът, от който се извиква функцията. Това поведение е прозрачно в повечето случаи, но има две обстоятелства, при които може да бъде объркващо: функция, дефинирана вътре в друга функция, и метод, извикан от събитие на обект. window.

    При изпълнение на предишния код, в конзолата се показва коментираният текст в края. Двете маркирани линии отразяват поведение, което може да бъде объркващо: контекстът на изпълнение на функцията probar_dentro() не probar(), както може да се очаква, но window, който показва глобалните променливи, а не свойствата със същото име. Ако не искате това поведение, просто създайте променлива във функцията от най-високо ниво и я присвоете на this, както в следния код.

    За контролиране на контекста на изпълнение, когато даден метод се извиква от събитие window, например чрез преоразмеряване на прозореца на браузъра, друга особеност на JavaScript: възможността за програмиране на "функционални фабрики", тоест функции, които генерират други функции, връщайки ги с return.

    В примерния код по-горе методът llamar() на обектите Contexto Той не върши работата, но връща анонимна функция, която се грижи за него. За да проверите дали всичко работи както се очаква, има глобална променлива със същото име като свойството, което функцията показва в конзолата; Ако контекстът е правилен, ще се покаже стойността на свойството, а не тази на глобалната променлива.

    JavaScript Опитайте се да коригирате знаците точка и запетая, които пропускаме в края на изреченията. Това позволява спокоен стил на писане, но е нож с две остриета, който трябва да се третира внимателно. В повечето случаи, за да избегнете нежеланите ефекти, които това води до изрази, които заемат няколко реда, можете да използвате скоби или да предхождате начина, по който JavaScript ще интерпретира кода; Ето защо ред 8 от примера включва function в задната част на return, ако бях използвал друг ред, значението щеше да е много различно. По мое мнение най-разбираемото решение е да се използва междинна (недопустима) променлива, както в следната версия; Очевидно, след като поведението е разбрано, решението съответства на програмиста.

    В същия смисъл на оценяване на израз като функция, тоест връщане на функция, а не стойността, която функцията връща; на ред 21 от последния пример (беше на ред 19 от предишния) спира с clearInterval функцията, извикана с setInterval. За да действа за 30 секунди, спирането се отлага с setTimeout, което от своя страна се нуждае от функция като първи аргумент; за доставяне на изпълнението като параметър clearInterval с променливата, която съдържа периодичното извикване (а не функцията clearInterval) е това, за което е създадена анонимната функция в последния ред.

    Изборът между писане на кода, интегриращ дефиницията на функцията, по-компактен (както в ред 21) или използване на спомагателна променлива, по мое мнение, по-четим (както в редове 19 и 20) варира малко в производителността и зависи от повече стил и четливост за поддръжка.

    За да тествате кода, преди да имате данни на сървъра, можете да използвате генератор на произволни стойности в желания диапазон или да подготвите таблици с контролирани стойности, които симулират работа при желаните условия. Следващият пример използва прост генератор на данни в целия диапазон, поради което те изглеждат малко преувеличени.

    За да тествате, можете изтеглете пълния код на примера образувана от уеб страница, написана на HTML, стилът CSS и кода JavaScript. Последното е най-подходящо, тъй като другите компоненти са само минимална поддръжка, много опростени и са много по-развити в статиите в съответните раздели.

    Публикувай коментар

    Може да сте пропуснали