Clipboard API

Clipboard API 允许异步地读写剪切板

剪切板操作通过 Navigator 接口的 clipboard 属性暴露的 Clipboard 接口实例使用

剪切板的部分操作需要获得 clipboard-write 权限和 clipboard-read 权限

读写文本

使用 Clipboard 接口的 writeText() 方法向剪切板中写入文本

方法接收一个字符串参数,代表向剪切板写入的文本内容

1
navigator.clipboard.writeText('data')

若存在用户交互,方法调用会自动授予 clipboard-write 权限

使用 Clipboard 接口的 readText() 方法从剪切板中读取文本

方法返回一个字符串,代表从剪切板读取的文本内容

1
const data = await navigator.clipboard.readText()

方法调用需要用户授予 clipboard-read 权限

读写复杂格式

使用 Clipboard 接口的 write() 方法向剪切板中写入复杂格式内容

方法接收一个 ClipboardItem 数组,代表要向剪切板写入的数据

调用 ClipboardItem() 构造函数创建 ClipboardItem 实例

需传入一个数据对象,该对象要求键为数据的 MIME 类型,值为实际数据(允许为 Promise)

1
2
3
4
5
navigator.clipboard.write([
new ClipboardItem({
'text/plain': new Blob(['data'], { type: 'text/plain' }),
}),
])

方法调用需要用户授予 clipboard-write 权限

使用 Clipboard 接口的 read() 方法从剪切板中读取复杂格式内容

方法返回一个 ClipboardItem 数组,代表要从剪切板读取的数据

ClipboardItem 实例的 types 属性反映其支持的 MIME 类型

ClipboardItem 实例的 getType() 方法根据指定的 MIME 类型返回对应的 Blob

1
2
3
const datas = await navigator.clipboard.read()

const blob = await datas.at(0).getType('text/plain')

方法调用需要用户授予 clipboard-read 权限

权限 API

该 API 调用需要用户授予 clipboard-readclipboard-write 权限,可以调用 Permission.query() 方法检查用户是否已授予了该权限

类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
interface Clipboard extends EventTarget {
read(): Promise<ClipboardItems>
readText(): Promise<string>
write(data: ClipboardItems): Promise<void>
writeText(data: string): Promise<void>
}

declare var Clipboard: {
prototype: Clipboard
}

interface ClipboardItem {
readonly types: ReadonlyArray<string>
getType(type: string): Promise<Blob>
}

declare var ClipboardItem: {
prototype: ClipboardItem
new(items: Record<string, string | Blob | PromiseLike<string | Blob>>): ClipboardItem
}

链接

Broadcast Channel API

Broadcast Channel API 允许在同源的浏览上下文中交换数据

创建广播频道

通过直接调用 BroadcastChannel() 构造函数来创建一个广播频道

需要传递一个字符串参数,代表广播频道的名称

若该名称的广播频道已经创建,则会复用并加入已有的广播频道

1
const bc = new BroadcastChannel('bc')

传递的广播频道名称可以经由 BroadcastChannel 实例的 name 只读属性读取

发送消息

通过调用 BroadcastChannel 实例的 postMessage() 方法来向广播频道发送消息

1
bc.postMessage('message')

发送的消息会经由结构化克隆算法处理,因此任意可由结构化克隆算法处理的类型的数据均可发送

订阅消息

通过监听 BroadcastChannel 实例的 message 事件监听成功接收的消息

1
2
3
bc.addEventListener('message', (e) => {
console.log(e.data)
})

通过监听 BroadcastChannel 实例的 messageerror 事件监听接收失败的消息

1
2
3
bc.addEventListener('messageerror', (e) => {
console.log(e.data)
})

关闭广播频道

通过调用 BroadcastChannel 实例的 close() 方法来断开与广播频道的连接

1
bc.close()

广播频道在没有任一浏览上下文连接至其时被回收

示例

收到的信息为:

类型

