LINUX.ORG.RU

Вебные аналого-цифровые индикаторы.

 , копрофагия


8

2

По итогам Есть ли что-то типа Grafana только на порядки легче и проще?

Написал ещё тогда и забыл. Ну пусть новогодний подарочек будет.

Продолжаем делать правильный вебдваноль. Как обычно, всё очень маленькое (2.5kb) и шустрое, на plain JS без каких-либо «фреймворков» и прочего многотонного жирного говна. Легко влезает в эмбедщину всякую и т.п.

Итак…

gauge.js

'use strict'

function Gauges( class_name )
{
    var _ = this;
    _.urls = [];
    var gauge = document.getElementsByClassName( class_name );
    for( var j = gauge.length; j--; )
    {
        var e = gauge.item(j);
        var g = JSON.parse( e.getAttribute( "data-conf" ) );
        if( !g ) return;

        g.id = e.id;
        g.title = e.title;
        e.removeAttribute( 'title' );

        var c = g.size / 2;
        var r = 0.8 * c;
        var l = 2 * Math.PI * r;

        for( var i = _.urls.length; i--; ) { if( _.urls[i].url == g.url ) break; }
        if( i < 0 ) _.urls.push( { url: g.url, gauges: [ g ] } );
        else        _.urls[i].gauges.push( g );

        e.innerHTML =
            '<svg width="' + g.size + '" height="' + g.size + '">'
          + '<circle class="gauge-bg" id="' + g.id + '-bg" cx="' + c + '" cy="' + c + '" r="' + r + '" stroke-dasharray="' + ( 2 * l / 3 ) + " " + ( l / 3 ) + '" stroke-dashoffset="' + ( -5 * l / 12 ) + '"/>'
          + '<circle class="gauge-pnt" id="' + g.id + '-pnt" cx="' + c + '" cy="' + c + '" r="' + r + '" stroke="' + g.color + '" stroke-width="' + ( 0.1 * g.size ) + '" stroke-dasharray="0 1"/>'
          + '<text class="gauge-val" id="' + g.id + '-val" fill="' + g.color + '" x="' + c + '" y="' + ( 1.1 * c ) + '" font-size="' + ( 0.45 * r ) + '" text-anchor="middle"></text>'
          + '<text class="gauge-title" x="' + c + '" y="' + ( c + r ) + '">' + g.title + '</text>'
          + '</svg>';
    }

    _.urls.forEach( function( u )
    {
        _.update( u );
        setInterval( function(){ _.update( u ) }, u.gauges[0].int );
    } );
}

Gauges.prototype.set = function( id, min, max, val )
{
    var e = document.getElementById( id + '-pnt' );
    if( !e ) return;

    var r = e.getAttribute( 'r' );
    var l = 2 * Math.PI * r;
    var v = val < min ? min : val > max ? max : val;
    var dash = ( 2 / 3 ) * l * ( v - min ) / ( max - min );

    e.setAttribute( 'stroke-dasharray', [ dash, l - dash ]);
    e.setAttribute( 'stroke-dashoffset', (-5 / 12) * l );

    document.getElementById( id + "-val" ).textContent = val;
}

Gauges.prototype.update = function( u )
{
    var _ = this;
    var req = new XMLHttpRequest();
    req.onreadystatechange = function()
    {
        if( this.readyState != 4 ) return;
        var obj = JSON.parse( this.responseText );
        if( !obj ) return;
        u.gauges.forEach( function( g )
        {
            var v = g.path.split('.').reduce( function( o, k ) { return o && o[k] }, obj );
            _.set( g.id, g.min, g.max, v.toFixed( g.prec ) );
        } );
    };
    req.open( "GET", u.url );
    req.send();
}

gauge.css

@font-face {
    font-family: "7SEG";
    src: url("DSEG7Classic-BoldItalic.ttf") format("opentype");
}

.gauge-pnt {
  fill: transparent;
}

.gauge-bg {
  stroke: #808080;
  stroke-width: 1px;
  fill: transparent;
}

.gauge-val {
    font-family: "7SEG", serif;
}

.gauge-title {
    text-anchor: middle;
    fill: #C0C0C0;
}

Шрифт DSEG7Classic-BoldItalic.ttf ради прикола, можно из дебиановского пакета fonts-dseg взять. Или в формате woff2, он размером поменьше будет.

Как использовать:

