跳到內容

每條游來游去的小魚,都是正在瀏覽這一頁的訪客,有一條是你自己 ( ´ ▽ ` )ノ 覺得干擾閱讀的話,可以把小魚關掉。

七巧板游標

cursor

隨著滑鼠型態變形的七巧板,讓游標變得超酷。ヽ(●`∀´●)ノ

名稱描述
Anime.js輕量級 JavaScript 動畫函式庫
Pointer 事件偵測滑鼠或觸控點移動、點擊、懸停等等事件,取得座標、目標等等資訊
JS 動畫基於 JavaScript 實現的動畫,達成更複雜、精準的動畫控制,常見套件有 GSAP、anime.js 等
SVG Morph讓 SVG 在不同形狀間平滑過渡的技術
Document elementFromPoint()取得指定座標位置最上層的元素
Window getComputedStyle()取得元素 CSS 屬性的解析值(resolved values)

隨著 cursor 型態持續變化。

none
pointer
text
wait
move
not-allowed
help
crosshair
zoom-in
zoom-out
grab
grabbing
vertical-text
cell
copy
alias
<template>
<div class="w-full flex flex-col gap-10 p-6">
<div class="example-ctrl flex flex-col gap-4">
<base-checkbox
v-model="visible"
:label="t('show')"
/>
</div>
<div class="grid grid-cols-2 w-full gap-10 md:grid-cols-3">
<div
v-for="item in list"
:key="item"
class="border px-8 py-4 text-center"
:style="{ cursor: item }"
>
<div class="text-sm opacity-60">
{{ item }}
</div>
</div>
</div>
<cursor-trangram
v-if="visible"
class="z-[9999]"
/>
</div>
</template>
<script setup lang="ts">
import type { CSSProperties } from 'vue'
import { ref } from 'vue'
import { useI18n } from 'vue-i18n'
import BaseCheckbox from '../../base-checkbox.vue'
import CursorTrangram from '../cursor-trangram.vue'
interface Props {
visible?: boolean;
}
const props = withDefaults(defineProps<Props>(), {
visible: true,
})
const visible = ref(props.visible)
const list: CSSProperties['cursor'][] = [
'none',
'pointer',
'text',
'wait',
'move',
'not-allowed',
'help',
'crosshair',
'zoom-in',
'zoom-out',
'grab',
'grabbing',
'vertical-text',
'cell',
'copy',
'alias',
]
const { t } = useI18n()
</script>

使用 useElementByPoint 取得目前觸碰的元素。

接著使用 getComputedStyle 取得目標的 CSS 屬性,再透過 cursor 屬性設定游標樣式。

最後就是 anime.js 與 svg 動畫的部分惹。(´,,•ω•,,)

type Cursor = NonNullable<CSSProperties['cursor']>
interface Props {
/** 7 個積木顏色 */
colors?: [string, string, string, string, string, string, string];
size?: string;
offsetX?: number | ((cursor: Cursor) => number);
offsetY?: number | ((cursor: Cursor) => number);
/** 可自定義位置。預設跟隨滑鼠 */
positionProvider?: () => { x: number; y: number };
}