Cómo hacer amigos Electron y Webix. Parte 2. Cree una aplicación con su Vista

Introducción


En el articulo anteriorHemos examinado con usted la cuestión de integrar el marco Webix en Electron y crear una aplicación GUI simple basada en estos marcos. El propósito de este artículo es desarrollar aún más el tema de la integración en una interfaz GUI creada con la ayuda de Electron y Webix de otros marcos JavaScript. Todos los elementos GUI implementados en "Webix" se caracterizan por el parámetro "ver". Dependiendo del valor de este parámetro, se mostrará uno u otro elemento de la GUI. El número de tipos de elementos de "vista" que le permite crear "Webix" se superponen alrededor del 90% de las tareas al implementar la interfaz. El 10% restante es solo el caso cuando es necesario integrar código escrito previamente o un marco (biblioteca) que no es explícitamente compatible con Webix.Para implementar la integración con marcos de trabajo de terceros (bibliotecas), crearemos junto con usted nuestro elemento de "vista" Webix.

Formulación del problema


Cree una aplicación GUI "Electron + Webix", que construirá un gráfico de una función de la forma "y = a * sin (b) + c" con la capacidad de cambiar los parámetros de la función "a, byc" con un redibujado dinámico del gráfico.

Pequeña reserva


Haga inmediatamente una reserva de que en "Webix" hay herramientas estándar muy potentes para trabajar con gráficos. Mi objetivo no es complementar estas herramientas, sino mostrar cómo puede integrar marcos o bibliotecas adicionales en el paquete Electron + Webix. Dio la casualidad de que tenía un código listo para este gráfico usando "D3.js" y decidí integrarlo en la aplicación.

Herramientas


  1. Visual Studio Code - editor code.visualstudio.com .
  2. Node.JS - descargar desde aquí nodejs.org/en
  3. Electrón - 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 soy una persona perezosa, no quiero escribir todo el código desde el principio por segunda vez. Por lo tanto, tomamos el código del artículo anterior y lo llenamos en la carpeta que necesitamos. Hay dos opciones El primero es descargar el archivo del sitio (Fig. 1) o clonarlo si tiene instalado el cliente Git (Fig. 2).


Higo. 1 - Descarga del código fuente de un sitio


Fig. 2 - Clonación del repositorio

2. Para no confundirse en el futuro, cambie el nombre de la carpeta (esto es opcional), por ejemplo, como "electron_webix_2" y ábralo en Visual Studio Code (Fig. 3).


Higo. 3 - Abrir el proyecto

3. Instale los elementos necesarios. Lo primero que debe hacer es descargar desde el enlace provisto en las herramientas arriba de "Node.JS" e instalarlo. Sin "Node.JS", no puedes hacer nada más. A continuación, abra la consola "Ctr +" en Visual Studio Code e ingrese los siguientes comandos uno por uno (Fig. 4):

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


Higo. 4 - Instalación de Node.JS y JQuery

4. A continuación, usted y yo todavía necesitaremos el marco "D3.js", también lo descargamos usando el enlace de las herramientas (archivo "d3.zip"). Del archivo descargado "d3.zip" extraemos el archivo "d3.js" y lo colocamos en la carpeta "libs" (Fig. 5).


Higo. 5 - Agregar la biblioteca D3.js

En esta estación de trabajo, hemos preparado.

Escribiendo la interfaz


Ahora que el lugar de trabajo está preparado, pasemos directamente a la creación de nuestra aplicación. Consistirá en los siguientes elementos de "vista":

  • - barra de herramientas, un elemento estándar de Webix. Este elemento se colocará en la parte superior de la ventana y contendrá los botones de control de la ventana y el nombre de la aplicación. Ya hemos creado este elemento de interfaz en los materiales del artículo anterior, y aquí no cambiaremos nada;
  • - myview, que usted y yo solo tendremos que crear, por así decirlo, una "vista" personalizada. Será el área en la que se construirá el gráfico de nuestra función utilizando el marco "D3.js". Entre otras cosas, esta área se enseñará a adaptarse al tamaño de la ventana de nuestra aplicación. Colóquelo en el medio de la ventana de la aplicación;
  • - control deslizante, un elemento estándar de "Webix". Este elemento le permite cambiar su valor utilizando el llamado "control deslizante". Crearemos 3 piezas de dichos elementos, cada uno será responsable de cambiar un determinado parámetro de nuestra función "a, b o c". Colóquelos en la parte inferior de la ventana de la aplicación.

Empecemos. Abra el archivo "renderer.js" y edítelo, es decir eliminamos los elementos que no necesitamos del artículo anterior y los reemplazamos con los elementos descritos anteriormente.

El archivo "renderer.js" era así:

//   
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();
    }
})

Se volverá así:

//   
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();
    }
})

Consideremos con más detalle qué parámetros incluyen "{" view ":" myview ", id:" d3_chart "}":
- view: myview - type "view", aunque no existe, todavía no lo hemos creado;
- id: d3_chart - Identificación "Webix", la usaremos para referirnos a nuestro elemento.
También explicaré los parámetros del elemento "control deslizante" para completar:
- vista: control deslizante - escriba "vista", control deslizante;
- etiqueta: "texto" - una etiqueta que se mostrará en el control deslizante;
- título: "#valor": el valor actual mostrado del control deslizante;
- valor: "valor" - valor predeterminado del control deslizante;
- min: "valor": el valor mínimo del control deslizante;
- max: "valor" - el valor máximo del control deslizante ";
- paso:" valor "- el paso de cambiar el valor del control deslizante.
Puede leer más sobre todos los parámetros de los elementos de Webix aquí docs.webix.com/desktop__components.html

