实战《实现对Arduino图像化编程》开发(一)之环境搭建

开发依赖

Node.js 版本 16.13.1

官网地址:https://nodejs.org/zh-cn/

Electron 版本 16.0.4

官网地址:https://www.electronjs.org/

Semantic  UI

官网地址:Semantic UI

Bootstrap UI

官网地址:https://getbootstrap.net/

Ace.js

官网地址:https://ace.c9.io/

目录结构

 

built:

src:

        arduino:放置与blockly相关代码

        assets:放置img、css等一些静态资源

        core:核心代码,所有的逻辑功能实现

        pluglns:插件

        views:放置html文件、目前有启动页和主页

        app.js:在html中调用的js文件

        main.js:electron需要的主文件

        target.js:配置文件、放置一些配置信息

        package.json:定义需要的各种模块

        uncompressed.js:没有编译的逻辑代码,这个主要负责将我们编写的代码实现在                 home.html引用,后面新增的js文件就不再html中引用,而是在uncompressed.js添加间         接引用,之所以这个文件名称为uncompressed,是因为当我们发布后要压缩代码,所         以叫未编译

我们进入src下,执行如下命令,我使用的cnpm,执行完了就多了一个 node_modules文件夹

cnpm install

其中package.json代码如下:里面定义了需要用到的各种模块以及版本

{
  "name": "demo",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "build": {
    "appId": "com.me.app",
    "mac": {
      "icon": "../build/logo.icns",
      "target": [
        "dmg"
      ]
    },
    "win": {
      "icon": "../build/logo.ico",
      "target": [
        "zip"
      ]
    },
    "directories": {
      "output": "../dist"
    },
    "asar": true,
    "extraResources": [
      {
        "from": "../../cli/linux/arduino",
        "to": "../arduino"
      }
    ]
  },
  "dependencies": {
    "jquery": "^3.6.0",
    "serialport": "^9.2.8"
  },
  "devDependencies": {
    "electron": "^16.0.4",
    "electron-builder": "^22.14.5",
    "electron-rebuild": "^3.2.3",
    "google-closure-compiler": "20180402.0.0",
    "google-closure-library": "20190301.0.0"
  },
  "scripts": {
    "start": "electron .",
    "build-win": "sudo electron-builder --win",
    "build-mac": "sudo electron-builder --mac",
    "build-linux": "sudo electron-builder --linux",
    "build-linux-arm": "sudo electron-builder --linux --arm64"
  }
}

main.js 代码如下,这个electron的主进程

const electron = require('electron');
const {ipcMain} = require("electron");
const App = electron.app;
const Dialog = electron.dialog;
const BrowserWindow = electron.BrowserWindow;

const path = require('path');
const url = require('url');
const SerialPort = require('serialport');
const os = require('os');
const fs = require("fs");
const process = require('process');

const isMac = os.type() === 'Darwin';
const isLinux = os.type() === 'Linux';
const isWin = os.type() === 'Windows_NT';

electron.Menu.setApplicationMenu(null);

function Lzm() {
  // 主窗口
  this.home = null;
  // 启动窗口
  this.start = null;
  // 串口
  this.serialPort = null;
}

/**
 * 创建主窗口
 */
Lzm.prototype.createMainWindow = function(callback) {

  // 创建主窗口
  this.home = new BrowserWindow({
    title: 'AudDemo',
    width: 1200,
    height: 720,
    minWidth: 800,
    minHeight: 600,
    backgroundColor: '#FFF',
    plugins: true,
    webPreferences: {
      nodeIntegration: true,
      enableRemoteModule: true,
      contextIsolation: false,
    },
    show: false,
  });

  // 绑定Html
  this.home.loadURL(url.format({
    pathname: path.join(__dirname, 'views/home.html'),
    protocol: 'file:',
    slashes: true
  })).then();

  // 首次启动
  this.home.once('ready-to-show', () => {
    callback();
    this.home.show();
  });

  // 关闭时
  this.home.on('close', (e) => {
    this.home.webContents.send("close-app");
    e.preventDefault();
  });

  // 关闭后
  this.home.on('closed', () => {
    this.home = null;
  });
  // 调试工具
  // this.home.webContents.openDevTools();
};

/**
 * 创建启动界面
 */
Lzm.prototype.createStartWindow = function() {
  //获取屏幕像素计算窗口大小
  const size = electron.screen.getPrimaryDisplay().workAreaSize;
  let width = parseInt((Math.min(size.height, size.width) / 2).toString());
  let height = parseInt((width * 0.75).toString());

  //创建启动界面
  this.start = new BrowserWindow({
    width: width,
    height: height,
    minWidth: width,
    minHeight: height,
    webPreferences: {
      nodeIntegration: true,
      enableRemoteModule: true,
      contextIsolation: false,
    },
    transparent: true,
    frame: false,
    show: false
  });

  //加载启动页面
  this.start.loadURL(url.format({
    protocol: 'file:',
    pathname: path.join(__dirname, 'views/start.html'),
  })).then();

  //启动一次
  this.start.once('ready-to-show', () => {
    this.start.show();
  });
};

