概要

俗话说水生金,摸鱼 = 水,得出定式摸鱼 ≈ 生金。

下面提到的项目我已经开源,发布在 gitee,检索 fish-ads-app 可以查看。

正文

前段时间刷小红薯看到一些将桌面背景改为客厅的效果图,然后将视频的小窗口模式放在效果图的电视上的达人。

我心想这小窗口模式太危险了吧,而且谁上班一直待在桌面不动的呀,直到后来刷到了下面这个视频。

看来大家都有在努力上班啊!

她把小窗口视频叠加到了 360 弹层之上,同事愣是没发现(当然也有摆拍可能)。

但是仔细看的话视频窗口的大小和弹层的大小是不匹配的,最右边超出了一小部分,而且这样做虽然比桌面效果图的方法更安全些,但是弹层被关闭后视频窗口不会一起关闭。

不过想法是很不错,如果视频能嵌入到弹层里(大小统一,弹层关闭时一起消失)变成一个真的假弹层,不就更完美了。那这个时候我就想到了 Electron,一款使用 JavaScript、HTML 和 CSS 构建桌面应用程序的框架。那我本人前端会一些,Election 之前也跟着官网起步文档运行过,既然理论成立直接开搞。

一开始我的想法是这样的,输入视频地址然后直接进入到弹层模式显示。但是后来我觉得既然 Chromium 已经嵌入到 Electron 框架中了,要不直接跳出一个搜索引擎的界面让使用者自己搜索到想看的视频地址页面,然后再变成弹层不是更加舒服。

那第一个窗口我是这样做的:

  // Create the browser window.
const win = new BrowserWindow({
width: 800,
height: 600
}) await win.loadURL("https://cn.bing.com/") // 拦截打开新窗口
win.webContents.setWindowOpenHandler(details => {
win.loadURL(details.url)
return { action: 'deny' }
})

创建一个默认窗口 使用 loadURL 加载一个搜索引擎的地址(以必应为例),然后我只想在一个窗口中跳转链接,于是当该窗口点击了跳转链接时阻止跳转且让当前窗口重新加载跳转地址。

那么除了自己搜索外,大多数时候我们是在B站腾讯视频爱奇艺等主流的视频网站上刷剧看视频的。那么我们需要自定义一个Menu,加入一些主流视频网站的地址作为快捷跳转。最后把选定的视频地址传入到弹层窗口显示,那么Menu的配置大致如下:

const template = [
{
label: '视频',
submenu: [
{
label: '哔哩哔哩',
click: () => {
var focusedWin = BrowserWindow.getFocusedWindow()
focusedWin.loadURL('https://www.bilibili.com/').catch(error => console.error(error))
}
},
{
label: '腾讯视频',
click: () => {
var focusedWin = BrowserWindow.getFocusedWindow()
focusedWin.loadURL('https://v.qq.com/').catch(error => console.error(error))
}
},
// ......
],
},
{
label: '弹窗',
click: async () => {
var focusedWin = BrowserWindow.getFocusedWindow()
// 这里的地址是为了重新选择视频地址是记录上一个播放地址
lastUrl = focusedWin.webContents.getURL()
focusedWin.hide()
createPopupWindow()
}
}
] const createPopupWindow = async () => {
const primaryDisplay = screen.getPrimaryDisplay()
const { width, height } = primaryDisplay.workAreaSize // ipc 监听在 loadURL 之前,防止事件未注册
initIpcMain() const win = new BrowserWindow({
width: 370,
height: 470,
x: width - (370 + 10),
y: height - (470 + 10),
movable: false, // 窗口是否可移动
hasShadow: false, // 窗口是否显示阴影
frame: false, // 窗口是否显示边框
show: false, // 等 loadURL 完成之后再显示
alwaysOnTop: true, // 窗口是否置顶
skipTaskbar: true, // 窗口是否显示在任务栏中
webPreferences: {
webviewTag: true, // 启用 webview
preload: path.join(__dirname, 'preload.js'), // 预加载脚本
nodeIntegration: true,
contextIsolation: false
}
})
await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL).catch(error => console.error(error))
win.show()
} // 初始化 IPC 事件
const initIpcMain = () => {
// 获取最新页面的 URL(页面加载就要获取的方法要写在 loadURL 之前)
ipcMain.handleOnce('webview-url', () => {
return lastUrl
})
}

这里主要是处理了快捷地址和选择后的地址通过ipc 通信传入到页面,这里配置的预加载脚本 preload.js 通过 ipcRenderer.invoke('webview-url')能访问到如上配置的ipcMain.handleOnce('webview-url')从而获得上一个窗口的选择地址。点击窗口模式后创建一个新的 BrowserWindow,大小类似广告弹层且显示在桌面的右下角。