<HTML>
<HEAD>
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Cache-Control" content="no-cache">
<META HTTP-EQUIV="Content-Type" content="text/html; charset=utf-8">
<LINK rel="stylesheet" type="text/css" href="gauge.css">
<SCRIPT src="gauge.js" type="text/javascript"></SCRIPT>
<SCRIPT>
var ups_gauges;
window.addEventListener( 'load', function() { ups_gauges = new Gauges( 'ups' ); }, false );
</SCRIPT>
<STYLE>
a.ups { outline: none; }
body { background-color: #000000; color: #c0c0c0; }
</STYLE>
<TITLE>Gauge</TITLE>
</HEAD>
<BODY>
<a href="ups/voltage.html" class="ups" title="UPS Vin, V"  id="Vin" data-conf='{"url":"data/ups.json","path":"Vin","int":20000,"min":0,"max":300,"prec":0,"color":"#40C040","size":150}'></a>
<a href="ups/load.html"    class="ups" title="UPS Load, %" id="Load" data-conf='{"url":"data/ups.json","path":"Load","int":20000,"min":0,"max":100,"prec":0,"color":"#C040C0","size":150}'></a>
<a href="ups/temp.html"    class="ups" title="UPS T, °C"   id="Temp" data-conf='{"url":"data/ups.json","path":"Temp","int":20000,"min":0,"max":100,"prec":1,"color":"#C0C0C0","size":150}'></a>
</BODY>

data/ups.json

{ "Vin": 193.2, "Load": 40, "Temp": 38.0 }

В аттрибут data-conf элемента который превращаем в индикатор пишем JSON где

url - URL источника данных для индикатора в формате JSON
path - "путь" в JSON до нужной величины, например "sensors.0.temp"
int - интервал обновления в миллисекундах
min - минимальное значение аналоговой шкалы индикатора
max - максимальное значение аналоговой шкалы индикатора
prec - число цифр после запятой для цифрового индикатора 
color - цвет индикатора
size - размер индикатора

У элементов превращаемых в индикаторы должен быть установлен аттрибут id.

В аттрибуте title указывается подпись под индикатором.

Элементам индикаторов одной группы присваеваем один класс и его имя передаём в конструктор new Gauges('class_name') когда нужно создать и запустить индикаторы.

Если у нескольких индикаторов одного и того же класса URL источника данных одинаковый, то запрос к этому URL при периодическом обновлении будет только один, но при этом будут обновлены все индикаторы этого класса с этим URL.

Выглядит так: http://stanson.ch/gauges.png

Лицнзия WTFPL

★★★★★

Последнее исправление: Stanson (всего исправлений: 8)

Ответ на: комментарий от th3m3

Почему не let/const? var же считается устаревшим.

Мне похер. Кому не нравится - берёт и заменяет. :)

Stanson ★★★★★
() автор топика

svg тормозит. Понатянут всякой гадости, а страницы потом кладут на лопатки мощные процессоры. Рисовать надо на канвазе. Толку, что у тебя 2 килобайта, если они тормозят.

Legioner ★★★★★
()

Типичное нечитабельное говно с однобуквенными переменными, так что дальше первого экрана не читал. И да, есть какая-то веская причина использовать getByClassName вместо querySelector?

Nervous ★★★★★
()

а чо теги большими буквами? старый ишак приснился?

deep-purple ★★★★★
()

Последний тег это ваш фетиш?

mydibyje ★★★★
()

вместо лайкосика нажал на звёздочку

Bad_ptr ★★★★★
()
Ответ на: комментарий от deep-purple

Можно и так, можно и один канваз на всё. Смотря что именно требуется.

У меня в текущем проекте тоже свг сделали и график там рисуют. А это показывается на старых компьютерах. Вот на многих тормозит очень ощутимо. На канваз перепишем как время будет.

Legioner ★★★★★
()
Ответ на: комментарий от Legioner

на старых компьютерах

бгг. Ты ещё скажи под винХП не работает. :)

Bad_ptr ★★★★★
()
Ответ на: комментарий от javascript

Вряд ли вся логика завязана на function-scope или переопределении переменных.

fernandos ★★★
()

Как использовать:

Кто пустил sqlщика к написанию гипертекста?

fernandos ★★★
()

Никто это использовать, конечно, не будет.

theNamelessOne ★★★★★
()
Ответ на: комментарий от Legioner

Э-э-э… Простенькие иконки на канвасе рисовать? Это нынче так модно?

100500 простых svg жрут намного меньше чем 100500 канвасов.

Stanson ★★★★★
() автор топика
Ответ на: комментарий от Nervous

Типичное нечитабельное говно с однобуквенными переменными, так что дальше первого экрана не читал.

Сходи свою жабу понюхай, любитель идентификаторов на полстроки.

И да, есть какая-то веская причина использовать getByClassName вместо querySelector?

Какая нафиг разница?

