Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

利用 Electron 开发快速截图工具(一) #64

Open
YIXUNFE opened this issue Mar 20, 2016 · 2 comments
Open

利用 Electron 开发快速截图工具(一) #64

YIXUNFE opened this issue Mar 20, 2016 · 2 comments

Comments

@YIXUNFE
Copy link
Owner

YIXUNFE commented Mar 20, 2016

利用 Electron 开发快速截图工具(一)

上周和大家介绍了下 Electron,这周我们利用 Electron 实战开发一款简易的屏幕截图工具。先在这里罗列一下这款工具的一些需求点:

  • 主界面小巧,始终悬浮于屏幕之上,且不占据任务栏位置;
  • 支持快捷键截图与退出应用;
  • 支持保存截图文件;
  • 截图存于剪贴板,便于复制黏贴。

名词解释:

  • 主进程指 main.js;
  • 主界面指 index.html,是一个渲染进程;
  • 子界面,也是一个渲染进程。

这些文件名皆继承自 Electron 开胃篇(另可参阅 Electron Get Start 中的内容)。


设计思路

截图的实现核心在于获取屏幕截图,这里将会使用两个渲染进程配合实现完整功能。

  • 主界面负责展示按钮等;
  • 子界面负责展示屏幕截图,并允许用户通过选区得到最后的图像。

我们先看看主界面的一些功能点。

界面设置

界面小巧,是指界面中仅仅包含几个按钮,比如截图、退出按钮。一般应用所具备的最小化、最大化、关闭三个按钮,我们不需要。

始终悬浮于屏幕之上,这点类似 QQ 的主界面,无论你当前使用的是哪款软件,它始终居于最上层。

Electron 中有一个比较重要的类,叫 BrowserWindow。我们需要从这个类中找寻对应的 API 以实现上述需求。

让我们来修改一下主进程文件 main.js中关于开打窗口的代码:

app.on('ready', function() {
  ...
  mainWindow = new BrowserWindow({
    width: 216, 
    height: 46, 
    resizable: false, 
    frame: false,
    alwaysOnTop: true,
    skipTaskbar: true
  });
  ...
});

这点代码的意思是,在 Electron 准备完成后,即打开一个大小为 216x46 的窗口,而且这个窗口是不可被拉伸的。

参数选项 frame:false 表示窗口是一个 Frameless Window,没有工具栏、菜单栏等。

参数选项 alwaysOnTop: true 表示窗口始终在其他窗口之前。

参数选项 skipTaskbar: true 让应用不会出现在任务栏中。


在渲染进程主文件 index.html 中,我们添加两个按钮,以便观察效果。

<ul class="items">
  <li id="capture">截图</li>
  <li id="close">关闭</li>
</ul>
html, body, ul, li {padding: 0; margin: 0;}
body {background: #f1f1f1}
.items {height: 30px; line-height: 30px; width: 200px; overflow: hidden; padding: 8px;}
.items li {border-radius: 4px; width: 80px; margin: 0 10px; height: 30px; float: left; text-align: center; line-height: 30px; list-style: none;  cursor: pointer}
.items li:hover {background: #000; color: #fff;}

效果图:

000

这里需要注意的是,我们的窗口由于没有边框部分,所以目前无法自由的拖动。在页面上添加 -webkit-app-region: drag 即可解决这个问题。

但是该属性会导致可点击按钮的点击事件难以触发,所以需要在按钮上添加 -webkit-app-region: no-drag 以提高体验。

body {-webkit-app-region: drag;}
.items li {-webkit-app-region: no-drag;}

快捷键设置

Electron 通过 globalShortcut 模块管理快捷键。用法也超级简单:

var globalShortcut = electron.globalShortcut;
globalShortcut.register('ctrl+shift+q', function () {
  mainWindow.webContents.send('global-shortcut-quit', 1);
}); 
globalShortcut.register('ctrl+shift+c', function () {
  mainWindow.webContents.send('global-shortcut-capture', 1);
});

这里我设置了两组快捷键,一个是截图,一个是退出。对应在渲染进程中的代码:

var ipc = require('ipc');
ipc.on('global-shortcut-quit', function (arg) {
  var event = new MouseEvent('click');
  document.getElementById('close').dispatchEvent(event);
});
ipc.on('global-shortcut-capture', function (arg) {
  var event = new MouseEvent('click');
  document.getElementById('capture').dispatchEvent(event);
});

ipc 模块用于实现主进程与渲染进程通信。在快捷键句柄触发时,主进程发送消息至渲染进程,渲染进程触发对应的事件句柄。


屏幕截图

Electron 为我们提供了 desktopCapturer 模块用以获取截图。查看文档

var desktopCapturer = require('electron').desktopCapturer;
desktopCapturer.getSources({types: ['window', 'screen']}, function(error, sources) {
  ...
})

上述代码最终会获得几个数据源,对应参数数组中的 windowscreenwindow 参数表示应用窗口,screen 表示屏幕窗口。另外还有一个和 tyoes 参数一起的是 thumbnailSize,默认截图的缩略图大小是 150x150

所以我们结合自身需求,代码会是这样的:

var desktopCapturer = require('electron').desktopCapturer,
  w = screen.width,
  h = screen.height

desktopCapturer.getSources({types: ['screen'], thumbnailSize: {width: w, height: h}}, function(error, sources) {
  if (error) throw error;
  localStorage['img'] = sources[0].thumbnail.toDataURL()
});

代码中我们指定缩略图即原图大小,最后将截图数据转化成 DataURL 形式存放于 localStorage 中,以便于子页面获取截图。


按钮功能

目前仅两个按钮:截图与关闭。

关闭按钮即关闭应用。由于在主进程 main.js 中已经有如下代码:

app.on('window-all-closed', function() {
  if (process.platform != 'darwin') {
    app.quit();
  }
});

当所有应用窗口皆关闭时,即关闭应用。所以我们的关闭按钮只要确保主界面与子界面关闭即可。

subWindow && subWindow.close()
window.close()
此处有坑哦,在下一篇中有提及。

截图按钮的功能除了上面提到的截图,还需要打开子界面。子界面会展示屏幕截图,以便用户进一步选取其中部分进行保存或者复制黏贴。

subWindow = new BrowserWindow({width: w, height: h, resizable: false, skipTaskbar: true, frame: false, alwaysOnTop: true});
subWindow.loadURL('file://' + __dirname + '/sub.html');

这篇就讲到这里,下一篇我们将实现子界面中的选区截图等功能。


Thanks


@jincdream
Copy link

要是有人能大概翻译和描述下Electron Documentation就比较多人喜欢了

@YIXUNFE
Copy link
Owner Author

YIXUNFE commented Mar 21, 2016

我们也觉得确实缺少一个组织做专门的前端技术相关的翻译工作,希望以后能有一批英文好的前端er为我们开路。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants