electron关于应用功能之旅(六)|七日打卡

1,121 阅读6分钟

微信公众号:[猫十二的日常],欢迎留言和指出问题a

本节将讲剩下几个功能,离线/在线侦测 针对macos系统BrowserWindows的展示文件 原生文件拖放 离屏渲染 暗黑模式 在electron中嵌入网页等几个功能进行探讨

离线/在线侦测

离线在线监测是针对网络情况的判断,实际上这种监测不一定准确,跟软件所处的网络环境还有可能跑在虚拟环境下面的虚拟以太网处于"always connected" 状态,我们不可能完全依赖这个东西进行判断

渲染进程的事件探测是基于HTML5API中的navigator.onLine属性实现的

navigator.onLine 属性返回值:

  • false:如果所有网络请求都失败(例如,断开网络)。
  • true: 在其他情况下都返回 true

Renderer.js

const watcher = () => {
  console.log(navigator.onLine ? "在线" : "离线");
};
window.addEventListener("online", watcher);
window.addEventListener("offline", watcher);

//离线

按照下面的操作可以触发离线在线状态

image-20210115101802697

主进程的事件探测

这个其实在主进程并没有提供这个功能,但是我们可以基于ipc通讯将渲染进程监听到事件,传递到主进程.从而实现了主进程能够拿到在线离线的状态

Renderer.js

const { ipcRenderer } = require("electron");
const watcher = () => {
  console.log(navigator.onLine ? "在线" : "离线");
  ipcRenderer.send("is-offlne", navigator.onLine ? "在线" : "离线");
};
window.addEventListener("online", watcher);
window.addEventListener("offline", watcher);

//离线

Main.js

const { app, BrowserWindow, ipcMain } = require("electron");

ipcMain.on("is-offlne", (event, arg) => {
  console.log("现在所处的网络", arg);
});

//现在所处的网络 离线

针对 macOS系统 BrowserWindows的展示文件

在 macOS 上,您可以为应用程序中的任何窗口设置一个代表文件。这也意味着文件的icon也将展示在标题上面,我们可以使用command-click 或者 control-Click 可以触发一个文件的展示

function createWindow() {
  let win = new BrowserWindow({
    width: 1920,
    height: 1080,
    webPreferences: {
      nodeIntegration: true,
      webviewTag: true, //需要设置webview来启用这个
    },
  });
  win.setRepresentedFilename("/Users/liuyang/aymfx/学习/pr"); //这个是个目录
  win.setDocumentEdited(true);
  const contents = win.webContents;
  contents.openDevTools(); //打开调试工具
  win.loadURL("http://127.0.0.1:5500/2020-01-15/index.html");
}

image-20210115144556215

这个值针对mac平台其他os系统不存在可以设置这个玩意的配置,可能设置的时候需要针对这个单独处理

原生文件的拖放

作为一个桌面应用,拖拽功能肯定是必要的,将需要下载的文件或者目录的某个东西直接拖拽到桌面上或者指定的位置

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Electron演示</title>
</head>
<body>
    Electron演示
    <a href="#" id="drag">快来拽我</a>
    <webview src='./other.html' webpreferences="nodeIntegration=true" id="webview">
    </webview>
    <script src="./renderer.js"></script>
</body>
</html>

Main.js

ipcMain.on("ondragstart", (event, filePath) => {
  event.sender.startDrag({
    file: filePath,
    icon: "/Users/liuyang/aymfx/flowerPot.png", 
  });
});

renderer.js

document.getElementById("drag").ondragstart = (event) => {
  event.preventDefault();
  ipcRenderer.send("ondragstart", "/Users/liuyang/aymfx/flowerPot.png");
};

event.sender.startDrag对象的两个属性

  • file 需要复制的文件地址
  • icon 拖拽过程展示的icon样式 那个盆栽就是

image-20210115145741277

离屏渲染

我在实验过程中发现这个功能就是在不打开应用的情况下处理应用,然后屏幕展示成这样。离线模式不展示内容,但是我们可以通过截屏处理

image-20210115152432003

Main.js

const fs = require("fs");
const path = require("path");
app.disableHardwareAcceleration(); //禁用当前应用程序的硬件加速。这个方法只能在应用程序准备就绪(ready)之前调用。
// -------------
app.whenReady().then(createWindow);
function createWindow() {
  win = new BrowserWindow({ webPreferences: { offscreen: true } });
  win.loadURL("http://127.0.0.1:5500/2020-01-15/index.html");
  win.webContents.on("paint", (event, dirty, image) => { //截屏
    console.log("paint");
    fs.writeFileSync(path.resolve(__dirname, "ex.png"), image.toPNG()); //截屏生成一张图片
  });
  win.webContents.setFrameRate(60); //设置渲染的帧率
}

一般情况下用不到这个技术,我们只是展示一下具体的用法

暗黑模式

