Como fazer amigos Electron e Webix. Parte 2. Crie um aplicativo com seu View

Introdução


No artigo anteriorexaminamos com você a questão de integrar a estrutura Webix ao Electron e criar um aplicativo GUI simples com base nessas estruturas. O objetivo deste artigo é desenvolver ainda mais a questão da integração em uma interface GUI criada com a ajuda do Electron e Webix de outras estruturas JavaScript. Todos os elementos da GUI implementados no "Webix" são caracterizados pelo parâmetro "view". Dependendo do valor desse parâmetro, um ou outro elemento da GUI será exibido. O número de tipos de elementos de "visualização" que permitem criar "Webix" se sobrepõe a cerca de 90% das tarefas ao implementar a interface. Os 10% restantes são justamente o caso quando é necessário integrar código previamente escrito ou uma estrutura (biblioteca) que não é explicitamente suportada no Webix.Para implementar a integração com estruturas de terceiros (bibliotecas), criaremos junto com você nosso elemento Webix "view".

Formulação do problema


Crie um aplicativo GUI "Electron + Webix", que criará um gráfico de uma função da forma "y = a * sin (b) + c" com a capacidade de alterar os parâmetros da função "a, bec" com um redesenho dinâmico do gráfico.

Pequena reserva


Faça imediatamente uma reserva de que no "Webix" existem ferramentas padrão muito poderosas para trabalhar com gráficos. Meu objetivo não é suplementar essas ferramentas, mas mostrar como você pode integrar estruturas ou bibliotecas adicionais ao pacote Electron + Webix. Aconteceu que eu tinha um código pronto para este gráfico usando “D3.js.” e decidi integrá-lo ao aplicativo.

