跳转到内容

EyeDropper API:拾取屏幕上任意像素的颜色

发布于

一句话: 根据 Chrome for Developers 的说明,“EyeDropper API 让开发者可以在自定义取色器中 使用浏览器自带的取色工具”,从而在不自行实现取色逻辑的情况下,拾取屏幕上任意像素(包括浏览器 窗口以外的像素)的颜色。

根据 Chrome for Developers 的说明,open() “只能在响应用户操作(例如按钮点击)时调用”, 因此这次调用应放在点击处理函数内部——把它粘贴到脚本顶层并不会启动取色器:

const pickButton = document.createElement("button");
pickButton.textContent = "Pick color";
const colorInput = document.createElement("input");
colorInput.type = "color";
document.body.append(pickButton, colorInput);
pickButton.addEventListener("click", async () => {
const eyeDropper = new EyeDropper();
try {
const result = await eyeDropper.open();
colorInput.value = result.sRGBHex; // 例如 "#3366ff"
} catch (err) {
// 如果用户取消取色(例如按下 Escape),Promise 会 reject。
console.log("取色已取消:", err);
}
});

根据 Chrome for Developers,open() 方法“返回一个 Promise,在用户选取屏幕上的某个像素后 resolve”,其 resolve 的值提供“以 sRGBHex 格式(#RRGGBB)访问该像素颜色”的能力。当用户 取消而不是选取像素时,这个 Promise 会 reject;示例使用 try/catch 处理该 rejection。

Chrome for Developers 明确指出了激活要求:“该 API 不会在没有用户意图的情况下启动取色模式。 open() 方法只能在响应用户操作(例如按钮点击)时调用。” 在点击等用户手势处理函数之外调用 open() 不会启动取色器。

除了用户按下 Escape,open() 还接受一个 AbortSignal,可用于以编程方式取消正在进行的 取色:

const controller = new AbortController();
eyeDropper.open({ signal: controller.signal }).catch(() => {
// 如果用户取消(例如按下 Escape)或信号被中止,Promise 会 reject。
});
// 在其他地方,例如某个"取消"按钮上:
controller.abort();

在未实现该 API 的每个浏览器(Firefox、Safari)中,"EyeDropper" in window 都为 false。下面的回退分支会真正展示 <input type="color"> 色块来代替取色按钮,而不只是 注释说明应该这样做:

function initColorPicker(pickButton, colorInput) {
if (!("EyeDropper" in window)) {
// 此处不支持原生取色器——隐藏取色按钮,改用始终存在的
// <input type="color"> 色块让用户选取颜色。
pickButton.hidden = true;
colorInput.hidden = false;
return;
}
pickButton.hidden = false;
pickButton.addEventListener("click", async () => {
const eyeDropper = new EyeDropper();
try {
const { sRGBHex } = await eyeDropper.open();
colorInput.value = sRGBHex;
} catch (err) {
// 如果用户取消取色(例如按下 Escape),Promise 会 reject。
console.log("取色已取消:", err);
}
});
}
const pickButton = document.createElement("button");
pickButton.textContent = "Pick color";
const colorInput = document.createElement("input");
colorInput.type = "color";
colorInput.hidden = true;
document.body.append(pickButton, colorInput);
initColorPicker(pickButton, colorInput);

根据 MDN,EyeDropper API “不属于 Baseline,因为它在一些广泛使用的浏览器中尚不可用”。根据 Chrome for Developers,该 API “自版本 95 起在 Chromium 内核浏览器(如 Edge 或 Chrome)中受支持”; 根据 caniuse 对该特性的跟踪记录,其支持范围还延伸到了 Opera。Chrome for Developers 自己的演示 教程在“Windows 或 Mac”上运行,这与 Chromium 实现中该 API 仅限桌面端的情况相符。Firefox 与 Safari 均未实现 EyeDropper API。

  • 在构造 EyeDropper 之前先做 "EyeDropper" in window 特性检测——根据 MDN 与 Chrome for Developers,支持范围仅限于 Chromium 桌面浏览器(Chrome/Edge 95+)。
  • 只在用户手势处理函数内部(例如点击监听器)调用 open()——根据 Chrome for Developers, 它“只能在响应用户操作时调用”。
  • 处理 open() 被拒绝的 Promise——如果用户取消取色(例如按下 Escape)而不是选取像素, Promise 会 reject。
  • 如果界面需要以编程方式取消正在进行的取色(例如取色器所在的对话框被关闭),请传入 AbortSignal。
  • 为不支持 EyeDropper 的浏览器提供回退颜色输入(例如 <input type="color">),因为 Firefox 与 Safari 均未实现该 API。