Naučte HTML novým trikům (II)

Pavel, 03.02.2015 08:00, Internet, 7 odpovědí (7519 zobrazení)

Dnes si ukážeme, jak vytvořit nový HTML tag, reprezentující SVG prvek, který se zobrazí jako sedmisegmentovka (jedna číslice). Použijeme ho např. takhle: <svg-segment x=“20“ y=“30“ value=“6“ color=“blue“></svg-segment>

Článek volně navazuje na předchozí: Naučte HTML novým trikům.

Pozn.: Je mi jasné, že daný úkol lze realizovat mnoha způsoby, jistě jsou i elegantnější než moje řešení :-)

Sedmisegmentovka

Jedná se hojně rozšířený způsob zobrazení čílic 0 – 9 (popřípadě 0 – F v šestnáctkové soustavě). Může vypadat např. takhle:
http://pc.poradna.net/file/view/21476-7segmentovka            -popis-png
Každý segment má svoje označení (a – g), číslice zobrazíme tak, že příslušný segment buď rozsvítíme, nebo zhasneme.
Pro zobrazení číslice 3 rozsvítíme segmenty: a, b, c, d, g.
http://pc.poradna.net/file/view/21477-7segmentovka            -cislice-3-png

Direktiva v Angularu

Pomocí javascriptové knihovny AngularJS můžeme definovat nový tag, který potom využijeme v HTML kódu webové stránky. Naše direktiva se jmenuje svgSegment a v HTML kódu ji použijeme jako <svg-segment></svg-segment>.
Může vypadat takto:

app.directive('svgSegment', function(){
    return {
    restrict: 'E',
    replace: true,
    scope: {
        x:'@',
        y: '@',
        min: '@',
        max: '@',
        value: '=value',
        error: '@',
        errorColor: '@',
        color: '@'
    },
    templateNamespace: "svg",
    template: '<g transform="translate({{x}}, {{y}})">\n\
                    <polyline id="segm_a" stroke-width="1" points="11, 14 17, 8 47, 8 53, 14 47, 20 17, 20 11, 14 17, 8" stroke-linejoin="miter" ng-attr-fill="{{a}}" />\n\
                    <polyline id="segm_g" stroke-width="1" points="11, 65 17, 59 47, 59 53, 65 47, 71 17, 71 10, 65 17, 59" stroke-linejoin="miter"  ng-attr-fill="{{g}}" />\n\
                    <polyline id="segm_d" stroke-width="1" points="11, 114 17, 108 47, 108 53, 114 47, 120 17, 120 11, 114 17, 108" stroke-linejoin="miter"  ng-attr-fill="{{d}}" />\n\
                    <polyline id="segm_f" stroke-width="1" points="8, 19 14, 25 14, 55 8, 61 2, 55 2, 25 8, 19 14, 25" stroke-linejoin="miter" ng-attr-fill="{{f}}" />\n\
                    <polyline id="segm_b" stroke-width="1" points="56, 19 62, 25 62, 55 56, 61 50, 55 50, 25 56, 19 62, 25" stroke-linejoin="miter"  ng-attr-fill="{{b}}" />\n\
                    <polyline id="segm_c" stroke-width="1" points="56, 69 62, 75 62, 105 56, 111 50, 105 50, 75 56, 69 62, 75" stroke-linejoin="miter" ng-attr-fill="{{c}}" />\n\
                    <polyline id="segm_e" stroke-width="1" points="8, 69 14, 75 14, 105 8, 111 2, 105 2, 75 8, 69 14, 75" stroke-linejoin="miter" ng-attr-fill="{{e}}" />\n\
                    \n\</g>',

controller: function ($scope){
         
        $scope.getColors = function(){
            var val = $scope.value;
            if (!$scope.isError) {
                $scope.a = (val === 0 || val === 2 || val === 3 || val === 5 || val === 6 || val === 7 || val === 8 || val === 9) ? $scope.color : 'none';
                $scope.b = (val === 0 || val === 1 || val === 2 || val === 3 || val === 4 || val === 7 || val === 8 || val === 9) ? $scope.color : 'none';
                $scope.c = (val === 0 || val === 1 || val === 3 || val === 4 || val === 5 || val === 6|| val === 7 || val === 8 || val === 9) ? $scope.color : 'none';
                $scope.d = (val === 0 || val === 2 || val === 3 || val === 5 || val === 6 || val === 8) ? $scope.color : 'none';
                $scope.e = (val === 0 || val === 2 || val === 6 || val === 8 ) ? $scope.color : 'none';
                $scope.f = (val === 0 || val === 4 || val === 5 || val === 6 || val === 8 || val === 9) ? $scope.color : 'none';
                $scope.g = (val === 2 || val === 3 || val === 4 || val === 5 || val === 6 || val === 8 || val === 9) ? $scope.color : 'none';                
            }
            else {
                if ($scope.error === "E") {
                    $scope.a = $scope.f = $scope.g = $scope.e = $scope.d = $scope.errorColor;
                    $scope.b = $scope.c = 'none';
                }
                else {
                    $scope.g = $scope.errorColor;
                    $scope.a = $scope.b = $scope.c = $scope.d = $scope.e = $scope.f = 'none';
                }
            }             
        };
        
        $scope.checkError = function(){
            $scope.isError = false;
            $scope.isError = !( ($scope.value === parseInt($scope.value)) && ($scope.value >= $scope.min) && ($scope.value <= $scope.max) );
        };
         
         
        $scope.min = ($scope.min === parseInt($scope.min)) ? $scope.min : 0;
        $scope.max = ($scope.max === parseInt($scope.max)) ? $scope.max : 9;
         
        $scope.color = $scope.color || 'black';
        $scope.errorColor = $scope.errorColor || 'red';
        $scope.error = ( ($scope.error === '-') || ($scope.error === 'E') ) ? $scope.error : 'E';

$scope.$watch('value', function(newVal){
            $scope.value = newVal;
            $scope.checkError();
            $scope.getColors();
        });
    }
    }; 
});

