Mouse Trail CTA

UserBigcatgj
原作者: motionsites
原文链接
2026/8/17
通用
CTA

提示词内容

Build a React + TypeScript + Tailwind CSS + Vite section called "Partner with us". It's a large rounded white card with a giant serif heading, a dark pill button containing a portrait avatar, and an interactive mouse-trail effect that drops fading, slightly rotated images wherever the user moves the cursor inside the card.

### Fonts (global, in `src/index.css` before `@tailwind` directives)

```css
@font-face {
  font-family: 'PP Neue Montreal';
  src: url('https://assets.website-files.com/6009ec8cda7f305645c9d91b/60176f9bb43e36419997ecfe_PPNeueMontreal-Book.otf') format('opentype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'PP Neue Montreal';
  src: url('https://assets.website-files.com/6009ec8cda7f305645c9d91b/60176f9b39c5673e51a86f5a_PPNeueMontreal-Medium.otf') format('opentype');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'PP Mondwest';
  src: url('/PPMondwest-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@tailwind base;
@tailwind components;
@tailwind utilities;

body {
  font-family: 'PP Neue Montreal', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

@keyframes fadeInUp {
  0%   { opacity: 0; transform: translateY(30px); }
  100% { opacity: 1; transform: translateY(0); }
}
.animate-fade-in-up {
  animation: fadeInUp 0.8s ease-out forwards;
  opacity: 0;
}
```

Place `PPMondwest-Regular.woff2` in `public/`. Also place a square portrait JPG in `public/` (e.g., `viktor.jpg`) to use as the avatar inside the CTA button.

### In-view hook (`src/hooks/useInViewAnimation.ts`)

`IntersectionObserver` with `threshold = 0.1`. Returns `{ ref, isInView }`. Sticky once true.

### Component (`src/components/PartnerSection.tsx`)

**Props**
- `images: string[]` — a list of image URLs used as the trail. Use the same GIF/animation URLs you have on the rest of the page (any 8+ rectangular assets).

**State / refs**
- `trailImages: TrailImage[]` where `TrailImage = { id: number; x: number; y: number; timestamp: number; src: string; rotation: number }`.
- `isHovered: boolean` (default false).
- `sectionRef` — ref on the inner rounded card (for bounding-rect math).
- `lastSpawnTime` — `useRef(0)` for spawn throttling.
- `imageIdCounter` — `useRef(0)` monotonically increasing id.
- `animationRef`, `isInView` from `useInViewAnimation()` placed on the outer `

`.

**Mouse trail behaviour**
- `onMouseEnter` sets `isHovered = true`; `onMouseLeave` sets it false.
- `onMouseMove`:
  - Bail if `!isHovered` or `!sectionRef.current`.
  - Throttle: ignore if `Date.now() - lastSpawnTime.current < 80` ms.
  - Compute `(x, y)` relative to the section's `getBoundingClientRect()` (subtract `rect.left`, `rect.top`).
  - Pick a random image from `images`. Compute `rotation = (Math.random() - 0.5) * 20` degrees.
  - Push a new `TrailImage` with a fresh id, `timestamp = Date.now()`.
- Cleanup loop: `setInterval` every 50 ms removes any trail entry whose age `> 1000` ms.

**Per-image fade math** (applied as inline style on the trail wrapper):
- `age = now - img.timestamp`, `progress = min(age / 1000, 1)`.
- `opacity = 1 - progress`.
- `scale = 1 - progress * 0.15`.
- Position: `left = img.x - 50`, `top = img.y - 50`.
- Transform: `scale(${scale}) rotate(${img.rotation}deg)`.

**Markup**

Outer wrapper:
```html



```
Inner rounded card (this is the trail surface — attach `sectionRef`, `onMouseMove`, `onMouseEnter`, `onMouseLeave` here):
```
w-full max-w-7xl mx-auto py-48 bg-white relative overflow-hidden
shadow-[0_0_0_0.5px_rgba(0,0,0,0.05),0_4px_30px_rgba(0,0,0,0.08)]
rounded-[40px]
```

Inside the card, a centered content block above the trail:
```html



```

Heading:
```
text-[48px] md:text-[64px] lg:text-[80px] leading-[1.1]
text-[#0D212C] tracking-tight font-normal mb-12
```
- Inline style `fontFamily: "'PP Mondwest', serif"`.
- Text: `Partner with us`.
- Animation: when `isInView`, class `animate-fade-in-up`; else `opacity-0`. Inline `animationDelay: isInView ? '0.1s' : '0s'`.

CTA button (centered with `mx-auto`):
```
bg-[#051A24] text-white px-6 py-3.5 rounded-full
flex items-center gap-3
shadow-[0_1px_2px_0_rgba(5,26,36,0.1),0_4px_4px_0_rgba(5,26,36,0.09),0_9px_6px_0_rgba(5,26,36,0.05),0_17px_7px_0_rgba(5,26,36,0.01),0_26px_7px_0_rgba(5,26,36,0),inset_0_2px_8px_0_rgba(255,255,255,0.5)]
hover:bg-[#0D212C] transition-colors duration-200
```
- Animation: `animate-fade-in-up` (or `opacity-0`) with `animationDelay: '0.2s'`.
- Contents:
  1. `` of the portrait: `w-10 h-10 rounded-full object-cover`, `src` = portrait JPG path, `alt="Viktor Oddy"`.
  2. `Start chat with Viktor`.

After the centered content block, render the trail images list (still inside the card, not behind `z-10`):
```jsx
{trailImages.map((img) => (
  


    


))}
```

### Colors used
- Dark text / button bg: `#051A24` (button), `#0D212C` (heading and button hover).
- Card surface: `white`.
- Card shadow: `0 0 0 0.5px rgba(0,0,0,0.05), 0 4px 30px rgba(0,0,0,0.08)`.
- Button shadow (layered + inset highlight): as listed above.

### Behaviour summary
- Section fades in on scroll via `IntersectionObserver` (heading delay 0.1s, button delay 0.2s).
- Hovering the rounded card drops a randomized, rotated thumbnail every ~80 ms at the cursor; each thumbnail fades out and shrinks slightly over 1 second, then is removed.
- Trail thumbnails are 96 px wide (`w-24`), centered on the cursor (offset by 50 px), absolutely positioned, `pointer-events-none`, with `rounded-xl` and a soft `shadow-lg`.

### Required dependencies
`react`, `react-dom`, plus Vite + Tailwind toolchain. No `lucide-react` needed for this section.

---

暂无效果展示

作者尚未提供生成效果案例;新的公开提示词需要至少添加一个案例。

想要不同效果?只改几处即可

AI 自动找出可替换的部分(主体/风格/场景),填入想要的值,其余保持不变

提示词广场登录