Electron 在流程上差不多就这些,接下来就要考虑页面的展示了。首先想到的是将视频内容通过iframe标签嵌入在中间,上面是假的广告,下面是时间,假期的显示(如视频中展示的位置一样)。但是 iframe 有一个有同源策略的安全限制问题,不是所有的网站都允许你页面里面套页面的。于是就要用到另一个标签webview,与 iframe不同, webview 独立于你的应用程序运行,在 Electron 的文档中有提到 webview 的部分,可以自行查看更多详情。

<body>
<!-- 省略 -->
<main></main>
<!-- 省略 -->
</body>

HTML 部分只需要像视频里那样排版就行,这里我们主要关注中间部分。

const main = document.querySelector('main')
const webview = document.createElement('webview') window.electronAPI.webviewUrl().then(url => {
webview.src = url
})
main.appendChild(webview) webview.addEventListener('dom-ready', () => {
webview.style.display = 'inline-flex'
webview.style.width = '100%'
webview.style.height = 'calc(100vh - 263px)'
})

JS部分在获取地址之后,创建一个webview标签设置完属性和样式后追加到 main 标签里。这样基本上就大功告成了。

但是在我做出第一版的时候发现一个问题。想要完美显示得需要视频网站支持网页全屏显示的功能,注意是网页全屏,不是屏幕全屏,只需要在显示的部分占满即可。因为一开始我只以B站和腾讯视频作为示例,它两都有网页全屏,而其他网站是没有或不完美支持的(如爱奇艺,有这个功能但是有最小宽度(lll¬ω¬))。

既然原站没有只能自己造了,还好 webview 支持插入脚本,<webview>.executeJavaScript(code[, userGesture])

Election webview 标签 部分的文档中有提到:在页面中执行 code。 如果设置了userGesture,它将在页面中创建用户手势上下文。 像 requestFullScreen 这样的需要用户操作的HTML API可以利用这个选项来实现自动化。

当然我们不需要实现 requestFullScreen,因为那是屏幕全屏的方法。不过我们需要这个用户手势上下文,将userGesture设置为true即可。

既然可以插入脚本了,那么我的第一个想法就是,把无关内容全部设置displaynone,并且将video标签复制到body标签下成为它的的子集,然后将video设置样式,zInde调大置顶显示。

但是我想到这个解决方案的时候觉得自己真是个天才,然后不是所有的网站都是以video标签播放的,可能在页面里还套了个 iframe 标签来展示视频,当然这是试了腾讯视频之后得出来的,一开始我一直以为是我脚本的问题,没想到广告的 video 播放完之后,页面上再也不存在 video 标签了(好在广告的 video 都是播放完就消失,不然很难区分有效的 video 标签)。后来我暂时妥协,因为腾讯支持网页全屏功能,我只要模拟点击按钮就可以了(lll¬ω¬),于是第二版诞生,支持自动网页全屏,当然只支持Menu中配置的一些。

不过 iframe 播放的方式也是可以像 video 复制的方法解决的,之后的版本应该会解决这个问题,使得通过 iframe 播放网站也能使用。

总结

可以看出,对于办公党 Electron 的用途还是很广的。你只要会前端且跟着起步文档搭一搭,加上你自己的想法,一个有趣的桌面工具就诞生了!