Direktiva vrací objekt, jehož vlastnost:
restrict: 'E' říká, že vytvoříme nový tag = element
replace: true značí, že (níže uvedená) vlastnost template nahradí náš tag <svg-element></svg-element> zápisem uvedeným v template
scope je další objekt, pomocí kterého ovlivníme chování tagu <svg-element></svg-element> z HTML kódu použitím atributů
x, y jsou souřadnice, kde se nám sedmisegmentovka vykreslí
min, max umožní definovat minimální a maximální číslici, kterou sedmisegmentovka zobrazí
value je hodnota, kterou chceme zobrazit
error je znak, který se má zobrazit v případě chyby (např. číslo mimo rozsah min-max), může být buď „-„ nebo „E“
errorColor je barva, kterou se zobrazí chyba
color je barva rozsvíceného segmentu

templateNamespace: "svg" je tu proto, aby direktiva fungovala uvnitř SVG
template obsahuje kód, který se vloží místo tagu <svg-element></svg-element>
na prvním řádku je případné posunutí segmentovky o x pixelů doprava a o y pixelů dolů (klasický způsob v SVG)
na dalších řádcích jsou pak definovány jednotlivé segmenty ag pomocí tagu <polyline />, je to běžný zápis v SVG až na poslední atribut ng-attr-fill, který určuje barvu každého segmentu (podle toho, zda je rozsvícený nebo zhasnutý)

controller popisuje chování direktivy a provádí některé manipulace
funkce $scope.getColors() na základě hodnoty value nastaví barvu těm segmentům, které se mají rozsvítit, zhasnuté segmenty se vůbec nevykreslí; v případě chyby se zobrazí buď znak „-„ nebo znak „E“

funkce $scope.checkError() ověří, zda je zadána celočíselná hodnota value a zda je v intervalu min-max, v opačném případě nastaví proměnnou $scope.isError na true

poslední fukce $scope.$watch() by tu být nemusela v případě, že nepotřebujeme update sedmisegmentovky a stačilo by nám jen jednou nastavit její číselnou hodnotu, která se má zobrazit; pokud ale chceme, aby segmentovka reagovala na změnu atributu value, hodí se nám tato funkce

Použití tagu <svg-segment></svg-segment> v HTML

Direktiva definuje několik atributů pro tag (element) <svg-segment></svg-segment> zapsaný v HTML. Atributy jsou:
x, y, min, max, value, error, errorColor, color

Příklad použití:
<svg> <svg-segment x=“20“ y=“30“ value=“6“ color=“blue“></svg-segment> </svg>

Co se stane v případě, že některý z atributů vynecháme? Každý atribut má svoji implicitní hodnotu (která se použije). Souřadnice x, y ji sice nemají implicitně uvedenu, ale pokud je vynecháme, zobrazí se sedmisegmentovka na pozici 0, 0. Ostatní implicitní hodnoty jsou definovány v controlleru, např. minimum:
$scope.min = ($scope.min === parseInt($scope.min)) ? $scope.min : 0;
Zdálo by se, že vynecháním nejpodstatnějšího atributu value nebude zřejmé, co se vlastně má zobrazit, nicméně zobrazí se chyba (znak „-„ nebo „E“), to zařídí funkce $scope.checkError(), v jejíž první části podmínky se ověří, zda platí $scope.value === parseInt($scope.value), tj. zda je atribut value celé číslo. Tím, že atribut value úplně vynecháme, podmínka splněna není a je nastaven příznak chyby a proměnná $scope.isError má hodnotu true.

