DannyDevs logopart of logo

lab007: vueUse's useEyeDropper and the slick EyeDropper web API

July 31, 2022


The Eyedropper API is not supported by your browser

The vueUse useEyeDropper utility provides additional features around the amazing (but still experimental) EyeDropper web API. As of now the API is compatible with Chrome, Edge, and Opera, but no other browsers. Hopefully that will change soon.

Here is demo code that I analyzed to make this lab’s introductory demo:

<script setup>
import { useEyeDropper } from '@vueuse/core'
const { isSupported, open, sRGBHex } = useEyeDropper()
</script>

<template>
  <template v-if="isSupported">
    <div>isSupported: {{ isSupported }}</div>
    <div>sRGBHex: <span :style="{ color: sRGBHex }">{{ sRGBHex }}</span></div>
    <button
      :disabled="!isSupported"
      @click="() => open()"
    >
      Open Eye Dropper
    </button>
  </template>
  <div v-else>
    <span>Not Supported by Your Browser</span>
  </div>
</template>
<script setup>
import { useEyeDropper } from '@vueuse/core'
const { isSupported, open, sRGBHex } = useEyeDropper()
</script>

<template>
  <template v-if="isSupported">
    <div>isSupported: {{ isSupported }}</div>
    <div>sRGBHex: <span :style="{ color: sRGBHex }">{{ sRGBHex }}</span></div>
    <button
      :disabled="!isSupported"
      @click="() => open()"
    >
      Open Eye Dropper
    </button>
  </template>
  <div v-else>
    <span>Not Supported by Your Browser</span>
  </div>
</template>

The useEyeDropper function spits out:

  • a Boolean, isSupported, which checks if your browser supports the experimental EyeDropper API. We use it to conditionally render the page: either it works, or tells the user the API is not supported.

  • an open function, which is an async function that awaits the actual window.EyeDropper.open function, which magnifies the pixels under the user’s mouse pointer and returns the selected pixel’s color, which is then handed off to Vue.

  • sRGBHex is a string that describes colors using the sRGB hex triplet format. It stores the last color that the user selected.

The useEyeDropper function is given below. It is a terse piece of code! useSupported is imported to bring more refined checking whether the API is supported or now; it works for both regular .js composables and also for .vue files, which have a lifecycle and require that the check be initiated after the component is mounted into the DOM.

import { ref } from 'vue-demi'
import { useSupported } from '../useSupported'

export function useEyeDropper(options = {}) {
  const { initialValue = '' } = options
  const isSupported = useSupported(() => typeof window !== 'undefined' && 'EyeDropper' in window)
  const sRGBHex = ref(initialValue)

  async function open(openOptions?: EyeDropperOpenOptions) {
    if (!isSupported.value)
      return
    const eyeDropper: EyeDropper = new (window as any).EyeDropper()
    const result = await eyeDropper.open(openOptions)
    sRGBHex.value = result.sRGBHex
    return result
  }

  return { isSupported, sRGBHex, open }
}
import { ref } from 'vue-demi'
import { useSupported } from '../useSupported'

export function useEyeDropper(options = {}) {
  const { initialValue = '' } = options
  const isSupported = useSupported(() => typeof window !== 'undefined' && 'EyeDropper' in window)
  const sRGBHex = ref(initialValue)

  async function open(openOptions?: EyeDropperOpenOptions) {
    if (!isSupported.value)
      return
    const eyeDropper: EyeDropper = new (window as any).EyeDropper()
    const result = await eyeDropper.open(openOptions)
    sRGBHex.value = result.sRGBHex
    return result
  }

  return { isSupported, sRGBHex, open }
}

Another interesting thing to note is that Anthony has imported ref from vue-demi, which is an ingenious package that allows for authors to easily write npm libraries for Vue that are universal (working in both Vue 2 and Vue 3).

Next Steps

I can think of a few project ideas involving useEyeDropper, such as a palette creator (save colors while you surf the web! Organize them into collections! Drag them around to reorganize them.).

I can also see it being super useful as a web design tool, which means it might be ideal to leverage it in a Chrome extension. I’m going to research this right now to see if it’s feasible as a shorter-term project. I checked for eyedroppers in the Chrome store a while back and found the offerings to be disappointing, so let’s check again to see if there’s a market for it! DannyDevs out!

Home

Lab

Blog

About

Links