1
2
3
4
5
6
7
8
9
10
11
12
interface BroadcastChannel extends EventTarget {
readonly name: string
onmessage: ((this: BroadcastChannel, ev: MessageEvent) => any) | null
onmessageerror: ((this: BroadcastChannel, ev: MessageEvent) => any) | null
close(): void
postMessage(message: any): void
}

declare var BroadcastChannel: {
prototype: BroadcastChannel
new(name: string): BroadcastChannel
}

链接

Document Picture-in-Picture API

Document Picture-in-Picture API 是对原有 Picture-in-Picture API 的扩展,允许任意 DOM 元素进入画中画模式

任意时刻,每个顶层浏览上下文只能存在一个画中画窗口(多次调用会复用之前的画中画窗口)

该 API 必须在严格上下文模式下调用

Window 接口暴露的 documentPictureInPicture 只读属性提供的 DocumentPictureInPicture 接口实例来使用该 API

打开画中画窗口

DocumentPictureInPicture 接口的 requestWindow() 方法用于打开一个画中画窗口

方法传入一个可选的配置项,其 width 选项和 height 选项代表画中画窗口的宽度和高度

方法返回一个 Promise 的 Window,代表当前文档对应的画中画窗口

方法可能抛出 NotSupportedError,若该 API 不被支持(如因为用户的设置)

方法可能抛出 NotAllowedError,若未因为用户交互调用,或未在顶层浏览上下文在调用,或在画中画窗口中调用

方法可能抛出 RangeError,若参数 widthheight 仅指定其一或另一为 0

1
2
3
4
const pipwindow = await window.documentPictureInPicture.requestWindow({
width: 800,
height: 600,
})

DocumentPictureInPicture 接口的 enter 事件在打开画中画窗口时触发,返回一个 DocumentPictureInPictureEvent 事件

画中画窗口

DocumentPictureInPicture 接口的 window 只读属性返回 Windownull,反映当前文档对应的画中画窗口,若不存在返回 null

DocumentPictureInPicture 接口的 requestWindow() 方法打开的画中画窗口与 Window 接口的 open() 方法打开的同源的窗口类似

但存在以下一些区别:

  • 画中画窗口始终浮动在其他窗口顶部
  • 画中画窗口的生命周期一定不会比打开其的窗口的生命周期晚结束
  • 画中画窗口无法被导航
  • 画中画窗口的位置无法被网站设置

关闭画中画窗口

可能因为用户点击关闭按钮而关闭,或是调用 Window 接口的 close() 方法编程式关闭

在画中画窗口关闭时,类似与普通页面一样,可以通过监听 pagehide 事件其发生的时机

类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
interface Window {
readonly documentPictureInPicture: DocumentPictureInPicture
}

interface DocumentPictureInPicture extends EventTarget {
requestWindow(options?: DocumentPictureInPictureOptions): Promise<Window>
readonly window: Window | null
onenter
}

interface DocumentPictureInPictureOptions {
width: number
height: number
}

interface DocumentPictureInPictureEvent extends Event {
constructor(type: string, eventInitDict: DocumentPictureInPictureEventInit)
readonly window: Window
}

interface DocumentPictureInPictureEventInit extends EventInit {
window: Window
}

链接

Vibration API

Vibration API 允许调用设备的振动功能

若设备不支持振动,调用该方法不会具有任何效果

振动

Navigator 接口的 vibrate() 方法负责执行振动

方法传入一个数值或一个数值数组,代表振动的模式

方法返回一个 boolean,表示是否因为方法参数的合法性导致能否进行振动

1
2
3
4
navigator.vibrate(200)
navigator.vibrate([200])
navigator.vibrate([200, 100, 200])
navigator.vibrate(0)

若传入一个数值或仅有一个数值的数组,代表执行给定时间的一次振动

若传入一个数值数组,按照振动时间、暂停时间的循环执行振动

振动模式数组有一个用户代理定义的最大长度,传入超出此长度限制的数组会被截取至规定的长度

若传入参数前已有振动运行,会停止已有的振动并执行新的振动模式

若传入 0 或空数组或全 0 的数组,代表停止振动