自动更新原生界面,对于你的应用以外的一些ui界面你是无法进行修改的,但是macos引入了全新的的系统级的黑暗模式,这样我们也可以根据本机的ap具体的应用。

index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Electron演示</title>
    <style>
        @media (prefers-color-scheme: dark) { //暗黑模式运用
            body {
                background: #333;
                color: white;
            }
        }

        @media (prefers-color-scheme: light) { //正常模式运用
            body {
                background: #ddd;
                color: black;
            }
        }
    </style>
</head>

<body>

    <h1>Electron演示</h1>
    <p>当前系统主题: <strong id="theme-source">System</strong></p>

    <button id="toggle-dark-mode">Toggle Dark Mode</button>
    <button id="reset-to-system">Reset to System Theme</button>
    <webview src='./other.html' webpreferences="nodeIntegration=true" id="webview">
    </webview>
    <script src="./renderer.js"></script>
</body>

</html>

renderer.js

const { ipcRenderer } = require("electron");

document
  .getElementById("toggle-dark-mode")
  .addEventListener("click", async () => {
    const isDarkMode = await ipcRenderer.invoke("dark-mode:toggle");
    document.getElementById("theme-source").innerHTML = isDarkMode
      ? "Dark"
      : "Light";
  });

document
  .getElementById("reset-to-system")
  .addEventListener("click", async () => {
    await ipcRenderer.invoke("dark-mode:system");
    document.getElementById("theme-source").innerHTML = "System";
  });

Main.js

ipcMain.handle("dark-mode:toggle", () => {
  if (nativeTheme.shouldUseDarkColors) {//判断是不是dark模式
    nativeTheme.themeSource = "light";
  } else {
    nativeTheme.themeSource = "dark";
  }
  return nativeTheme.shouldUseDarkColors;
});

ipcMain.handle("dark-mode:system", () => {
  nativeTheme.themeSouce = "system";
});

效果展示

image-20210115161218214

image-20210115161235552

整体的外观发生了变化,这样我们就能跟随系统了,还是很帅气的功能,可能就是适配比较麻烦点

在electron中嵌入网页

如果我们需要嵌入第三方的网页,这里有三种方式可以提供给我们选择webview、iframe、browserViews

每种方式提供的功能略有不同,在不同情况下很有用,为了帮助我们如何选择合适我们的外部嵌入网页,我们开始对这个进行差异性的解释

  • webview

官网似乎不推荐我们使用这个标签进行嵌入第三方的url,因为这个标签经历过巨大的架构更改,可能会影响到应用程序的稳定性(we do not recommend you to use use WebViews

这个标签是基于谷歌的webviews,这似乎不是很明确的支持electron,所以我们不能保证在未来的electron,一些关于webview的一些api是否有效,为了使用webview 我们需要将它设置为true

main.js
function createWindow() {
  let win = new BrowserWindow({
    width: 1920,
    height: 1080,
    webPreferences: {
      nodeIntegration: true,
      webviewTag: true, //需要设置webview来启用这个
    },
  });
  const contents = win.webContents;
  contents.openDevTools(); //打开调试工具
  win.loadURL("http://127.0.0.1:5500/2020-01-15/index.html");
}
#index..html
<webview src='./other.html' webpreferences="nodeIntegration=true" id="webview">
  </webview>
nodeIntegration=true 这个意味着外嵌入的网页将可以使用node的一些功能

因为webview是自定义的标签,仅在electron内部起作用,它们被实现为“进程外iframe”,这意味所有的交流只能通过ipc通讯来完成,具体看我之前的ipc通讯,也有写。webview元素具有许多自定义方法和事件,类似于webContents,使得我们能更好的控制内容

与iframe相比,加载可能稍微慢点,但是它提供了更丰富的功能和ipc的通讯机制。

  • iframe

这里的iframe的行为和浏览器中的类似,一个iframe元素能让我们加载额外的内容,只要他们的内容安全政策允许。iframe限制了功能数量,建议使用沙盒属性,并且只支持你需要的功能

  • browserViews

这个不是dom的功能,它创建和控制是由主进程去处理的,我们可以利用主进程创建一个新的渲染进程,它对应的就是一个web页面,这意味着它和现有创建的主窗体是完全分来的,并且不受现有的窗体控制,是一个完全独立的状态,但是还是由主进程进行管理

BrowserViews提供了对其内容的最大控制,因为它们实现webContents的方式类似于BrowserWindow的实现方式,但是,由于BrowserViews不是DOM的一部分,而是覆盖在DOM之上,因此您必须手动管理其位置,比如开新的窗口,进行一些操作。

基本上把electron的功能模块过了一遍,覆盖点主要涵盖现在我们常用的东西,一些不常用的,只是简短的带过,这些都是electron内置提供的方法,我们还是要学习一遍这样在工作中才能有这个印象直接就拿来用就行

如果觉得我的文章还可以,点个赞或者关注一下下,还有精彩的故事等着你哦,还可以云撸猫