Crear "myview"


Ahora cree un archivo "view_chart.js" en el que definimos nuestro nuevo tipo "myview" y lo abrimos en "VSC".


Higo. 6 - Comenzando a editar view_chart.js

Agregue el siguiente código:

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

La función webix.protoUI está diseñada para crear elementos Webix personalizados basados ​​en elementos estándar. Considere los parámetros que se pasan a esta función:

  • nombre: nombre del elemento creado;
  • $ init es una función que se iniciará cuando se cree un elemento. En otras palabras, es un constructor;
  • redibujar: nuestra función con usted, que será responsable de volver a dibujar el gráfico de la función. Transmitiremos los valores de los parámetros de nuestras variables "a, byc"
  • webix.ui.view es el padre de nuestro elemento.

Puede leer más sobre webix.protoUI aquí.
Entonces, cuando el marco de nuestra "vista" esté listo, escribiremos un par de funciones que serán responsables de trazar el gráfico de pecado.
La función para calcular los valores de la función sin se verá así:
function calcsin(a, b, c) {
    dataset = [];
    for (var i = 1; i < 360; i++) {
        dataset.push({ "x": i, "y": a * Math.sin(b * i) + c });
    };
};


Aquí todo es muy simple, sustituimos los valores de los parámetros en la función matemática sin y guardamos el resultado en una matriz. Agréguelo al final del archivo "view_chart.js".
A continuación, agregue al final del archivo "view_chart.js" una función que dibujará un gráfico usando el marco D3.js, se verá así:
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); 
    })

}

El orden de la función dada es el siguiente:
- calcular el tamaño del gráfico en relación con el elemento div en el que está empaquetado "ancho" y "altura";
- escalamos los valores del gráfico por "X" e "Y";
- cree un elemento "html" "svg" en el que dibujemos el eje "X", el eje "Y" y el gráfico mismo;
Ahora que las funciones para calcular y renderizar nuestro gráfico están listas, conectaremos un par de bibliotecas y declararemos varias variables al comienzo del archivo "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;

Las variables "ancho" y "altura" almacenarán el ancho y la altura del gráfico, teniendo en cuenta la sangría.
Luego, regrese a la función "webix.protoUI" y escriba su funcionalidad:
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);

Lleno de contenido dos funciones. El primer "init" se ejecuta solo una vez al crear la "vista". Se llamará al segundo cuando necesitemos volver a dibujar el gráfico.
Ahora el contenido completo del archivo "view_chart.js" se verá así:
//     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 });
    };
};


A continuación, debe conectar el contenido del archivo "view_chart.js" en el archivo "renderer.js". ¿Por qué necesitamos agregar la línea "require (" ./ view_chart.js ") en la parte superior del archivo renderer.js como se muestra a continuación:
//   
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")


Ahora debe agregar un par de estilos al archivo "styles.css", abrirlo y agregar los estilos "ruta svg" y "#contenido" como se muestra a continuación:
.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);
}

Una vez que haya terminado con los estilos, puede intentar ejecutar nuestra aplicación y ver qué sucedió. Por lo tanto, presione "F5" y después de eso debería aparecer una ventana en la pantalla como se muestra en la Figura 7.


Fig. 7 - Ventana de nuestra aplicación

¿Qué vemos en ella? La parte superior es la barra de herramientas estándar de Webix. La parte central es el gráfico que creamos en myview. La parte inferior son tres controles deslizantes que debemos enseñar a cambiar los valores de los parámetros de nuestra función.

Hagamos que los controles deslizantes funcionen


Ahora pasemos al paso en el que volveremos a dibujar el gráfico en el medio de nuestra aplicación, dependiendo de los valores de los controles deslizantes "Amplitud", "Sesgo" y "Frecuencia". ¿Por qué agregamos el controlador de eventos "onChange" a los controles deslizantes como se muestra a continuación:

// 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());
                            }
                        }
                    }

En este controlador, accederemos a nuestro elemento por su "id" y llamaremos a la función "redibujar" que creamos anteriormente para volver a dibujar el gráfico, pasándole los valores actuales de los controles deslizantes. Haga clic en "F5", ejecute nuestra aplicación e intente cambiar los valores (Fig. 8).


Higo. 8 - Comprobación de la funcionalidad de los controles deslizantes

Tire del gráfico después de la ventana.


Y finalmente, agregamos una función que adaptará nuestro gráfico al tamaño de la ventana cuando cambie. ¿Por qué abrimos el archivo "view_chart.js" en el editor y agregamos un controlador al final que capta los cambios de la ventana como se muestra a continuación:

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

Esta función funciona cuando se cambia el tamaño de la ventana. Su funcionalidad se reduce a borrar el contenido del bloque "mycontent" y volver a dibujar el gráfico (llamando a la función "drawSin ()"). Cada vez que se llama a la función drawSin (), a las variables de ancho y alto se les asigna la información actual sobre los tamaños (alto y ancho) del bloque mycontent, después de lo cual el gráfico cambiará la escala para adaptarse a las dimensiones del bloque.

Conclusión


Eso es todo. Espero que esta información te sea útil. ¡Gracias! Las fuentes se pueden descargar aquí .

All Articles