需要注意的是,该方法要求在页面可见或存在用户交互的情况下调用,否则不具备效果

类型

1
2
3
4
5
interface Navigator {
vibrate(pattern: VibratePattern): boolean
}

type VibratePattern = number | number[]

链接

Get Installed Related Apps API

Get Installed Related Apps API 允许网页应用检测与之相关的应用是否已在本地设备下载

支持检测的应用包括通用 Window 应用 Android 应用或 PWA 应用

使用 API

调用 Navigator 接口上的 getInstalledRelatedApps() 方法以使用该 API

方法返回一个 Promise 的相关应用信息数组

id 项代表应用的 ID,具体格式受不同操作系统而有所不同

url 项代表与应用相关的 URL

version 项代表与应用相关的版本

platform 项代表应用的操作系统类型,可能是 chrome_web_store play chromeos_play webapp windows f-droid amazon 之一

方法抛出 InvalidStateError 错误,若未在顶层浏览器上下文中调用

1
2
3
4
5
6
7
8
const apps = await navigator.getInstalledRelatedApps()

for (const app of apps) {
console.log(app.id)
console.log(app.url)
console.log(app.version)
console.log(app.platform)
}

方法必须在顶层文档上下文中调用,且要求必须处于严格上下文环境中

背景要求

当前网页应用需要在 manifest 文件中指定 related_applications 字段

本地应用需要与网页应用存在某种形式的联系,如:

Android 应用通过 Digital Asset Links system 实现

Window 应用通过 URI Handlers 实现

PWA 应用通过其 manifest 文件中定义的 related_applications 字段或 /.well-known/assetlinks.json 文件定义

类型

1
2
3
4
5
6
7
8
9
10
interface Navigator {
getInstalledRelatedApps(): Promise<RelatedApplication[]>
}

interface RelatedApplication {
platform: string
url?: string
id?: string
version?: string
}

链接

Web Share API

Web Share API 允许分享文字、链接、文件或其他内容到用户指定的分享目标

分享操作

使用 Navigator 接口上的 share() 方法分享内容

方法允许传递一组可选的分享内容,包括 title 字段;text 字段;url 字段;files 字段

方法返回一个 Promise

方法可能抛出 InvalidStateError 异常,若当前文档未处于活跃状态;或当前存在其他分享操作

方法可能抛出 NotAllowedError 异常,若当前未被授予 web-share 权限;或分享操作未因用户交互行为调用;或分享的文件因为隐私问题被拒绝

方法可能抛出 TypeError 异常,若校验分享数据失败

title text url files 四个字段均为空

仅存在 files 字段且其为空数组

用户代理实现不支持分享文件

用户代理确信任一分享的文件存在恶意行为

存在 url 字段且解析 URL 失败

存在 url 字段且其协议不是可分享的协议类型,如 http https 等;或为不可分享的协议类型,如 file、ws、wss、javascript 或本地协议等

方法可能抛出 AbortError 异常,若用户代理无法获取到可用的分享目标;或用户退出选取分享目标过程

方法可能抛出 DataError 异常,若尝试启动分享目标失败;或传递分享数据失败

检测分享

使用 Navigator 接口上的 canShare() 方法检测内容能否被成功分享,传递的参数同 share() 方法,返回一个 boolean

通常在调用 share() 方法之前先行调用该方法以检测能否成功分享

若调用 share() 方法会成功,则 canShare() 方法一定返回 true;反之返回 false

权限策略

该 API 调用受到 web-share 权限策略的控制,可以通过 Permissions-Policy 响应头指定,或通过 <iframe> 标签的 allow 属性指定

默认为 self,即允许在当前上下文或内嵌的其他同源上下文中使用

类型

1
2
3
4
5
6
7
8
9
10
11
interface Navigator {
share(data?: ShareData): Promise<undefined>
canShare(data?: ShareData): boolean
}

interface ShareData {
files?: File[]
title?: string
text?: string
url?: string
}

链接

VirtualKeyboard API