Stanson ★★★★★
() автор топика
Ответ на: комментарий от fsb4000

Чо-то «недилетанты» так ничего настолько маленького и лёгкого и не родили за годы своего вебмакачества.

Поэтому «недилетанты» просто идут нахер.

Stanson ★★★★★
() автор топика
Ответ на: комментарий от Im_not_a_robot

Так дорисуй, жёваный крот, если тебе цифрового значения не достаточно.

Stanson ★★★★★
() автор топика
Ответ на: комментарий от Stanson

Чо-то «недилетанты» так ничего настолько маленького и лёгкого и не родили за годы своего вебмакачества.

А им надо? И насколько переменные с названием c, r, l недилентантские?

fernandos ★★★
()
Ответ на: комментарий от Harald

Так конструктивно критиковать нечего, маленькое, шустрое, работает,простое как 5 копеек, прям берёшь и хочешь в какой ESP8266 запихиваешь, хочешь на сайт в любое место добавляешь, вот и рвутся пердаки у вебмакак, потому что они так не могут. :)

Stanson ★★★★★
() автор топика
Последнее исправление: Stanson (всего исправлений: 1)
Ответ на: комментарий от fernandos

А им надо?

Мне плевать на то, что им там надо. Я как-то не очень на предмет копания в потаённых желаниях извращенцев.

Мне понадобилось, у вебмакак кроме жирного тормозного говна ничего не нашёл, написал за 10 минут, выложил тут, вдруг кому пригодится, кому не нравятся имена переменных, использование svg или большие буквы в тегах html и прочая вкусовщина - тот идёт и пользует жирную вебмакачью дрянь.

И насколько переменные с названием c, r, l недилентантские?

Настолько, что мне так захотелось, а дебил неспособный понять по одной букве смысл и назначение переменной в данном контексте не является целевой аудиторией данного вебдванольного высера.

Stanson ★★★★★
() автор топика
Последнее исправление: Stanson (всего исправлений: 2)
Ответ на: комментарий от Stanson

если канвас один на всё, то он уделает, а вот если канвасов дохера — хзхз.

deep-purple ★★★★★
()
Ответ на: комментарий от Stanson

Мне плевать на то, что им там надо. Я как-то не очень на предмет копания в потаённых желаниях извращенцев.

Тогда ваш аргумент теряет смысл.

Настолько, что мне так захотелось, а дебил неспособный понять по одной букве смысл и назначение переменной в данном контексте не является целевой аудиторией данного вебдванольного высера.

У вас там комментариев нет, жесть же.

fernandos ★★★
()
Ответ на: комментарий от deep-purple

Канвас быстрее при рисовании но медленнее и жирнее при создании и существовании.

Если надо нарисовать полтора графических элемента и потенциально таких независимых штук на странице может быть много - берём svg. Если надо нарисовать йоба-графику в одном большом элементе - берём канвас.

Кроме того, канвас - растр, svg - вектор. Для иконок svg предпочтительнее. Кроме того, svg можно css’ить.

Т.к. эти индикаторы - не более чем иногда изменяющиеся иконки, предназначенные для размещения в любом количестве в любых местах страницы, а не элемент с какой-нибудь игрушкой внутри, то выбор svg очевиден.

И да, если кто-то испытывает неимоверную ненависть к svg - то заменить svg на canvas в этой штуке - дело 10 минут. Так что все эти страдания на предмет svg vs canvas - не более чем пердёж в лужу.

Stanson ★★★★★
() автор топика
Последнее исправление: Stanson (всего исправлений: 1)
Ответ на: комментарий от fernandos

У вас там комментариев нет, жесть же.

Если человек настолько туп, что не способен без комментариев сходу понять что e - это элемент, r - это радиус, а l - это длина, то ему этот вебдванольный высер нафиг не нужен. Пущай идёт пердолится с графаной, например.

Stanson ★★★★★
() автор топика
Ответ на: комментарий от Stanson

Кроме того, канвас - растр, svg - вектор. Для иконок svg предпочтительнее. Кроме того, svg можно css’ить.

И в канвасе есть вектор. Канвас тоже «можно» css’ить.

deep-purple ★★★★★
()
Ответ на: комментарий от deep-purple

И в канвасе есть вектор.

Который сразу в растр, и с масштабированием иконки начинаются проблемы. Впрочем, зато можно как png какой сохранить.

Канвас тоже «можно» css’ить.

Очень условно. А svg всё-же dom и там все элементы напрямую можно css’ить без костылей самым прозаическим образом, что для обсуждаемого применения большой плюс.

