eyes-follow-pointer
Version:
Canvas eyes that smoothly follow the pointer with blinking, eyelid shadow and eyelashes. Works in any container.
155 lines (123 loc) • 4.37 kB
Markdown
# eyes-follow-pointer
Canvas 眼睛组件:在任意容器中渲染两只会“看着”指针移动的眼睛,带平滑缓动、空闲巡航、同步眨眼、眼皮阴影和睫毛效果。支持浏览器直接引入和 npm 包管理。
## 安装
```bash
npm i eyes-follow-pointer
# 或
pnpm add eyes-follow-pointer
# 或
yarn add eyes-follow-pointer
```
## 快速开始(浏览器 UMD)
```html
<div id="box" style="width:400px;height:240px;position:relative"></div>
<script src="https://unpkg.com/eyes-follow-pointer@1"></script>
<script>
const inst = Eyes.create('#box', { ease: 0.14 });
// 销毁
// inst.destroy();
</script>
```
## 在 React 中使用
要点:容器要有尺寸;在 effect 中创建并销毁实例。
```tsx
import { useEffect, useRef } from 'react';
import Eyes from 'eyes-follow-pointer';
export default function EyesBox() {
const boxRef = useRef<HTMLDivElement>(null);
useEffect(() => {
if (!boxRef.current) return;
const inst = Eyes.create(boxRef.current, {
ease: 0.14,
blinkMinInterval: 2000,
blinkMaxInterval: 5000,
blinkDuration: 160,
eyelashCount: 7,
eyelashLengthRatio: 0.5,
eyelidShadowAlpha: 0.4,
});
return () => inst.destroy();
}, []);
return (
<div
ref={boxRef}
style={{ width: 400, height: 240, position: 'relative', background: '#0f172a' }}
/>
);
}
```
- Next.js/SSR 注意:仅在客户端创建
```ts
useEffect(() => {
if (typeof window === 'undefined' || !boxRef.current) return;
const Eyes = require('eyes-follow-pointer').default;
const inst = Eyes.create(boxRef.current, {});
return () => inst.destroy();
}, []);
```
## 在 Vue 3 中使用
要点:在 `onMounted` 创建,在 `onBeforeUnmount` 销毁;容器需有尺寸。
```vue
<script setup lang="ts">
import { ref, onMounted, onBeforeUnmount } from 'vue';
import Eyes from 'eyes-follow-pointer';
const boxRef = ref<HTMLElement | null>(null);
let inst: ReturnType<typeof Eyes.create> | null = null;
onMounted(() => {
if (!boxRef.value) return;
inst = Eyes.create(boxRef.value, {
ease: 0.14,
blinkMinInterval: 2000,
blinkMaxInterval: 5000,
blinkDuration: 160,
eyelashCount: 7,
eyelashLengthRatio: 0.5,
eyelidShadowAlpha: 0.4,
});
});
onBeforeUnmount(() => {
inst?.destroy();
});
</script>
<template>
<div
ref="boxRef"
style="width: 400px; height: 240px; position: relative; background: #0f172a;"
/>
</template>
```
## 通过 UMD(CDN)在框架中使用
如果不走打包器,在 React/Vue 的挂载生命周期里也可以通过全局 `window.Eyes` 使用:
```html
<script src="https://unpkg.com/eyes-follow-pointer@1"></script>
<script>
// 在组件挂载后:
const inst = window.Eyes.create(containerElement, { ease: 0.14 });
// 组件卸载时:
inst.destroy();
</script>
```
## API
- Eyes.create(target, options?) => { canvas, destroy() }
- target: 选择器字符串、HTMLElement 或 HTMLCanvasElement
- 返回:
- canvas: HTMLCanvasElement 实例
- destroy(): 清理监听与动画并移除内部创建的 canvas(若传入的是已有 canvas 则不会移除)
### Options
- ease: number(默认 0.12)瞳孔跟随的缓动系数
- idleAfterMs: number(默认 1500)无交互多少毫秒后进入 idle 巡航
- idleRadiusRatio: number(默认 0.05)idle 巡航半径占容器短边比例
- maxDpr: number(默认 2)最高像素比上限(防止过高 DPR 影响性能)
- gapRatio: number(默认 1.6)两眼中心间距 = gapRatio × eyeRadius
- blinkMinInterval: number(默认 2500)两次眨眼最短间隔(毫秒)
- blinkMaxInterval: number(默认 6000)两次眨眼最长间隔(毫秒)
- blinkDuration: number(默认 180)一次眨眼时长(毫秒)
- eyelidShadowAlpha: number 0-1(默认 0.35)眼皮阴影基准强度
- eyelashCount: number(默认 6)上沿睫毛数量
- eyelashLengthRatio: number(默认 0.45)睫毛长度相对 eyeRadius 比例
## 常见问题
- 容器没有尺寸?请给父元素一个明确的 `width` 和 `height`,建议 `position: relative`。
- 想控制颜色/尺寸?可直接修改源码中颜色常量、或在后续版本开放更多外观参数。
- 想在 `<canvas>` 上使用?直接把 `canvas` 传入:`Eyes.create(canvasEl, options)`。
## 许可
MIT