VirtualKeyboard API 允许控制设备的虚拟键盘的几何信息和展示及隐藏(特别是针对平板、智能手机等无法提供机械键盘的设备)

通过 navigator.virtualKeyboard 暴露的 VirtualKeyboard 接口实例使用

虚拟键盘展示隐藏

VirtualKeyboard 接口的 show() 方法展示虚拟键盘

VirtualKeyboard 接口的 hide() 方法隐藏虚拟键盘

VirtualKeyboard 接口的 geometrychange 事件在虚拟键盘的可见性变化或浏览器窗口重定位时触发,返回一个 Event 事件,通常使用该事件来监听具体虚拟键盘的可见性的时机

1
2
3
4
5
6
7
navigator.virtualKeyboard.show()

navigator.virtualKeyboard.hide()

navigator.virtualKeyboard.addEventListener('geometrychange', (e) => {
//
})

需要在因为用户交互产生的行为中调用

需要当前聚焦元素的 virtualkeyboardpolicy 属性指定为 manualinputmode 指定为除 none 之外的其他值

其中 show() 方法额外需要当前聚焦的元素为表单元素或者当前聚焦元素需要指定 contenteditable 属性为 true

虚拟键盘几何位置信息

VirtualKeyboard 接口的 boundingRect 只读属性给出虚拟键盘的几何位置信息,返回一个 DOMRect,默认值均设置为 0

1
navigator.virtualKeyboard.boundingRect

同时 CSS 环境变量 keyboard-inset-top keyboard-inset-right keyboard-inset-bottom keyboard-inset-left keyboard-inset-width keyboard-inset-height 可以通过 env() CSS 函数使用

1
2
3
4
5
6
env(keyboard-inset-top)
env(keyboard-inset-right)
env(keyboard-inset-bottom)
env(keyboard-inset-left)
env(keyboard-inset-width)
env(keyboard-inset-height)

管理虚拟键盘几何位置

VirtualKeyboard 接口的 overlaysContent 属性用于指定虚拟键盘的几何位置策略,返回一个 boolean,默认 false

1
navigator.virtualKeyboard.overlaysContent

将该值设定为 true 以阻止浏览器默认的虚拟键盘调度策略,从而允许利用相关的 API 属性方法和 CSS 环境变量自定义地调整网页的布局

指定元素的虚拟键盘策略

全局 virtualkeyboardpolicy 属性用于指定特定元素的虚拟键盘策略,默认为空字符串

指定为空字符串或 auto 表示使用默认的虚拟键盘策略

指定为 manual 表示阻止使用默认的虚拟键盘策略

接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
interface ElementContentEditable {
virtualKeyboardPolicy: '' | 'auto' | 'manual'
}

interface VirtualKeyboard extends EventTarget {
show(): void
hide(): void
readonly boundingRect: DOMRect
overlaysContent: boolean
ongeometrychange: ((this: VirtualKeyboard, ev: Event) => any) | null
}

interface Navigator {
readonly virtualKeyboard: VirtualKeyboard
}

链接

Keyboard Map API

Keyboard Map API 允许获取键盘按键码至键盘按键名的映射

通过 navigator.keyboard 暴露的 Keyboard 接口实例使用

获取键盘映射

Keyboard 接口的 getLayoutMap() 方法提供了获取键盘映射的方法

方法返回一个 Promise 的 KeyboardLayoutMap 实例

1
2
3
4
navigator.keyboard.getLayoutMap().then((layoutMap) => {
const code = 'KeyW'
const key = layoutMap.get(code)
})

KeyboardLayoutMap 接口反映了一组键值对对象,键名为键盘按键码,键值为键盘按键名;它是一个只读的类 map 对象

键盘映射更改

Keyboard 接口的 layoutchange 事件在键盘映射改变时触发

该事件尚未得到主流浏览器的支持

权限策略

该 API 调用受到 keyboard-map 权限策略的控制,可以通过 Permissions-Policy 响应头指定,或通过 <iframe> 标签的 allow 属性指定

默认为 self,即允许在当前上下文或内嵌的其他同源上下文中使用

