|
1 | 1 | import React from 'react' |
2 | | -import clsx from 'clsx' |
| 2 | +import { motion } from 'framer-motion' |
3 | 3 |
|
4 | | -import styles from './index.module.less' |
| 4 | +const Meteors = ({ starCount = 50, primaryColor = '#ffffff', className = '' }) => { |
| 5 | + const stars = Array.from({ length: starCount }, (_, i) => { |
| 6 | + const starTailLength = Math.random() * 2.5 + 5 |
| 7 | + const topOffset = Math.random() * 100 |
| 8 | + const fallDuration = Math.random() * 6 + 6 |
| 9 | + const fallDelay = Math.random() * 10 |
| 10 | + |
| 11 | + return { |
| 12 | + id: i, |
| 13 | + topOffset, |
| 14 | + fallDuration, |
| 15 | + fallDelay, |
| 16 | + } |
| 17 | + }) |
5 | 18 |
|
6 | | -const Meteors = ({ number, className }) => { |
7 | | - const meteors = new Array(number || 20).fill(true) |
8 | 19 | return ( |
9 | | - <> |
10 | | - {meteors.map((el, idx) => ( |
11 | | - <span |
12 | | - key={'meteor' + idx} |
13 | | - className={clsx( |
14 | | - `${styles['animate-meteor-effect']} absolute top-1/2 left-1/2 h-0.5 w-0.5 rotate-[215deg] rounded-[9999px] bg-slate-500 shadow-[0_0_0_1px_#ffffff10]`, |
15 | | - "before:absolute before:top-1/2 before:h-[1px] before:w-[50px] before:-translate-y-[50%] before:transform before:bg-linear-to-r before:from-[#64748b] before:to-transparent before:content-['']", |
16 | | - className |
17 | | - )} |
| 20 | + <div |
| 21 | + className={`pointer-events-none absolute inset-0 h-full w-full -rotate-45 ${className}`} |
| 22 | + style={{ |
| 23 | + perspective: '1000px', |
| 24 | + transformStyle: 'preserve-3d', |
| 25 | + }} |
| 26 | + > |
| 27 | + {stars.map((star) => ( |
| 28 | + <motion.div |
| 29 | + key={star.id} |
| 30 | + className={`absolute h-[2px] rounded-full bg-gradient-to-r from-current to-transparent drop-shadow-[0_0_6px_currentColor]`} |
18 | 31 | style={{ |
19 | | - top: 0, |
20 | | - left: Math.floor(Math.random() * (400 - -400) + -400) + 'px', |
21 | | - animationDelay: Math.random() * (0.8 - 0.2) + 0.2 + 's', |
22 | | - animationDuration: Math.floor(Math.random() * (10 - 2) + 2) + 's', |
| 32 | + top: `${star.topOffset}vh`, |
| 33 | + width: '6em', |
| 34 | + color: primaryColor, |
| 35 | + willChange: 'transform', |
| 36 | + }} |
| 37 | + initial={{ x: '104em' }} |
| 38 | + animate={{ x: '-30em' }} |
| 39 | + transition={{ |
| 40 | + duration: star.fallDuration, |
| 41 | + delay: star.fallDelay, |
| 42 | + repeat: Infinity, |
| 43 | + ease: 'linear', |
| 44 | + repeatType: 'loop', |
23 | 45 | }} |
24 | | - ></span> |
| 46 | + > |
| 47 | + <div className="relative h-full w-full"> |
| 48 | + <div |
| 49 | + className={`rounded-inherit animate-blink absolute top-0 left-[calc(-1em)] h-full w-[1em] bg-gradient-to-r from-transparent via-current to-transparent`} |
| 50 | + style={{ |
| 51 | + willChange: 'transform, opacity', |
| 52 | + }} |
| 53 | + /> |
| 54 | + <div |
| 55 | + className={`rounded-inherit animate-blink absolute top-0 left-[calc(-1em)] h-full w-[1em] rotate-45 bg-gradient-to-r from-transparent via-current to-transparent`} |
| 56 | + style={{ |
| 57 | + willChange: 'transform, opacity', |
| 58 | + }} |
| 59 | + /> |
| 60 | + <div |
| 61 | + className={`rounded-inherit animate-blink absolute top-0 left-[calc(-1em)] h-full w-[1em] -rotate-45 bg-gradient-to-r from-transparent via-current to-transparent`} |
| 62 | + style={{ |
| 63 | + willChange: 'transform, opacity', |
| 64 | + }} |
| 65 | + /> |
| 66 | + </div> |
| 67 | + </motion.div> |
25 | 68 | ))} |
26 | | - </> |
| 69 | + </div> |
27 | 70 | ) |
28 | 71 | } |
29 | 72 |
|
|
0 commit comments