Ferramentas


  1. Código do Visual Studio - editor code.visualstudio.com .
  2. Node.JS - faça o download aqui nodejs.org/en
  3. Electron - instale "npm install --save-dev electron".
  4. Webix – ru.webix.com.
  5. JQuery – «npm jquery»
  6. D3.js – d3js.org
  7. (https://github.com/kapakym/electron_webix) , .


1. Como sou uma pessoa preguiçosa, não quero escrever todo o código desde o início pela segunda vez. Portanto, pegamos o código do artigo anterior e o preenchemos na pasta que precisamos. Existem duas opções. A primeira é apenas baixar o arquivo do site (Fig. 1) ou cloná-lo se você tiver o cliente Git instalado (Fig. 2).


FIG. 1 - Download do código fonte de um site


Fig. 2 - Clonando o repositório

2. Para não confundir no futuro, renomeie a pasta (isso é opcional), por exemplo, como “electron_webix_2” e abra-a no Visual Studio Code (Fig. 3).


FIG. 3 - Abra o projeto

3. Instale os elementos necessários. A primeira coisa que você precisa fazer é fazer o download no link fornecido nas ferramentas acima, “Node.JS” e instalá-lo. Sem o "Node.JS", você não pode fazer mais nada. Em seguida, abra o console "Ctr +` "no Visual Studio Code e insira os seguintes comandos, um por um (Fig. 4):

  • "Npm install --save-dev electron";
  • "Npm instala jquery".


FIG. 4 - Instalação do Node.JS e JQuery

4. Em seguida, você e eu ainda precisaremos da estrutura “D3.js.”, ​​também a baixamos usando o link das ferramentas (arquivo “d3.zip”). No arquivo baixado “d3.zip”, extraímos o arquivo “d3.js” e o colocamos na pasta “libs” (Fig. 5).


FIG. 5 - Adicionando a biblioteca D3.js.

Nesta estação de trabalho, preparamos.

Digitando a interface


Agora que o local de trabalho está preparado, vamos diretamente para a criação do nosso aplicativo. Ele consistirá nos seguintes elementos de "visualização":

  • - barra de ferramentas, um elemento Webix padrão. Este elemento será colocado na parte superior da janela e conterá os botões de controle da janela e o nome do aplicativo. Já criamos esse elemento de interface nos materiais do artigo anterior e aqui não mudaremos nada;
  • - myview, que você e eu teremos que criar, por assim dizer, uma "visualização" personalizada. Será a área na qual o gráfico de nossa função será construído usando a estrutura “D3.js.”. Entre outras coisas, essa área será ensinada a se adaptar ao tamanho da janela da nossa aplicação. Coloque-o no meio da janela do aplicativo;
  • - slider, um elemento padrão do "Webix". Este elemento permite alterar seu valor usando o chamado "controle deslizante". Criaremos 3 partes de tais elementos, cada um será responsável por alterar um determinado parâmetro de nossa função "a, b ou c". Coloque-os na parte inferior da janela do aplicativo.

Vamos começar. Abra o arquivo “renderer.js” e edite-o removemos os elementos que não precisamos do artigo anterior e os substituímos pelos elementos descritos acima.

O arquivo "renderer.js" era assim:

//   
const { remote } = require('electron')
//           
let WIN = remote.getCurrentWindow()
//   webix
const webix = require('./libs/webix.min.js')
//  JQuery
$ = require('jquery')
//               
webix.ui(
    {
        "id": 1587908357897,
        "rows": [
            {
                "css": "webix_dark",
                "view": "toolbar",
                "height": 0,
                "cols": [
                    { "view": "label", "label": "Elcetron +Webix its cool!", css:"head_win" },
                    { "label": "-", "view": "button", "height": 38, "width": 40, id:"min-bt" },
                    { "label": "+", "view": "button", "height": 38, "width": 40, id:"max-bt" },
                    { "label": "x", "view": "button", "height": 38, "width": 40, id:"close-bt" }
                ]
            },
            {
                "width": 0,
                "height": 0,
                "cols": [
                    { "url": "demo->5ea58f0e73f4cf00126e3769", "view": "sidebar", "width": 177 },
                    {
                        "width": 0,
                        "height": 0,
                        "rows": [
                            { "template": "Hello WORLD! ", "view": "template" },
                            {
                                "url": "demo->5ea58f0e73f4cf00126e376d",
                                "type": "bar",
                                "xAxis": "#value#",
                                "yAxis": {},
                                "view": "chart"
                            }
                        ]
                    }
                ]
            }
        ]
    }
)

//  
$$("close-bt").attachEvent("onItemClick", () => {
    const window = remote.getCurrentWindow();
    window.close();
})

//  
$$("min-bt").attachEvent("onItemClick", () => {
    const window = remote.getCurrentWindow();
    window.minimize();
})

//  
$$("max-bt").attachEvent("onItemClick", () => {
    const window = remote.getCurrentWindow();
    if (!window.isMaximized()) {
        window.maximize();
    } else {
        window.unmaximize();
    }
})

Vai ficar assim:

//   
const { remote } = require('electron')
//           
let WIN = remote.getCurrentWindow()
//   webix
const webix = require('./libs/webix.min.js')
//  JQuery
$ = require('jquery')
//               
webix.ui(
    {
        "id": 1587908357897,
        "rows": [
            {
                // view : toolbar - 1   
                "css": "webix_dark",
                "view": "toolbar",
                "height": 0,
                "cols": [
                    //  
                    { "view": "label", "label": "Electron + Webix + D3.js", css:"head_win" },
                    //  " "
                    { "label": "-", "view": "button", "height": 38, "width": 40, id:"min-bt" },
                    //  " "
                    { "label": "+", "view": "button", "height": 38, "width": 40, id:"max-bt" },
                    //  
                    { "label": "x", "view": "button", "height": 38, "width": 40, id:"close-bt" }
                ]
            },
            // view : myview -    ,      .
            { "view": "myview", id: "d3_chart" },
            {
                "cols": [
                    // view : slider - 3 .     sin
                    {
                        "label": "Amplitude", "title": "#value#", "value": 50, "view": "slider", id: "slider_amplitude",
                    },
                    // view : slider - 4 .      sin   Y
                    {
                        "label": "Bias", "title": "#value#", "value": 0, "view": "slider", "height": 38, id: "slider_scope", min:-50, max:50, step:1,
                    },
                    // view : slider - 5 .     sin
                    {
                        "label": "Frequency", "title": "#value#", "value": 0.005, "view": "slider", "height": 38, id: "slider_freq", min:0, max:0.1, step:0.001,
                    }
                ]
            }
        ]
    }
)

//  
$$("close-bt").attachEvent("onItemClick", () => {
    const window = remote.getCurrentWindow();
    window.close();
})

//  
$$("min-bt").attachEvent("onItemClick", () => {
    const window = remote.getCurrentWindow();
    window.minimize();
})

//  
$$("max-bt").attachEvent("onItemClick", () => {
    const window = remote.getCurrentWindow();
    if (!window.isMaximized()) {
        window.maximize();
    } else {
        window.unmaximize();
    }
})

Vamos considerar com mais detalhes quais parâmetros incluem "{" view ":" myview ", id:" d3_chart "}":
- view: myview - digite "view", embora não exista, ainda não o criamos;
- id: d3_chart - id "Webix", vamos usá-lo para se referir ao nosso elemento.
Também explicarei os parâmetros do elemento “slider” para completude:
- view: slider - digite “view”, slider;
- label: “text” - um rótulo que será exibido no controle deslizante;
- title: "#value" - o valor atual exibido do controle deslizante;
- valor: "valor" - valor padrão do controle deslizante;
- min: "value" - o valor mínimo do controle deslizante;
- max: "value" - o valor máximo do controle deslizante ";
- step:" value "- o passo para alterar o valor do controle deslizante.
Você pode ler mais sobre todos os parâmetros dos elementos Webix aqui docs.webix.com/desktop__components.html

Crie "minha visão"


Agora crie um arquivo "view_chart.js" no qual definimos nosso novo tipo "myview" e o abra em "VSC".


FIG. 6 - Introdução à edição do view_chart.js

Adicione o seguinte código:

webix.protoUI({
    name: "myview",
    $init: function () {
    },
    redraw: function (a, b, c) {
    },
}, webix.ui.view);

A função webix.protoUI foi projetada para criar elementos Webix customizados com base em elementos padrão. Considere os parâmetros que são passados ​​para esta função:

  • nome - nome do item criado;
  • $ init é uma função que será iniciada quando um elemento for criado. Em outras palavras, é um construtor;
  • redesenhar - nossa função com você, que será responsável por redesenhar o gráfico da função. Passaremos os valores dos parâmetros de nossas variáveis ​​"a, bec"
  • webix.ui.view é o pai do nosso elemento.

Você pode ler mais sobre webix.protoUI aqui.
Então, quando a estrutura da nossa “visão” está pronto, vamos escrever um par de funções que será responsável por planejar o gráfico pecado.
A função para calcular os valores da função sin será semelhante a:
function calcsin(a, b, c) {
    dataset = [];
    for (var i = 1; i < 360; i++) {
        dataset.push({ "x": i, "y": a * Math.sin(b * i) + c });
    };
};


Tudo é muito simples aqui, substituímos os valores dos parâmetros na função matemática sin e salvamos o resultado em uma matriz. Adicione-o ao final do arquivo "view_chart.js".
Em seguida, adicione ao final do arquivo “view_chart.js” uma função que irá desenhar um gráfico usando a estrutura D3.js.
function drawSin() {
    $(document).ready(function () {
        width = $("#mycontent").width() - margin.left - margin.right
        height = $("#mycontent").height() - margin.top - margin.bottom;
        var xScale = d3.scaleLinear()
            .domain([0, 360]) 
            .range([0, width]); 

        var yScale = d3.scaleLinear()
            .domain([-100, 100]) 
            .range([height, 0]);  

        var line = d3.line()
            .x(function (d, i) { return xScale(d.x); }) 
            .y(function (d) { return yScale(d.y); })
            .curve(d3.curveMonotoneX)

        var svg = d3.select("#mycontent").append("svg")
            .attr("float", "center")
            .attr("class", "webix_chart")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")")

        svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height/2 + ")")
            .call(d3.axisBottom(xScale)); 

        svg.append("g")
            .attr("class", "y axis")
            .call(d3.axisLeft(yScale))

        svg.append("path")

            .datum(dataset) 
            .attr("class", "line") 
            .attr("d", line); 
    })

}

A ordem da função fornecida é a seguinte:
- calcule o tamanho do gráfico em relação ao elemento div no qual ele é empacotado "width" e "height";
- escalamos os valores do gráfico em "X" e "Y";
- crie um elemento "html" "svg" no qual desenhamos o eixo "X", o eixo "Y" e o próprio gráfico;
Agora que as funções para calcular e renderizar nosso gráfico estão prontas, conectaremos algumas bibliotecas e declararemos várias variáveis ​​no início do arquivo "view_chart.js":
//     D3.js
const d3 = require("./libs/d3")
//   JQuery
$ = require('jquery')
//          X    Y
var dataset = [];
//         
var margin = { top: 50, right: 50, bottom: 50, left: 50 }
    , width = $("#mycontent").width() - margin.left - margin.right 
    , height = $("#mycontent").height() - margin.top - margin.bottom;

As variáveis ​​“width” e “height” armazenam a largura e a altura do gráfico, levando em consideração o recuo.
Em seguida, volte à função "webix.protoUI" e escreva sua funcionalidade:
webix.protoUI({
    name: "myview",
    $init: function () { //  View
        //   div  id=mycontent.      
        this.$view.innerHTML = "<div id='mycontent'></div>"
        //   calcsin       data  
        calcsin(60, 0.05, 0)
        //   drawSin        data
        drawSin()
    },
    redraw: function (a, b, c) { //    
        //   
        $("#mycontent").html("")
        //       data
        calcsin(a, b, c)
        //  
        drawSin()
    },
}, webix.ui.view);