/**
 * 绑定
 */
Lzm.prototype.bind = function() {
  // 主进程于渲染进程间通信
};

/**
 * 应用准备完成
 */
App.on('ready', function() {
  const lzm = new Lzm();
  // 创建启动页
  lzm.createStartWindow();
  // 绑定监听
  lzm.bind();
});

/**
 * 退出
 */
App.on('window-all-closed', function() {
  App.quit();
});

app.js 我们暂时不需要编写代码

在views/start.html 代码如下,这个主要是用来显示启动界面,我们可以做一些与处理的操作,当然现在我们不需要,只是一个演示

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet" type="text/css" href="../plugins/bootstrap/bootstrap.min.css">
    <link rel="stylesheet" type="text/css" href="../plugins/semantic/semantic.min.css">
    <link rel="stylesheet" href="../assets/css/style.css">
    <script>window.$ = window.jQuery = require('jquery');</script>
</head>
<style>
    .start-page {
        width: 100%;
        height: 100%;
        background-image: linear-gradient(#063737, #063737, #0c7272);
        padding: 0;
    }

    .name {
        text-align: center;
        position: absolute;
        padding-top: 4rem;
        top: 25%;
        width: 100%;
        height: 50%;
        font-size: 4rem;
        font-weight: bold;
        color: #8dbaba;
    }

</style>
<body ondragstart="return false">
<div class="start-page">
    <div class="name">Dome</div>
</div>
</body>

<script>
  const {ipcRenderer} = require("electron");
  ipcRenderer.send("load-config", 0);

  // 代码授权使用
  // const hour = 48 - Math.ceil((new Date().getTime() - 1639926972171) / 1000 / 60 / 60);
  // setTimeout(() => {
  //   ipcRenderer.send("load-config", hour < 0);
  // }, 500);
</script>

</html>

页面大概是这样子

uncompressed.js代码如下,主要实现间接调用其他js,就不反复在home.html中添加引用

/**
 * 动态加载
 * @type {
   
   {css: dynamicLoading.css, js: dynamicLoading.js}}
 */
const dynamicLoading = {
  css: function(path) {
    if (!path || path.length === 0) {
      throw new Error('argument "path" is required !');
    }
    const head = document.getElementsByTagName('head')[0];
    const link = document.createElement('link');
    link.href = path;
    link.rel = 'stylesheet';
    link.type = 'text/css';
    head.appendChild(link);
  },
  js: function(path) {
    if (!path || path.length === 0) {
      throw new Error('argument "path" is required !');
    }
    var head = document.getElementsByTagName('head')[0];
    var script = document.createElement('script');
    script.src = path;
    script.type = 'text/javascript';
    head.appendChild(script);
  }
};

/**
 * 需要加载的js文件,无需写后缀 例如 jsFiles = ["test"]
 * @type {string[]}
 */
const jsFiles = [];

//动态加载 JS 文件
for (let i = 0, file; (file = jsFiles[i]); i++) {
  dynamicLoading.js("../" + file + '.js');
}

 在views/home.html 代码如下,这个用于主窗口内容显示的文件,其中插件也是在此引用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title></title>
    <link rel="stylesheet" type="text/css" href="../plugins/bootstrap/bootstrap.min.css">
    <link rel="stylesheet" type="text/css" href="../plugins/semantic/semantic.min.css">
    <link rel="stylesheet" href="../assets/css/style.css">
    <script>window.$ = window.jQuery = require('jquery');</script>
    <script type="text/javascript" src="../plugins/semantic/semantic.min.js"></script>
    <script type="text/javascript" src="../plugins/ace/ace.js"></script>
    <script type="text/javascript" src="../plugins/ace/ext-language_tools.js"></script>

</head>
<body ondragstart="return false"></body>
<script type="text/javascript" src="../uncompressed.js"></script>
</html>

这样我们的环境就搭建好了,执行下面命令可以运行electron

cd src
electron .

如果不出意外的话,就会看到以下界面,首先是现实启动界面,然后跳转到主界面,因为我什么都没写,所以是一个空白界面

 到这里我们已经完成了项目的准备工作,剩下就是编写逻辑。

上一篇  实战《实现对Arduino图像化编程》开发(前言)_js君-CSDN博客

猜你喜欢

转载自blog.csdn.net/weixin_43532890/article/details/122177867