徒手從零實現 uTools 系列(三)- 螢幕取色和截圖

muwooo發表於2021-07-07

前言

為了進一步提高開發工作效率,最近我們基於 electron 開發了一款媲美 uTools 的開源工具箱 rubick。該工具箱不僅僅開源,最重要的是可以使用 uTools 生態內所有開源外掛!這將是巨大的能力,意味著 uTools 生態內所有外掛可以無差異化使用到 rubick 中。

設計互動上為了更能提高使用者的使用效率,我們又嘗試去實現了 uTools 中非常優秀的一些設計,比如:全域性取色和截圖。全域性取色在獲取一些圖片、其他App應用的顏色時非常有用。截圖雖然可以使用釘釘或者微信自帶的截圖功能,但是為了更加符合 uTools 使用者習慣,我們也順便實現了一下。

接下來進入主題,我們來基於 rubick 來一步步實現一個取色和截圖能力。

程式碼倉庫

Rubick github

功能演示:

QQ20210707-170430.gif

實現取色

要實現螢幕取色能力,主要核心能力步驟如下:

  1. 跟隨滑鼠移動,獲取當前螢幕滑鼠位置
  2. 獲取當前座標的顏色

1. 獲取滑鼠移動的座標

要獲取系統滑鼠移動的座標,electron 本身沒有提供相關的函式和能力,所以要實現跟隨獲取系統滑鼠位置,可能要呼叫原生能力。好在有一個 iohook 這樣一個強大的系統呼叫工具,可以幫助我們監聽系統滑鼠操作以及按鍵操作。所以我們可以基於 iohook 來實現位置座標獲取。在 electron 中按照 iohook,在 npm install iohook 之前,需要在 package.json 中配置:

"iohook": {
  "targets": [
    "node-72",
    "electron-85"
  ],
  "platforms": [
    "win32",
    "darwin",
    "linux"
  ],
  "arches": [
    "x64",
    "ia32"
  ]
}

後面在 install 的時候會為我們按照所需下載通過 node-gyp 編譯好的 node 可呼叫的包。如果需要重新編譯,需要再重新執行命令:

"rebuild": "npm rebuild --runtime=electron --target=5.0.0 --disturl=https://atom.io/download/atom-shell --abi=80"

具體需要哪個版本的 nodeelectron 可以參考這篇文章

準備工作做完之後,接下來就是呼叫 iohook 獲取滑鼠移動位置:

 ioHook.on('mousemove', ({x, y}) => {
  // todo
})

2. 獲取當前座標位置顏色

這裡,需要利用到另一個庫 robotjs,該庫提供了強大的系統操作能力,最最最重要的是他可以獲取到畫素點的色彩,這就很關鍵了。這個正好是我們需要的:

 let color = "#" + robot.getPixelColor(parseInt(x), parseInt(y));

到這裡就基本上完成了。

另一種實現方案

上面是一種比較常規的做法,但除了上面的方式,還有沒有其他的方式呢?當時我也想了很久,後來仔細想想,electron 雖然獲取不到系統滑鼠位置和點選以及系統級別的畫素,但是如果我們的螢幕本身就是一個 electronbrowserWindow 那就可以通過 DOM 來實現啦!

確實這是一個思路,核心步驟拆解下來就是:

  1. 根據當前顯示器個數渲染對應個數 browserWindow
  2. 每個 browserWindow 尺寸設定成透明全屏的
  3. 獲取每個 screen 的全屏截圖
  4. 繪製截圖到 browserWindow 的 canvas 上
  5. 從系統級操作轉成 electron 內部操作

具體的實現方式這裡就不細說,因為下面截圖採用的就是這種方案。

實現系統截圖

系統截圖就可以參考上面所述,採用分屏渲染子視窗,再操作子視窗的方式來實現,這裡我也是參考了:從零開始用 electron 手擼一個截圖工具

最後

本篇主要介紹如何實現一個類似於 utools 的取色、截圖能力,當然這遠遠不是 utools 的全部,下期我們再繼續介紹如何實現 utools 其他能力。歡迎大家前往體驗 Rubick 有問題可以隨時提 issue 我們會及時反饋。

另外,如果覺得設計實現思路對你有用,也歡迎給個 Star:https://github.com/clouDr-f2e/rubick

相關文章