Cheio de conteúdo duas funções. O primeiro “init” é executado apenas uma vez ao criar a “visualização”. O segundo será chamado quando precisarmos redesenhar o gráfico.
Agora, o conteúdo completo do arquivo "view_chart.js" ficará assim:
//     D3.js
const d3 = require("./libs/d3")
//   JQuery
$ = require('jquery')
//          X    Y
var dataset = [];
//         
var margin = { top: 50, right: 50, bottom: 50, left: 50 }
    , width = $("#mycontent").width() - margin.left - margin.right 
    , height = $("#mycontent").height() - margin.top - margin.bottom;

webix.protoUI({
    name: "myview",
    $init: function () { //  View
        //   div  id=mycontent.      
        this.$view.innerHTML = "<div id='mycontent'></div>"
        //   calcsin       data  
        calcsin(60, 0.05, 0)
        //   drawSin        data
        drawSin()
    },
    redraw: function (a, b, c) { //    
        //   
        $("#mycontent").html("")
        //       data
        calcsin(a, b, c)
        //  
        drawSin()
    },
}, webix.ui.view);



function drawSin() {
    $(document).ready(function () {
        width = $("#mycontent").width() - margin.left - margin.right
        height = $("#mycontent").height() - margin.top - margin.bottom;
        var xScale = d3.scaleLinear()
            .domain([0, 360]) 
            .range([0, width]); 

        var yScale = d3.scaleLinear()
            .domain([-100, 100]) 
            .range([height, 0]);  

        var line = d3.line()
            .x(function (d, i) { return xScale(d.x); }) 
            .y(function (d) { return yScale(d.y); })
            .curve(d3.curveMonotoneX)

        var svg = d3.select("#mycontent").append("svg")
            .attr("float", "center")
            .attr("class", "webix_chart")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("transform", "translate(" + margin.left + "," + margin.top + ")")

        svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height/2 + ")")
            .call(d3.axisBottom(xScale)); 

        svg.append("g")
            .attr("class", "y axis")
            .call(d3.axisLeft(yScale))

        svg.append("path")

            .datum(dataset) 
            .attr("class", "line") 
            .attr("d", line); 
    })

}

function calcsin(a, b, c) {
    dataset = [];
    for (var i = 1; i < 360; i++) {
        dataset.push({ "x": i, "y": a * Math.sin(b * i) + c });
    };
};


Em seguida, você precisa conectar o conteúdo do arquivo "view_chart.js" no arquivo "renderer.js". Por que precisamos adicionar a linha "require (" ./ view_chart.js ") na parte superior do arquivo renderer.js, conforme mostrado abaixo:
//   
const { remote } = require('electron')
//           
let WIN = remote.getCurrentWindow()
//   webix
const webix = require('./libs/webix.min.js')
//  JQuery
$ = require('jquery')
//  view_chart.js
require("./view_chart.js")