Na závěr

Jsem si vědom toho, že daný úkol se dá řešit mnoha způsoby, z nichž některé jsou jistě elegantnější než moje řešení. Pro experty: Také vím, že v direktivách existují funkce link a compile…

Direktiva by šla ještě rozšířit o atribut type s hodnotami „bin“, „dec“, „hex“ a s příslušně upraveným controllorem by se pak dala použít na zobrazování dvojkových, desítkových a šestnáctkových číslic.

Pokud někomu nevyhovuje velikost sedmisegmentovky, nemusí nic upravovat v kódu, ale stačí obalit segmentovku tagy <g> a </g> a nastavit příslušnou hodnotu scale, např:
<svg> <g transform=“scale(0.5)“> <svg-segment x=“20“ y=“30“ value=“6“ color=“blue“></svg-segment> </g> </svg>

Odpovědět


PředmětAutorDatum
Re: Naučte HTML novým trikům (II) LeguanOS03.02.2015 10:09
Re: Naučte HTML novým trikům (II) MaSo03.02.2015 10:41
Re: Naučte HTML novým trikům (II) Kráťa03.02.2015 14:12
Re: Naučte HTML novým trikům (II) CoCoChanel03.02.2015 14:41
Re: Naučte HTML novým trikům (II) Kráťa03.02.2015 21:57
Re: Naučte HTML novým trikům (II) Rce05.02.2015 03:22
Re: Naučte HTML novým trikům (II) posledníKráťa05.02.2015 10:34

Re: Naučte HTML novým trikům (II)

LeguanOS [93.171.217.xxx], 03.02.2015 10:09


Pozn.: Je mi jasné, že daný úkol lze realizovat mnoha způsoby, jistě jsou i elegantnější než moje řešení :-)
Tak proč pises članek?

Článek o HTML bez řadku 'html' dobry vtip, :-D Chtělo by to víc praxe a techniky před napsaním članku (malé A4), nebo upozornit ze se jen učíš ;-)
Jinak hezké :-)

↑ Odpovědět


Re: Naučte HTML novým trikům (II)

Bronzový rádce MaSo, 03.02.2015 10:41
Na takové hračičky je Angular pěkný, ale na větším komerčním projektu už bych ho nenasazoval, použil něco jiného (React) nebo počkal bych na verzi 2, která bude podle všeho postavená úplně jinak a dořeší neduhy jedičky...
CAFEBABE

↑ Odpovědět


Re: Naučte HTML novým trikům (II)

Moderátor Kráťa, 03.02.2015 14:12
Pěkné. Když jsem ale testoval HTML5 inputy, některé prohlížeže to nezvládaly a tak dělám stále postaru.
Teď jsem se tam podíval
http://krata.bubakov.net/www/pokusy/input-date/
a Firefox to stále neumí.
Nejsme zaměstnanci - jsme dobrovolníci

↑ Odpovědět


Re: Naučte HTML novým trikům (II)

Bronzový rádce CoCoChanel, 03.02.2015 14:41
Kráťa

• Proc nenapises o tech "HTML5 input" naké clanek? (pripadne mi to zajimavejsi s rozsahlejsim vyuzitim)
• Jako clanek o <HTML> se mi to zda jako zajimavejsi koncept nez Angular .
Google překlad > dobrá překlad.

↑ ← Odpovědět


Re: Naučte HTML novým trikům (II)

Moderátor Kráťa, 03.02.2015 21:57
Já testoval pouze tento input "date". Na článek by to jednak nebylo a druhak se necítím být natolik odborně, abych o tom sepsal pojednání.
Nicméně díky za inspiraci, možná testnu i ostatní a napíšu pojednání z pohledu webotvůrce a uživatele.
V roce 2011 jsem na to i založil vlákno
http://pc.poradna.net/q/view/666610-ma-smysl-delat -input-type-date
Nejsme zaměstnanci - jsme dobrovolníci

↑ ← Odpovědět


Re: Naučte HTML novým trikům (II)

Registrovaný Rce, 05.02.2015 03:22
V Konqueroru je to ještě vtipnější. Je tam sice cvakátko-klikátko na vytažení roletky, leč nejde zmačknout :-D http://pc.poradna.net/file/view/21521-konq-png

↑ ← Odpovědět


Re: Naučte HTML novým trikům (II) poslední

Moderátor Kráťa, 05.02.2015 10:34
To nemá chybu! :-)
Nejsme zaměstnanci - jsme dobrovolníci

↑ ← Odpovědět


TOPlist