Skip to content

借隻貓手 cursor

貓手幫你點擊!(=①ω①=)

這個元件的靈感來自日文諺語「 猫の手も借りたい」,意思是「忙到連貓的手都想借來用」

不同於諺語的部分是這個元件真的有貓手!ԅ(´∀` ԅ)

TIP

此元件針對滑鼠設計,建議使用電腦或可以使用滑鼠的裝置瀏覽。

技術關鍵字

名稱 描述
JS 動畫基於 JavaScript 實現的動畫,達成更複雜、精準的動畫控制,常見套件有 GSAP、anime.js 等
向量計算處理方向、加速度、速度等等數學運算
Anime.js輕量級 JavaScript 動畫函式庫
Pointer 事件偵測滑鼠或觸控點移動、點擊、懸停等等事件,取得座標、目標等等資訊
Document activeElement取得目前擁有焦點的元素
Document elementsFromPoint()取得指定座標位置的所有元素

使用範例

基本用法

貓手跟隨滑鼠與元素互動產生變化

POINTER
NOT_ALLOWED
查看範例原始碼
vue
<template>
  <div class="w-full flex flex-col gap-4 rounded-xl py-10">
    <div class="flex flex-col select-none items-center justify-center gap-[6vh]">
      <base-checkbox
        v-model="visible"
        label="顯示游標"
        class="cursor-pointer border border-l-4 p-4"
      />

      <div class="card bg-pointer cursor-pointer p-4">
        POINTER
      </div>

      <div class="card bg-not-allowed cursor-not-allowed p-4">
        NOT_ALLOWED
      </div>
    </div>

    <cursor-lend-a-paw
      v-if="visible"
      z-index="9999"
    />
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import BaseCheckbox from '../../base-checkbox.vue'
import CursorLendAPaw from '../cursor-lend-a-paw.vue'

interface Props {
  visible?: boolean;
}

const props = withDefaults(defineProps<Props>(), {
  visible: true,
})

const visible = ref(props.visible)
</script>

<style lang="sass" scoped>
.card
  font-weight: 700
  transition-duration: 0.3s
.bg-pointer
  color: light-dark(#111, #FFF)
  background-color: light-dark(#FFF, #222)
  $bg-color: light-dark(#EEE, #555)
  background-image: linear-gradient(45deg, $bg-color 25%, transparent 25%, transparent 75%, $bg-color 75%, $bg-color), linear-gradient(45deg, $bg-color 25%, transparent 25%, transparent 75%, $bg-color 75%, $bg-color)
  background-size: 10px 10px
  background-position: 0 0, 5px 5px
.bg-not-allowed
  color: light-dark(#7f1d1d, #e83a3a)
  background: repeating-linear-gradient(135deg, light-dark(#ffadad, #6b2828) 0 10px, light-dark(#FFF, #222) 10px 20px)
</style>

原理

使用 Zdog 繪製貓手,並透過 JS 動畫模擬貓手的動作

後記

原本苦惱要怎麼繪製貓手,3D 找不到合適的模型,自己畫好麻煩;SVG 不能模擬 3D 動作;DOM 形狀太死板,複雜度又高。

一直找不到理想中適合的繪製方式,導致元件就這樣擱置了好久。( ˘・з・)

直到意外發現 Zdog 這個超酷的套件,這個元件終於順利問世了。✧⁑。٩(ˊᗜˋ*)و✧⁕。

2025/07/16

感謝社群大大的建議(Ian Ng、天地毛毛、JimYe),追加點擊後留下掌印的效果,可愛度翻倍 (*´∀`)~♥

2025/07/17

感謝 kevindawnsu 大大的建議,將滑鼠變成雷射光點,真是畫龍點睛 (ゝ∀・)b

貓掌印淡出

點擊後留下貓掌印不難,和繪製貓手的邏輯類似,但是實作淡出的時候遇到一個問題。

Zdog 的繪圖不支援直接修改透明度,這下怎麼辦呢?(。-`ω´-)

賣個關子,好奇的朋友們可以看看原始碼,猜猜看如何實作。ヽ(●`∀´●)ノ

游標改成雷射光點

本來想說隱藏游標應該不難,CSS 來個 cursor: none 就好啦。

沒意外的話,果然要出意外了 (´;ω;`)

如果直接在 body 設定 cursor: none,就會導致所有子元素的 cursor 都是 none,這樣就沒辦法根據 hover 的 DOM 判斷目前的動作了。( ´•̥̥̥ ω •̥̥̥` )

最後使用了 datasetIntersectionObservercursor 隱藏圖片 組合技,才完成一個效果與性能兼具的方案。

概念為:

  1. body 設定 cursor: url('透明圖片'), auto,在 cursor value 為 auto 或 default 時隱藏游標。
  2. 使用 document.querySelectorAll 取得所有需要處理 cursor 樣式的元素。
  3. 取得可見元素 cursor value 儲存至 dataset 中,其他不可見元素則註冊至 IntersectionObserver

當然還有回復樣式的部分,這裡就不贅述了。

大家有興趣的話,可以來原始碼看看具體實作。( ´ ▽ ` )ノ

原始碼

API

Props

interface Props {
  /** [x, y]。@default [60, 30] */
  offset?: [number, number];
  /** @default 40 */
  size?: number;
  /** @default '#444' */
  furColor?: string;
  /** @default '#FFA5A5' */
  padColor?: string;
  /** @default '#DDD' */
  padPrintColor?: string;
  /** ms。@default 5000 */
  maxPrintLifeTime?: number;
  /** @default '#F00' */
  laserColor?: string;
  zIndex?: string | number;
}

v0.47.1