Agora você precisa adicionar alguns estilos ao arquivo "styles.css", abra-o e adicione os estilos "svg path" e "#mycontent", como mostrado abaixo:
.head_win {
    -webkit-app-region: drag;
}

/*   */
svg path{
    /*   */
    stroke: #666;
    /*   */
    fill: none;
    /*    */
    stroke-width: 1;
}

/*   mycontent,     */
#mycontent { 
    /*     */
    text-align: center;
    /*   */
    overflow: none;
    /*   */
    border: 1px solid black;
    /*     */
    background-color: antiquewhite;
    /*   */
    height: calc(100% - 2px);
}

Depois de terminar os estilos, você pode tentar executar nosso aplicativo e ver o que aconteceu. Então, pressione “F5” e, em seguida, uma janela deve aparecer na tela, como mostra a Figura 7.


Fig. 7 - Janela da nossa aplicação

O que vemos nela? A parte superior é a barra de ferramentas padrão da Webix. A parte do meio é o gráfico que criamos no myview. A parte inferior são três controles deslizantes que devemos ensinar a alterar os valores dos parâmetros de nossa função.

Vamos fazer os controles deslizantes funcionarem


Agora, vamos para a etapa em que redesenharemos o gráfico no meio de nossa aplicação, dependendo dos valores dos controles deslizantes "Amplitude", "Viés" e "Frequência". Por que adicionamos o manipulador de eventos “onChange” aos controles deslizantes, como mostrado abaixo:

// view : slider - 3 .     sin
                    {
                        "label": "Amplitude", "title": "#value#", "value": 50, "view": "slider", id: "slider_amplitude",
                        on: {
                            onChange: function () {
                                $$("d3_chart").redraw($$("slider_amplitude").getValue(), $$("slider_freq").getValue(), $$("slider_scope").getValue());
                            }
                        }
                    },
                    // view : slider - 4 .      sin   Y
                    {
                        "label": "Bias", "title": "#value#", "value": 0, "view": "slider", "height": 38, id: "slider_scope", min:-50, max:50, step:1,
                        on: {
                            onChange: function () {
                                $$("d3_chart").redraw($$("slider_amplitude").getValue(), $$("slider_freq").getValue(), $$("slider_scope").getValue());
                            }
                        }
                    },
                    // view : slider - 5 .     sin
                    {
                        "label": "Frequency", "title": "#value#", "value": 0.005, "view": "slider", "height": 38, id: "slider_freq", min:0, max:0.1, step:0.001,
                        on: {
                            onChange: function () {
                                $$("d3_chart").redraw($$("slider_amplitude").getValue(), $$("slider_freq").getValue(), $$("slider_scope").getValue());
                            }
                        }
                    }

Nesse manipulador, acessaremos nosso elemento por seu "id" e chamaremos a função "redesenhar" que criamos anteriormente para redesenhar o gráfico, passando os valores atuais dos controles deslizantes. Clique em “F5”, execute nosso aplicativo e tente alterar os valores (Fig. 8).


FIG. 8 - Verificando a funcionalidade dos controles deslizantes

Puxe o gráfico após a janela


E, finalmente, adicionamos uma função que adaptará nosso gráfico ao tamanho da janela quando ela mudar. Por que abrimos o arquivo “view_chart.js” no editor e adicionamos um manipulador ao final que captura as alterações da janela, como mostrado abaixo:

window.onresize = function ( e ) {
  
    $("#mycontent").html("")
    drawSin()
}

Esta função funciona quando a janela é redimensionada. Sua funcionalidade se resume a limpar o conteúdo do bloco “mycontent” e redesenhar o gráfico (chamando a função “drawSin ()”). Cada vez que a função "drawSin ()" é chamada, as variáveis ​​"width" e "height" recebem as informações atuais sobre os tamanhos (altura e largura) do bloco "mycontent", após o que o gráfico altera a escala para ajustar as dimensões do bloco.

Conclusão


Isso é tudo. Espero que esta informação seja útil para você. Obrigado! As fontes podem ser baixadas aqui .

All Articles