graf (pokročilé funkce GRID)
Založíme si nový projekt a pojmenujeme si LineGraph.
Úvodní kód:
vytvoříme Analogový vstup. Analog je reprezontován (desetiným) číslem. které může jít i do záporných hodnot. (Poslední datový typ messeage, si ukážeme později.)
let anaIn = context.inputs.add("analin","analog","Analog Input");
a přidáme sizeProfile
context.addSizeProfiles(3,2,20,20);
a nakonec přidáme "generický element", na kterém budeme pracovat.
let element = new WK.Element(context);

Tímto jsme si vytvořili bílý obdélník jenž vyplňuje celou plochu widgetu.
uchování hodnot:
Určitě budeme chtít zaznamenat hodnoty, které pak vykreslíme do widgetu jako graf. Proto si vytvoříme pole., do kterého si budeme ukládat hodnoty. (připomínám, že pole v Javascriptu(typescriptu) fungují jinak než v Javě,C(++/#) apod.)
let dataStorage = [];
Nejlepší způsob, jak získat hodnotu z inputu je event listenerem. Proto napíšem
anaIn.listenEvent("valueChanged", e => {
dataStorage.push(anaIn.value);
});
Pozn.: kvůli bugu v GRID se nová hodnota nedá získat z callbacku (e).
tímto při každé změně uložíme novou hodnotu do pole.

Nyní je třeba začít s vykreslováním na element.
Event render a kreslení
Widgety vykreslovány v Canvasu, díky tomu můžeme použít oficiální dokumentaci Canvasu. (LINK).
Veškeré vykreslování se děje v
context.listenEvent("render", e => {
let draw = e.context;
})
čímž kreslíme na vrh celé "plochy" widgetu. Protože budeme hodně používat e.context, uložil jsem si ho do promněné pro jednodušší práci.
Ve zkratce nyní shrnu nejduležitější body z dokumentace Canvasu,
Prakticky veškeré úkony s ním začínáme tím, že zavoláme metodu
.beginPath();
bod 0,0 se nachází v levém horním rohu
veškeré změny projeví až poté co zavoláme
.stroke();
Nakreslíme si základní testovací čáru. pod námi definovaný _draw _napíšeme
draw.beginPath();
draw.moveTo(0,0);
draw.lineTo(context.root.visibleRect.size.width,context.root.visibleRect.size.height);
draw.strokeStyle = "#000000";
draw.stroke();`

a klikneme na test

Čára by vždy měla být z levého horního rohu do dolního pravého.
Pozornější si jistě všimli context.root.invalidate();
Tato metoda se volá kdykoliv se změní widget a je třeba znovu ho celý vykreslit (znova zavolá render).
Např. při změně velikosti widgetu, nebo když ho zavoláme my s tím že chceme vykreslit nově příchozí hodnoty.
když už jsme dali dohromady základy práce s canvasem, jsem si udělat graf z hodnot co ukládáme do pole.
více práce s kreslením
Pro snažší práci si zabarvíme pozadí na bílo a vytvoříme si několik promněných pro snažší práci.
Samozřejmě, přídáme si element, který jsme vytvořili na žačátku do widgetu.
context.root.add(element);
nyní by při kliknuntí na test měla čára být nakreslená na bílém pozadí.

Na začátek renderu si nadefinujeme několik pomocných promněných.
začneme s
let chartPaddingX = 10;
let chartPaddingY = 10;
chceme nechat nějaký prostor na krajích. poté
let chartX = 30 + chartPaddingX;
let chartY = 10 + chartPaddingY;
jakožto "startovací bod" pro náš graf (vlevo nahoře). Odtud budeme začínat se vším vykreslováním.
nakonec
let chartWidth = context.root.visibleRect.size.width - chartPaddingX
let chartHeight = context.root.visibleRect.size.height - chartPaddingY;
Ve zkratce jsme si nadefinovali výšku a šířku pro náš widget, složením těchto dvou hodnot máme souřadnice pravého dolního rohu našeho grafu. U _chartWidth _jsme si vzali šířku celého widgetu (která může být různě veliká) a odečetli jsme od ní padding (pro odstup od okraje).
Abychom zhruba věděli, jak je náš Graf ve widgetu velký, změníme několik parametrů v naší předtím vytvořené čáry.
změníme
draw.moveTo(0,0);
draw.lineTo(context.root.visibleRect.size.width,context.root.visibleRect.size.height);
na
draw.moveTo(chartX, chartY);
draw.lineTo(chartWidth, chartHeight);

klikneme na test a podíváme se, zda se všechno povedlo dle plánu.

zakreslování hodnot
Poté, co jsme si oveřili že vše vypadá OK, mohli bychom získat data z našeho pole, a zakreslit je do widgetu. to uděláme smyčkou(loop).
nejdříve najdeme nejvyšší hodnotu v poli, což uděláme jednoduše:
let max = 0;
for (let i = 0; i < dataStorage.length; i++) {
if (max < dataStorage[i]) {
max = dataStorage[i];
}
}
vytvoříme promněnou, kterou budeme určovat počet prvků jenž zobrazíme v grafu
let chartSize = 50;
poté napíšeme smyčku na vykreslování grafu jako takového:
render.beginPath();
let first = true;
for (let i = Math.max(dataStorage.length - chartSize, 0), j = 0; i < dataStorage.length; i++ , j++) {
const x = chartX + (j / chartSize) * chartWidth;
const y = chartY + chartHeight - (dataStorage[i] / max) * chartHeight;
if (first) {
draw.moveTo(x, y);
}
else {
draw.lineTo(x, y);
}
first = false;
}
draw.strokeStyle = "#489fdf";
draw.stroke();`

překreslení hodnot (re-render)
To nejdůležitější je hotovo. Pokud jste ještě nedopsali to, že při změně hodnoty se má překreslit widget, nyní je správná chvíle
anaIn.listenEvent("valueChanged", e => {
context.root.invalidate();
dataStorage.push(anaIn.value);
});
`
a můžeme náš widget otestovat.

widget by měl při každé změně hodnoty nakreslit nový graf, který se postupně posouvá.
Vodící čáry grafu:
Avšak, graf bez hodnot je užitečný jako bezdrátová myš bez baterek. Přidáme text a "vodící čáry'
draw.fillStyle = "#000";
draw.fillText("0", 3, chartY + chartHeight - 3);
draw.fillText(max, 3, chartY + 13);
draw.strokeStyle = "rgba(0,0,0,0.5)";
draw.beginPath();
draw.moveTo(chartX, chartY);
draw.lineTo(chartX + chartWidth, chartY);
draw.stroke();
draw.beginPath();
draw.moveTo(chartX, chartY + chartHeight);
draw.lineTo(chartX + chartWidth, chartY + chartHeight);
draw.stroke();
Zároveň, můžeme přidat i to, že se vykreslí "kolečka" na vrcholech. první část kódu známe
for(let i = Math.max(dataStorage.length - chartSize, 0), j = 0; i < dataStorage.length; i++, j++) {
const x = chartX + (j / chartSize) * chartWidth;
const y = chartY + chartHeight - (dataStorage[i] / max) * chartHeight;
draw.beginPath();
draw.arc(x,y,2,0,2*Math.PI); //nakreslí oblouk o poloměru Pí * 2 radiánů (celý kruh)
draw.closePath();
draw.strokeStyle = "rgb(0, 153, 255)";
draw.stroke();
draw.fillStyle = "rgba(0, 153, 255, 0.5)";
draw.fill();
}
změna četnosti vykreslování
Pokud se zamyslíme tak zjistíme, že se hodnoty do grafu vykreslují ve chvíli, kdy se změní hodnota vstupu, což je poněkud k ničemu.
Vytvoříme si interval, který bude pravidělně číst a zapisovat do grafu:
setInterval(function () {
dataStorage.push(input.value); //přidáme hodnotu do pole
context.root.invalidate(); //překreslíme widget
}, 1000);
a listener smažeme, protože nechceme nadále zapisovat hodnoty pouze při změně, ale pravidelně
input.listenEvent("valueChanged", function (e) {});
výsledný graf bude vypadat nějak takto

Pokud jste s grafem spokojeni. Můžete ho vesele používat kde potřebujete.
konečné slovo:
Samozřejmě je zde hromada místa k zlepšení, jako např. možnost ukazovat více čar, možnost zobrazovat i čísla pod nulu...
Last updated