文/玄魂
目錄
node-webkit學習(4)Native UI API 之window
前言
4.1 window api 概述
4.2 獲取和創建窗口
4.3 window對象屬性和方法
4.3.1 Window.window
4.3.2 Window.x/Window.y
4.3.3 Window.width/Window.height
4.3.4 Window.title
4.3.5 Window.menu
4.3.6 Window.isFullscreen
4.3.7 Window.isKioskMode
4.3.8 Window.zoomLevel
4.3.9 Window.moveTo(x, y)
4.3.10 Window.moveBy(x, y)
4.3.11 Window.resizeTo(width, height)
4.3.12 Window.resizeBy(width, height)
4.3.13 Window.focus()
4.3.14 Window.blur()
4.3.15 Window.show()
4.3.16 Window.hide()
4.3.17 Window.close([force])
4.3.18 Window.reload()
4.3.19 Window.reloadIgnoringCache()
4.3.20 Window.maximize()
4.3.21 Window.minimize()
4.3.22 Window.restore()
4.3.23 Window.enterFullscreen()
4.3.24 Window.leaveFullscreen()
4.3.25 Window.toggleFullscreen()
4.3.26 Window.enterKioskMode()
4.3.27 Window.leaveKioskMode()
4.3.28 Window.toggleKioskMode()
4.3.29 Window.showDevTools([id | iframe, headless])
4.3.30 Window.closeDevTools()
4.3.31 Window.isDevToolsOpen()
4.3.32 Window.setMaximumSize(width, height)
4.3.33 Window.setMinimumSize(width, height)
4.3.34 Window.setResizable(Boolean resizable)
4.3.35 Window.setAlwaysOnTop(Boolean top)
4.3.36 Window.setPosition(String position)
4.3.37 Window.setShowInTaskbar(Boolean show)
4.3.38 Window.requestAttention(Boolean attention)
4.3.39 Window.capturePage(callback [, image_format | config_object ])
4.3.40 Window.cookies.*
4.3.41 Window.eval(frame, script)
4.4 window事件
4.4.1 close
4.4.2 closed
4.4.3 loading
4.4.4 loaded
4.4.5 document-start
4.4.6 document-end
4.4.7 focus
4.4.8 blur
4.4.9 minimize
4.4.10 restore
4.4.11 maximize
4.4.12 unmaximize
4.4.13 move
4.4.14 resize
4.4.15 enter-fullscreen
4.4.16 leave-fullscreen
4.4.17 zoom
4.4.18 capturepagedone
4.4.19 devtools-opened
4.4.20 devtools-closed
4.4.21 new-win-policy
4.5 存在的問題
幾個月前,要開發一個簡易的展示應用,要求支持離線播放(桌面應用)和在線播放(web應用)。
當時第一想到的是flex,同一套代碼(或者只需少量的更改)就可以同時運行在桌面和瀏覽器上。由於很多展現效果要全新開發,我想到了impress.js(https://github.com/bartaz/impress.js/)。如果選擇impress.js,就意味着要將html5作為桌面應用,當時想到要封裝webkit,但是本人對這方面也不是很熟悉,時間也很有限,就又沿着這個方向搜索,找到了node-webkit(https://github.com/rogerwang/node-webkit)。
node-webkit解決了我通過html和js來編寫桌面應用的難題。
至於node-webkit的定義,按照作者的說法:
“ 基於node.js和chromium的應用程序實時運行環境,可運行通過HTML(5)、CSS(3)、Javascript來編寫的本地應用程序。node.js和webkit的結合體,webkit提供DOM操作,node.js提供本地化操作;且將二者的context完全整合,可在HTML代碼中直接使用node.js的API。”
node-webkit版本 >= v0.3.0才支持window api。
Native GUI API 中的window是對DOM頁面的windows的一個封裝,擴展了DOM window的操作,同時可以接收各種事件。
每一個window都繼承 了node.js中的 EventEmitter 對象,你可以使用Window.on(...)的方式監聽native window的事件。
為了有一個整體上的認識,和上一篇文章(node-webkit學習(3)Native UI API概覽)一樣,我們先做一個小例子。之后會在這個示例的基礎上測試window api的各個屬性和方法。
先創建windowdemo.html和package.json文件。
windowdemo.html文件代碼如下:
<html>
<head>
<title>windowdemo</title>
<metahttp-equiv="Content-Type"content="text/html; charset=utf-8"/>
</head>
<body>
<h1>window api 測試</h1>
<script>
var gui = require('nw.gui');
var win = gui.Window.get();
win.on('minimize', function () {
var element = document.createElement('div');
element.appendChild(document.createTextNode('窗口最小化'));
document.body.appendChild(element);
});
win.minimize();
var new_win = gui.Window.get(
window.open('http://ebook.xuanhun521.com')
);
new_win.on('focus', function () {
var element = document.createElement('div');
element.appendChild(document.createTextNode('新窗口被激活'));
document.body.appendChild(element);
//Unlisten the minimize event
win.removeAllListeners('minimize');
});
</script>
</body>
</html>
package.json代碼如下:
{
"name": "window-demo",
"main": "windowdemo.html",
"nodejs":true,
"width":100,
"height":200,
"window": {
"title": "windowdemo",
"toolbar": true,
"width": 800,
"height": 600,
"resizable":true,
"show_in_taskbar":true,
"frame":true,
"kiosk":false
},
"webkit":{
"plugin":true
}
}
現在我們簡單解釋下windowdemo.html,首先通過
var gui = require('nw.gui');
var win = gui.Window.get();
獲得當前窗口對象win,然后通過下面的代碼定義了窗口最小化事件的處理函數。
win.on('minimize', function () {
var element = document.createElement('div');
element.appendChild(document.createTextNode('窗口最小化'));
document.body.appendChild(element);
});
當窗口最小化時,在當前DOM文檔中添加一個div元素,文本內容為“窗口最小化”。
下面的代碼示例了如何打開一個新窗口。
通過類似的方式監聽新窗口的獲取焦點事件。
new_win.on('focus', function () {
var element = document.createElement('div');
element.appendChild(document.createTextNode('新窗口被激活'));
document.body.appendChild(element);
//Unlisten the minimize event
});
上面的代碼中通過removeAllListeners函數,移除了主窗口所有最小化事件的處理函數。
win.removeAllListeners('minimize');
運行程序,結果如下:
基本的獲取、新建窗口,創建和移除事件監聽函數的方式,現在都有了整體上的認識,下面對window的屬性和方法逐一介紹。
鄙視不標明出處的轉載,更多相關內容,歡迎訪問玄魂的博客(www.xuanhun521.com)
獲取和創建新的window都是使用get方法,在上面的示例中,已經演示的很清楚,無參的get方法獲取當前窗口對象。
var win = gui.Window.get();
向get方法傳入一個DOM window對象,會打開新的窗口。
var new_win = gui.Window.get(
window.open('https://github.com')
);
獲取新窗口對象的另一種方法是,使用nw.gui.Window.open方法。
var win = gui.Window.open('http://ebook.xuanhun521.com', {
position: 'center',
width: 901,
height: 127
});
該方法傳入一個url,可選的配置參數,新窗體會加載url。在最新版本的node-webkit,默認情況下新打開的窗口是沒有被激活的(未獲取焦點),如果想默認獲取焦點,可以在在配置中設置“focus”屬性為true,如下:
var win = gui.Window.open('http://ebook.xuanhun521.com', {
position: 'center',
width: 901,
height: 127,
focus:true
});
修改windowdemo.html如下,使用gui.Window.open的方式打開新窗口。
<html>
<head>
<title>windowdemo</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body >
<h1>window api 測試</h1>
<script>
var gui = require('nw.gui');
var win = gui.Window.get();
win.on('minimize', function () {
var element = document.createElement('div');
element.appendChild(document.createTextNode('窗口最小化'));
document.body.appendChild(element);
});
win.minimize();
//var new_win = gui.Window.get(
// window.open('http://ebook.xuanhun521.com')
//);
var new_win = gui.Window.open('http://ebook.xuanhun521.com', {
position: 'center',
width: 901,
height: 127,
focus: true
});
new_win.on('focus', function () {
var element = document.createElement('div');
element.appendChild(document.createTextNode('新窗口被激活'));
document.body.appendChild(element);
//Unlisten the minimize event
win.removeAllListeners('minimize');
});
</script>
</body>
</html>
Window.window屬性獲取的是當前DOM文檔中的window對象。
修改windowdemo.html內容如下:
<html>
<head>
<title>windowdemo</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body >
<h1>window api 測試</h1>
<script>
var gui = require('nw.gui');
var win = gui.Window.get();
if (win.window == window)//比較是否為DOM window
{
var element = document.createElement('div');
element.appendChild(document.createTextNode('Window.window 和DOM window對象相同'));
document.body.appendChild(element);
}
</script>
</body>
</html>
運行結果如下:
獲取或者設置當前窗口在當前顯示屏幕內的x/y偏移。
下面我們修改windowdemo.html,使其顯示后移動到屏幕的左上角。
var gui = require('nw.gui');
var win = gui.Window.get();
win.x = 0;
win.y = 0;
獲取或設置當前窗口的大小。
修改windowdemo.html的script如下:
<script>
var gui = require('nw.gui');
var win = gui.Window.get();
var windowWidth = win.width;
var windowHeight = win.height;
if (win.window == window)
{
var element = document.createElement('div');
element.appendChild(document.createTextNode('nativeWidth:' + windowWidth ));
document.body.appendChild(element);
}
</script>
運行結果如下:
獲取或者窗體的標題。
到目前為止,有兩個地方可以設置起始窗體的標題,package.json和DOM頁面的title。下面我們通過Window.title屬性先獲取再修改窗口標題。
修改后的頁面內容為:
<html>
<head>
<title>windowdemo</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body >
<h1>window api 測試</h1>
<input type="button" value="修改窗口標題" id="btn_ChangeTitle" onclick="changeTitle()"/>
<script>
var gui = require('nw.gui');
var win = gui.Window.get();
var windowWidth = win.width;
var windowHeight = win.height;
if (win.window == window)
{
var element = document.createElement('div');
element.appendChild(document.createTextNode('nativeWidth:' + windowWidth ));
document.body.appendChild(element);
}
function changeTitle()
{
win.title = "新標題";
}
</script>
</body>
</html>
程序啟動時界面如下:
點擊“修改窗口標題”按鈕之后:
獲取或設置window的menubar。會在menu一節中詳細介紹。
獲取或設置是否以全屏模式展現窗體。如果程序啟動時就全屏顯示,需要在package.json中配置(參考:http://www.xuanhun521.com/Blog/2014/4/10/node-webkit%E5%AD%A6%E4%B9%A02%E5%9F%BA%E6%9C%AC%E7%BB%93%E6%9E%84%E5%92%8C%E9%85%8D%E7%BD%AE)
獲取或設置是否啟用KioskMode。
獲取 或者設置窗體內頁面的zoom值。正值代表zoom in,負值代表zoom out。
如在之前的腳本中添加
win.zoomLevel = 50;
顯示效果如下:
如果設置
win.zoomLevel = -50;
效果如下:
移動窗口到指定坐標點。
以當前位置為0點,移動x,y距離。
重新設置窗口大小。
以當前窗口大小為基准,重新增加指定值到窗口的寬高。
使窗口獲取焦點。
使窗口失去焦點
顯示隱藏的窗口。在某些平台上,show方法並不會使窗口獲取焦點,如果你想在窗口顯示的同時使其獲取焦點,需要調用focus方法。
show(false)和Window.hide()方法效果一樣。
隱藏窗口。
關閉窗體。可以通過監聽close事件,阻止窗口關閉。但是如果force=true,將會忽略close事件的監聽程序。
一般情況下,我們會在程序中先監聽close事件,在事件處理函數中做一些基本工作再關閉窗口。如:
win.on('close', function() {
this.hide(); // Pretend to be closed already
console.log("We're closing...");
this.close(true);
});
win.close();
重新加載窗口。
重新加載窗體,強制刷新緩存。
是窗口最大化
最小化窗口。
恢復窗口到上一狀態。
使窗口進入全屏模式。這和html5的FullScreen API不同,html5可以使頁面的一部分全屏,該方法只能使整個窗口全屏。
退出全屏模式。
切換全屏模式。
進入Kiosk模式。Kiosk模式使應用全屏,並且阻止用戶退出。所以在該模式下必須提供退出Kiosk模式的途徑。
退出Kiosk模式。
切換Kiosk模式。
在窗口中打開開發者工具。
詳情 參見:https://github.com/rogerwang/node-webkit/wiki/Devtools-jail-feature
關閉開發者工具。
返回開發者工具是否被打開的狀態信息。
設置窗口的最大值。
設置窗口的最小值。
設置窗口是否可以被重置大小。
設置窗口是否總在最前端。
移動窗體到指定位置。目前只有“center”支持所有平台,將窗口移動到屏幕中央。
設置是否允許在任務欄顯示圖標。
是否需要身份驗證。
對窗口內的內容作截圖。我們通過一個實例來理解它的用法。
新建html:
<html>
<head>
<title>windowdemo</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body style="background: #333">
<h1>window 測試</h1>
<script>
var gui = require('nw.gui');
var win = gui.Window.get();
function takeSnapshot() {
win.capturePage(function (img) {
var base64Data = img.replace(/^data:image\/(png|jpg|jpeg);base64,/, "");
require("fs").writeFile("out.png", base64Data, 'base64', function (err) {
console.log(err);
});
}, 'png');
}
</script>
<div style="background: #123; width:100px; height:100px; border:1px solid #000">
</div>
<button onclick="takeSnapshot()">截圖</button>
</body>
</html>
在上面的代碼中,調用win.capturePage進行截圖,截圖的結果會傳入到回調函數中,傳入的數據是base64字符串,程序通過require("fs").writeFile方法將圖片輸出。
運行結果如下:
從node-webkit v0.9.3開始,可以通過配置參數的方式進行截圖了,使用方法如下:
// png as base64string
win.capturePage(function(base64string){
// do something with the base64string
}, { format : 'png', datatype : 'raw'} );
// png as node buffer
win.capturePage(function(buffer){
// do something with the buffer
}, { format : 'png', datatype : 'buffer'} );
配置項可用值參考:
{
format : "[jpeg|png]",
datatype : "[raw|buffer|datauri]"
}
默認情況下,format值為jpeg,datatype為datauri。
包含一些列處理cookie的方法。這些api的定義方式和chrome擴展相同。node-webkit支持get, getAll, remove 和 set 方法; onChanged 事件 (該事件支持支持 both addListener 和 removeListener 方法)。
和CookieStore有關的擴展api不被支持,因為node-webkit只有一個全局的cookie存儲。
在目標window或者iframe中執行javascript代碼段。script參數是要執行的javascript代碼。
鄙視不標明出處的轉載,更多相關內容,歡迎訪問玄魂的博客(www.xuanhun521.com)
本節介紹的事件,都可以通過Window.on()方法進行監聽,更多接收事件相關內容參考node.js文檔, EventEmitter。
關閉窗口事件。參考上文window.close()方法。
窗口關閉完畢事件。正常情況下在同一窗體內是無法監聽此事件的,以為窗口已經關閉,所有javascript 對象都被釋放掉了。
但是我們可以通過在另一窗口,監聽被關閉窗口的已關閉事件。如:
<script>
var gui = require('nw.gui');
//var new_win = gui.Window.get(
// window.open('http://ebook.xuanhun521.com')
//);
var new_win = gui.Window.open('http://ebook.xuanhun521.com', {
position: 'center',
width: 901,
height: 127,
focus: true
});
new_win.on('closed', function () {
var element = document.createElement('div');
element.appendChild(document.createTextNode('新窗口已經關閉'));
document.body.appendChild(element);
});
</script>
在當前窗體監聽新建窗體的已關閉事件,關閉新窗口后的顯示結果:
窗口正在初始化時的事件。
該事件只能在刷新窗口或者在其他窗口中監聽。
窗口初始化完畢。
function (frame) {}
窗體中的document對象或者iframe中的css文件都加載完畢,DOM元素還未開始渲染,javascript代碼還未執行,觸發此事件。
監聽事件的函數會接收一個frame參數,值為具體的iframe對象或者為null。
讀者可同時參考node webkit學習(2)基本結構和配置中的inject-js-start
function (frame) {}
文檔加載完畢觸發的事件。
獲取焦點的事件。
失去焦點的事件。
窗口最小化事件。
當窗口從最小化重置到上一狀態時觸發的事件。
窗口最大化事件。
窗口從最大化狀態重置到之前的狀態時觸發的事件。
窗口被移動后引發的事件。
事件處理函數應該接收兩個參數(x,y),是窗口的新位置。
窗體大小被重置時觸發的事件。
事件監聽的回調函數接收兩個參數(width,height),窗口的新大小。
窗口進入全屏模式時觸發的事件。
退出全屏模式時觸發的事件。
當窗體中文檔發生zooming時觸發的事件,帶有zoomlevel參數,參見上文的window.zoom屬性。
截圖完畢觸發的事件,事件的傳遞參數參考上文Window.capturePage函數的回調函數的參數定義。
開發者工具被打開觸發的事件。
事件的回調函數接收一個url參數,是打開開發者工具的窗口地址。
開發者工具被關閉時觸發的事件。
當一個新窗口被從當前窗口打開,或者打開一個iframe時觸發該事件。
function (frame, url, policy) {}
· frame 發起請求的子iframe,如果從頂層窗口中發起的請求,該值為null
· url 請求的地址
· policy 帶有以下方法的對象
o ignore() : 忽略請求。
o forceCurrent() :強制在同一frame中打開鏈接
o forceDownload() : 強制鏈接被下載或者在其他應用中打開
o forceNewWindow() : 強制在新窗口中打開鏈接
o forceNewPopup() : 強制在新的 popup window中打開鏈接
在linux下, setMaximumSize()/setMinimumSize()
和 setResizable()
方法不能被同時使用。
本文內容主要參考node-webkit的官方英文文檔(https://github.com/rogerwang/node-webkit/wiki/Window)。
下一篇文章,介紹Frameless window。
鄙視不標明出處的轉載,更多相關內容,歡迎訪問玄魂的博客(www.xuanhun521.com)
更多相關內容,歡迎訪問玄魂的博客(更多node-webkit相關內容 http://www.xuanhun521.com/Blog/Tag/node-webkit)
ps:nw.js,electron交流群 313717550