# EyeDropper API - 启用浏览器吸管工具获取屏幕任意目标元素HEX色值

> Photoshop、Illustrator等一些图形、图像设计软件都有一个吸管工具，作用就是拾取元素中某一位置的颜色，填充待作业的元素。Web开发中 HTML Input Color type 属性也可以做到类似效果，它类似Photoshop中前景色与背景色填色效果；那Web端有没有类似吸管工具的效果？

Author: DeathGhost
Published: 2021-11-15 22:17:27
Category: javascript
Canonical: https://www.deathghost.cn/article/javascript/105
Keywords: EyeDropper, 拾色器, 取色器, 吸管工具, 滴管, 取色工具, 吸色, 取色, new EyeDropper(), eyeDropper.open()

Web前端设计与开发过程中偶尔需要获取页面某一元素颜色值或浏览器窗口外桌面素材颜色值；我个人往往会通过QQ快捷键（CTRL+ALT+A）截取查看，或浏览器安装小工具进行吸取某一区域的颜色值而获取，又或者抓取截图在已打开的Photoshop画布中通过吸管工具获取。

很别扭，也很麻烦，要么得复制，要么得记住它的值，要么得借助其他软件。

吸管工具常见于设计软件，如：Photoshop、Illustrator等一些图形图像设计软件；需要获取某一元素颜色值对新建元素填充时使用。

前端开发者都知道HTML有一元素input，当类型为color时，会给用户提供一个颜色选择器，根据色彩面板进行颜色值选择或其自身吸管（拾色器）工具获取颜色值，然后通过JavaScript将其获取进行其他操作。

那有没有可以直接通过点击事件调用吸管工具获取（吸取）颜色值，且可获取桌面任意元素，不仅仅是当前工作区（页面）？

有！- EyeDropper API。

![EyeDropper](https://static.deathghost.cn/post/2021/11/16/1637071434962520.jpg)

EyeDropper API - 启用浏览器吸管工具获取屏幕任意目标元素HEX色值

截至目前，还是一个实验性功能，但是新版Chrome与Edge可使用。

使用前首先检测浏览器是否支持 EyeDropper API

if ('EyeDropper' in window) {
  console.log('支持！');
} else {
  console.log('当前浏览器不支持！');
}

## EyeDropper API 使用方法

使用 EyeDropper API 前，请先创建一个EyeDropper对象，然后调用其open()方法。

const eyeDropper = new EyeDropper();
open() 方法返回的是Promise对象，同时存在潜在隐私安全问题，所以需要用户触发方可执行。

async function openEyeDropper() {
  const res = await eyeDropper.open().catch(error => {
    console.error('吸管已被取消！');
  });
  return res;
}
当点击按钮时，鼠标会由普通光标稍许延迟变成一个圆形网格放大镜样式供用户选取目标元素像素点色彩值，同时也可以按ESC键终止（取消）吸管。

如：点击按钮选择目标元素色彩点，点击即可获取：{sRGBHex: '#000000'}。

## EyeDropper 示例

创建一个网格页面，第一个格子背景色通过两次点击其他格子颜色将其替换。

    See the Pen [EyeDropper API - Web 拾色器](https://codepen.io/deathghost/pen/xxLQwGO) by 孙志锋 ([@deathghost](https://codepen.io/deathghost))
    on [CodePen](https://codepen.io).

从示例中，可以看出，其他单元格颜色按颜色名称定义，通过吸管工具获取后，颜色值为十六进制（HEX）色码。

## EyeDropper 示例代码

html,body{
    margin: 0;
}
.grid{
    display: grid;
    grid-template-columns: 25vw 25vw 25vw 25vw ;
    grid-template-rows: 25vh 25vh 25vh 25vh;
}
.grid .item:first-of-type{
    background-color: #ef342a;
    cursor: pointer;
    color: black;
    text-shadow: 0 0 0.2em rgb(23, 252, 61), 0 0 0.2em rgb(36, 223, 19),0 0 0.2em rgb(0, 255, 85);
    grid-column: 1 / 3;
    grid-row: 1 / 3;
}
.grid .item:first-of-type::after{
    content: "";
}
.grid .item{
    position: relative;
    cursor: crosshair;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: column;
    border: 1px #f5f5f5 solid;
    font-size: 12px;
    z-index: 0;
}
.grid .item::after{
    position: absolute;
    left: 0;
    top: 0;
    color: rgba(0,0,0,.05);
    content: "DeathGhost.cn";
    transform: scale(2) rotate(45deg);
    z-index: 1;
}
<section>
    <div class="grid">
        <div class="item" id="active">
            <h1>EyeDropper</h1>
            <p>点击颜色模块开启拾色器（吸管）模式获取当前光标位置颜色</p>
            <p>
                你当前所选的是：
                <mark id="name">颜色名</mark>
                <mark id="hex" style="text-decoration: underline;">HEX</mark>
            </p>
        </div>
        <div class="item" onclick="getColor(this)" style="background: Orange;">Orange</div>
        <div class="item" onclick="getColor(this)" style="background: BlueViolet;">BlueViolet</div>
        <div class="item" onclick="getColor(this)" style="background: Chartreuse;">Chartreuse</div>
        <div class="item" onclick="getColor(this)" style="background: DeepPink;">DeepPink</div>
        <div class="item" onclick="getColor(this)" style="background: ForestGreen;">ForestGreen</div>
        <div class="item" onclick="getColor(this)" style="background: GreenYellow;">GreenYellow</div>
        <div class="item" onclick="getColor(this)" style="background: Indigo;">Indigo</div>
        <div class="item" onclick="getColor(this)" style="background: LawnGreen;">LawnGreen</div>
        <div class="item" onclick="getColor(this)" style="background: Maroon;">Maroon</div>
        <div class="item" onclick="getColor(this)" style="background: olive;">olive</div>
        <div class="item" onclick="getColor(this)" style="background: OrangeRed;">OrangeRed</div>
        <div class="item" onclick="getColor(this)" style="background: WhiteSmoke;">
            <p>WhiteSmoke</p>
            <p>或将光标移出工作区（桌面或其他应用程序）👉</p>
        </div>
    </div>
</section>
const active = document.querySelector('#active');
let colorName = document.querySelector('#name');
let colorHex = document.querySelector('#hex');
async function getColor(e) {
    if (!window.EyeDropper) {
        alert('浏览器不支持 EyeDropper！');
        return false;
    }
    const eyeDropper = new EyeDropper();
    const res = await eyeDropper.open().catch(error => console.warn('已取消！'));
    if (res) {
        // HEX
        active.style.background = res.sRGBHex;
        colorName.textContent = e.style.background;
        colorHex.textContent = res.sRGBHex;
    }
}

## 使用 EyeDropper API 注意事项

- 目前仅支持新版Chrome与Microsoft Edge浏览器。

- 每次获取使用吸管工具都会重新启动打开，然后关闭。

最后想说的是，这个功能的确不错，但还有不足；暂时也不适合生产环境，初步了解，以待使用。

## Related

- Previous: [at 相对索引方法 - 查找元素](https://www.deathghost.cn/article/javascript/104)
- Next: [告别低精度累加：JavaScript Math.sumPrecise() 完全解析](https://www.deathghost.cn/article/javascript/128)