Stanson ★★★★★
() автор топика
Ответ на: комментарий от Stanson

Тут особо критиковать то нечего, из плохого стоило бы не хадродить значения подобные этому ( this.readyState != 4 ) этому ( 0.1 * g.size ) и так далее, хотя бы просто вытащить в константы какие-нибудь, и шаблон свг разметки тоже. Ну и сейчас вполне можно было бы написать и на актуальном жс, бабл все равно умеет это превратить в такой на котором написано и скорее всего сделает это не хуже вас.

abcq ★★
()

var _ = this;

в жс завезли стрелочные функции, которые не переписывают this, этот костыль уже можно выкинуть.

anonymous
()
Ответ на: комментарий от anonymous

Погоди ты, тут автор на осле ещё сидит, не гони лошадей!

menangen ★★★★★
()
Ответ на: комментарий от anonymous

Зачем тащить в код всякие новшества, если они вообще ничего не дают кроме сокращения совместимости со всяким старьём?

Stanson ★★★★★
() автор топика
Ответ на: комментарий от Harald

дискуссия в треде прям блещет конструктивной критикой :D

То, что на лоре больше всего похоже на конструктивную критику, можно увидеть в соседнем треде про трудовую теорию стоимости.

Nervous ★★★★★
()
Ответ на: комментарий от Stanson

Если человек настолько туп, что не способен без комментариев сходу понять что e - это элемент, r - это радиус, а l - это длина

Ололо.

Nervous ★★★★★
()
Ответ на: комментарий от Stanson

любитель идентификаторов на полстроки

Когда какуля одна и маленькая, вроде бы ничего страшного. Когда однобуквенные ненавидящие документацию макакичи скатают из какуль огромный ком неподдерживаемого говна — будет не до смеха. А они обязательно скатают.

Какая нафиг разница?

А если я захочу искать элемент по id, например? Нырять и фиксить?

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 3)
Ответ на: комментарий от MOPKOBKA

Это всего лишь превентивные меры для того, чтобы не надо было ползать по скрипту и менять его каждый раз когда что-то захочется поменять, более того, это делается средствами языка, просто немного причесать и убрать хардкод. Но в любом случае, спасибо что отметились, ваша позиция абсурда ясна.

abcq ★★
()
Ответ на: комментарий от anonymous

что еще раз доказывает, что бабел бы даже лучше справился раз стояла задача сделать скрипт кроссбраузерным.

abcq ★★
()
Ответ на: комментарий от abcq

бабел бы даже лучше справился раз стояла задача сделать скрипт кроссбраузерным.

Похоже, у некоторых эмбедщиков суровые условия существования вызывают легкую форму мазохизма — если вручную не попердолился и не пострадал, то и день зря прошел.

Nervous ★★★★★
()
Ответ на: комментарий от Nervous

А если я захочу искать элемент по id, например?

А зачем мне в данном случае искать элементы по id? Тут вся суть как раз в том, чтобы оптом всю группу индикаторов с одинаковым классом обработать и сгруппировать индикаторы в подгруппы с одинаковым источником данных, чтобы дёргать xhr минимально необходимое количество раз, а не на каждый отдельный индикатор.

id тут вообще для передачи конфигурации индикатора используется. Всякие кастомные data-* только в HTML5 добавили.

Stanson ★★★★★
() автор топика
Ответ на: комментарий от anonymous

Осёл вообще не рассматривается даже. Оно совсем инопланетное.

Array.from например

Там ещё Array.prototype.findIndex относительно новый. Впрочем, и то и другое элементарно заменить на обычный for().

ЗЫ: Заменил, кстати, спасибо.

Stanson ★★★★★
() автор топика
Последнее исправление: Stanson (всего исправлений: 1)

Кстати, а почему бы не использовать map (объект) для urls вместо массива? Не надо будет для каждого индикатора делать линейный поиск по всему массиву.

Nervous ★★★★★
()
Последнее исправление: Nervous (всего исправлений: 1)
Ответ на: комментарий от Nervous

Кстати, а почему бы не использовать map (объект) для urls вместо массива? Не надо будет для каждого индикатора делать линейный поиск по всему массиву.

Можно, но Map относительно новый, и большого смысла его использовать нету, потому что раскладывание индикаторов по URL’ям происходит только один раз, при инициализации, и вряд-ли использование Map даст сколь-нибудь заметный эффект. Кроме того, urls потом вообще не используется, update’ам скармливаются конкретные элементы этого массива. Я его оставил как пропертю Gauges чисто для потенциальной возможности что-нибудь делать с индикаторами на ходу, типа пределы измерения поменять или ещё что.

Stanson ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.