Electron 办公党的摸鱼神器的更多相关文章

  1. Thief-Book 上班摸鱼神器

    Thief-Book 上班摸鱼神器 介绍 Thief-Book 是一款真正的摸鱼神器,可以更加隐秘性大胆的看小说. 隐蔽性 自定义透明背景,随意调整大小,完美融入各种软件界面 快捷性 三个快捷键,实现 ...

  2. vscode插件(摸鱼神器-小霸王游戏机

    vscode插件(摸鱼神器-小霸王游戏机 步骤 vscode扩展搜索小霸王,点击下载即可. 使用 默认有一个demo小游戏,即超级玛丽. 本地仓库 可以通过local菜单上的添加按钮添加本地nes r ...

  3. 【摸鱼神器】UI库秒变LowCode工具——列表篇(一)设计与实现

    内容摘要: 需求分析 定义 interface 定义 json 文件 定义列表控件的 props 基于 el-table 封装,实现依赖 json 渲染 实现内置功能:选择行(单选.多选),格式化.锁 ...

  4. 【转】让Chrome化身成为摸鱼神器,利用Chorme运行布卡漫画以及其他安卓APK应用教程

    下周就是十一了,无论是学生党还是工作党,大家的大概都会有点心不在焉,为了让大家更好的心不在焉,更好的在十一前最后一周愉快的摸鱼,今天就写一个如何让Chrome(google浏览器)运行安卓APK应用的 ...

  5. 【摸鱼神器】基于SSM风格的Java源代码生成器 单表生成 一对一、一对多、多对多连接查询生成

    一.序言 UCode Cms 是一款Maven版的Java源代码生成器,是快速构建项目的利器.代码生成器模块属于可拆卸模块,即按需引入.代码生成器生成SSM(Spring.SpringBoot.Myb ...

  6. 【摸鱼神器】UCode Cms管理系统 内置超好用的代码生成器 解决多表连接痛点

    一.序言 UCode Cms管理系统是面向企业级应用软件开发的脚手架.当前版本1.3.4.快速体验: git clone https://gitee.com/decsa/demo-cms.git (一 ...

  7. 【摸鱼神器】一次搞定 vue3的 路由 + 菜单 + tabs

    做一个管理后台,首先要设置路由,然后配置菜单(有时候还需要导航),再来一个动态tabs,最后加上权限判断. 这个是不是有点繁琐?尤其是路由的设置和菜单的配置,是不是很雷同?那么能不能简单一点呢?如果可 ...

  8. 【摸鱼神器】UI库秒变LowCode工具——列表篇(二)维护json的小工具

    上一篇介绍了一下如何实现一个可以依赖 json 渲染的列表控件,既然需要 json 文件,那么要如何维护这个 json 文件就成了重点,如果没有好的维护方案的话,那么还不如直接用UI库. 所以需要我们 ...

  9. 【摸鱼神器】UI库秒变低代码工具——表单篇(一)设计

    前面说了列表的低代码化的方法,本篇介绍一下表单的低代码化. 内容摘要 需求分析. 定义 interface. 定义表单控件的 props. 定义 json 文件. 基于 el-form 封装,实现依赖 ...

  10. 【摸鱼神器】UI库秒变低代码工具——表单篇(二)子控件

    上一篇介绍了表单控件,这一篇介绍一下表单里面的各种子控件的封装方式. 主要内容 需求分析 子控件的分类 子控件属性的分类 定义 interface. 定义子控件的的 props. 定义 json 文件 ...

随机推荐

  1. centos7 下全局配置最新版的golang语言开发环境

    按照以下步骤进行操作: 前往Go官方网站下载页面(https://golang.org/dl/)查找最新版本的Go二进制文件. 使用wget命令下载最新版本的Go二进制文件.例如,如果最新版本是1.1 ...

  2. 【Ubuntu】ARM交叉编译开发环境解决“没有那个文件或目录”问题

    [Ubuntu]ARM交叉编译开发环境解决"没有那个文件或目录"问题 零.起因 最近在使用Ubuntu虚拟机编译ARM程序,解压ARM的GCC后想要启动,报"没有那个文件 ...

  3. 【安卓】使用Handler出现的警告

    使用Handler出现的警告 零.原由 安卓中使用Hander时出现了如下警告: This Handler class should be static or leaks might occur (a ...

  4. git 取消 git add 操作

    ... 按照套路我们在对项目做了一些新增或修改操作后,会很自然的执行 git add 操作, 但是马上又发现好像添加的内容有点不对: 文件名错了 多了个符号 少了点什么 马上发现bug 等等... 总 ...

  5. P3392 涂国旗 题解

    题目大意 题目真的是不说人话...... 有一个国家的国旗是由一个 N * M 的方格组成的.如果想要这面国旗合法,就必须满足要求: 国旗从上到下必须是白色.蓝色和红色,顺序不能改变. 每一种颜色都至 ...

  6. shell处理字符串

    概念 字符串是shell编程中最常用最有用的数据类型(除了数字和字符串,也没啥其它类型好用了),字符串可以用单引号,也可以用双引号,也可以不用引号. 单引号声明字符串 单引号里的任何字符都会原样输出, ...

  7. java开发中简简单单的全局异常处理

    今天吃饭时,被公司新来的同事问道:"项目controller层里好多都没写try,catch,难道异常不用处理吗?".虽然正吃饭时被打扰,让我很讨厌,但是既然他诚心诚意的问了,本着 ...

  8. Java 的 CMS 垃圾回收流程

    Java 的 CMS 垃圾回收流程 CMS(Concurrent Mark-Sweep)垃圾回收器 是一种并发垃圾回收器,旨在减少垃圾回收时的停顿时间,适用于对低延迟要求较高的应用.CMS 主要通过并 ...

  9. mysql设置时区

    参考:https://blog.csdn.net/vkingnew/article/details/82149726 查看时区 show variables like '%time_zone%'; 设 ...

  10. 设计模式之“外观模式(门面模式)(Facade)”

    一.外观模式 1.概念 为子系统中的一组接口提供一个一致的界面 此模式定义了一个高层接口 这个接口使得这一子系统更加容易使用 他完美的体现了依赖倒转原则和迪米特法则的思想,是常用模式之一 2.何时使用 ...