类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
interface Keyboard extends EventTarget {
lock(keyCodes?: string[]): Promise<void>
unlock(): void
}

interface Navigator {
readonly keyboard: Keyboard
}

interface KeyboardLayoutMap {
forEach(callbackfn: (value: string, key: string, map: Map<string, string>) => void, thisArg?: any): void
get(key: string): string | undefined
has(key: string): boolean
readonly size: number
entries(): IterableIterator<[string, string]>
keys(): IterableIterator<string>
values(): IterableIterator<string>
[Symbol.iterator](): IterableIterator<[string, string]>
}

链接

EyeDropper API

EyeDropper API 提供了吸管工具,允许用户选择屏幕上的某个特定位置的颜色

该 API 仅在严格上下文环境下允许使用

使用

EyeDropper() 构造函数用于创建一个 eyedropper 工具

调用 EyeDropper 接口的 open() 方法以选择颜色

方法接受一个可选的配置项,其唯一可选属性 signal 是一个 AbortSignal,可用于编程式退出选择过程

方法返回一个 Promise 的对象,其唯一属性 sRGBHex 代表一个相应的十六进制的颜色字符串

方法可能抛出 NotAllowedError,若方法不是因为用户交互触发的

方法可能抛出 InvalidStateError,若当前已存在其他打开的 EyeDropper

方法可能抛出 AbortError,若用户退出选择颜色或因调用 AbortSignal.abort() 方法退出

方法可能抛出 OperationError,若因为除用户主动退出之外的原因导致获取颜色信息失败

1
2
3
4
5
6
7
8
9
10
11
12
13
try {
const eyeDropper = new EyeDropper()

const controller = new AbortController()

const { sRGBHex } = await eyeDropper.open({
signal: controller.signal,
})

console.log(sRGBHex)
} catch (err) {
console.error(err)
}

示例

选择的颜色为:

类型

1
2
3
4
5
6
7
8
9
10
11
12
interface ColorSelectionResult {
sRGBHex: string
}

interface ColorSelectionOptions {
signal: AbortSignal
}

interface EyeDropper {
constructor()
open(options: ColorSelectionOptions): Promise<ColorSelectionResult>
}

链接

Network Information API

Network Information API 允许获取网络信息和监听网络信息更改,以及 Save Data API 提供了侦测用户流量使用倾向的方法

通过 navigator.connection 暴露 NetworkInformation 实例使用

获取网络信息

NetworkInformation 接口的 type 属性表示当前的网络连接的类型

NetworkInformation 接口的 effectiveType 属性表示当前的网络连接的状态

NetworkInformation 接口的 downlink 属性表示当前的 downlink 速度

NetworkInformation 接口的 downlinkMax 属性表示当前最大的 downlink 速度

NetworkInformation 接口的 rtt 属性表示当前的 RTT 参数

1
2
3
4
5
const type = navigator.connection.type
const effectiveType = navigator.connection.effectiveType
const downlink = navigator.connection.downlink
const downlinkMax = navigator.connection.downlinkMax
const rtt = navigator.connection.rtt

监听网络信息

NetworkInformation 接口的 change 事件在网络信息更新时触发

1
navigator.connection.addEventListener('change', () => { /* to do something */ })

类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
interface Navigator {
readonly connection: NetworkInformation
}

interface WorkerNavigator {
readonly connection: NetworkInformation
}

interface NetworkInformation extends EventTarget {
readonly type: ConnectionType
readonly effectiveType: EffectiveConnectionType
readonly downlinkMax: number
readonly downlink: number
readonly rtt: number
readonly saveData: boolean
onchange: ((this: NetworkInformation, ev: Event) => any) | null
}

interface NetworkInformationEventMap {
change: Event
}

type ConnectionType = 'bluetooth' | 'cellular' | 'ethernet' | 'none' | 'wifi' | 'wimax' | 'other' | 'unknown'

type EffectiveConnectionType = 'slow-2g' | '2g' | '3g' | '4g'

链接


:D 一言句子获取中...