mirror of
https://github.com/NoFxAiOS/nofx.git
synced 2026-07-16 01:06:59 +08:00
feat(web): Typewriter 优化(修复 undefined、矩阵绿样式、降低速度)并更新启动指令为 README 前端开发流程
This commit is contained in:
@@ -381,24 +381,6 @@ export function LandingPage() {
|
|||||||
/>
|
/>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
|
|
||||||
<FloatingCard
|
|
||||||
delay={0.7}
|
|
||||||
position={{ bottom: '-6', left: '-6' }}
|
|
||||||
color='yellow'
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className='text-2xl font-bold'
|
|
||||||
style={{ color: 'var(--brand-yellow)' }}
|
|
||||||
>
|
|
||||||
24/7
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className='text-xs'
|
|
||||||
style={{ color: 'var(--text-secondary)' }}
|
|
||||||
>
|
|
||||||
自动交易
|
|
||||||
</div>
|
|
||||||
</FloatingCard>
|
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -519,15 +501,16 @@ export function LandingPage() {
|
|||||||
<Typewriter
|
<Typewriter
|
||||||
lines={[
|
lines={[
|
||||||
'$ git clone https://github.com/tinkle-community/nofx',
|
'$ git clone https://github.com/tinkle-community/nofx',
|
||||||
'$ docker compose up -d',
|
'$ cd nofx/web',
|
||||||
'🚀 NOFX 已启动',
|
'$ npm install',
|
||||||
'✓ AI 代理运行中',
|
'$ npm run dev',
|
||||||
'✓ 交易所已连接',
|
'🚀 前端已启动 http://localhost:3000',
|
||||||
'✓ 策略已激活',
|
'✓ 就绪',
|
||||||
]}
|
]}
|
||||||
typingSpeed={24}
|
typingSpeed={55}
|
||||||
lineDelay={350}
|
lineDelay={700}
|
||||||
className='text-sm font-mono'
|
className='text-sm font-mono'
|
||||||
|
style={{ color: '#00FF41', textShadow: '0 0 6px rgba(0,255,65,0.6)' }}
|
||||||
/>
|
/>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</motion.div>
|
</motion.div>
|
||||||
@@ -940,33 +923,6 @@ export function LandingPage() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Helper Components
|
|
||||||
function FloatingCard({ children, delay, position, color }: any) {
|
|
||||||
return (
|
|
||||||
<motion.div
|
|
||||||
className={`absolute rounded-xl px-4 py-3 backdrop-blur-xl z-20`}
|
|
||||||
style={{
|
|
||||||
background: 'rgba(30, 35, 41, 0.9)',
|
|
||||||
border: `1px solid ${
|
|
||||||
color === 'green'
|
|
||||||
? 'rgba(14, 203, 129, 0.3)'
|
|
||||||
: 'rgba(240, 185, 11, 0.3)'
|
|
||||||
}`,
|
|
||||||
...Object.keys(position).reduce((acc: any, key) => {
|
|
||||||
acc[key] = position[key] + 'rem'
|
|
||||||
return acc
|
|
||||||
}, {}),
|
|
||||||
}}
|
|
||||||
initial={{ opacity: 0, scale: 0 }}
|
|
||||||
animate={{ opacity: 1, scale: 1 }}
|
|
||||||
transition={{ delay, type: 'spring', stiffness: 260, damping: 20 }}
|
|
||||||
whileHover={{ scale: 1.1, rotate: 5 }}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</motion.div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
function AnimatedSection({
|
function AnimatedSection({
|
||||||
children,
|
children,
|
||||||
id,
|
id,
|
||||||
|
|||||||
@@ -5,15 +5,17 @@ interface TypewriterProps {
|
|||||||
typingSpeed?: number // 毫秒/字符
|
typingSpeed?: number // 毫秒/字符
|
||||||
lineDelay?: number // 每行结束的额外等待
|
lineDelay?: number // 每行结束的额外等待
|
||||||
className?: string
|
className?: string
|
||||||
|
style?: React.CSSProperties
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function Typewriter({
|
export default function Typewriter({
|
||||||
lines,
|
lines,
|
||||||
typingSpeed = 25,
|
typingSpeed = 50,
|
||||||
lineDelay = 400,
|
lineDelay = 600,
|
||||||
className,
|
className,
|
||||||
|
style,
|
||||||
}: TypewriterProps) {
|
}: TypewriterProps) {
|
||||||
const [text, setText] = useState('')
|
const [typedLines, setTypedLines] = useState<string[]>([''])
|
||||||
const [showCursor, setShowCursor] = useState(true)
|
const [showCursor, setShowCursor] = useState(true)
|
||||||
const lineIndexRef = useRef(0)
|
const lineIndexRef = useRef(0)
|
||||||
const charIndexRef = useRef(0)
|
const charIndexRef = useRef(0)
|
||||||
@@ -24,15 +26,19 @@ export default function Typewriter({
|
|||||||
function typeNext() {
|
function typeNext() {
|
||||||
const currentLine = lines[lineIndexRef.current] ?? ''
|
const currentLine = lines[lineIndexRef.current] ?? ''
|
||||||
if (charIndexRef.current < currentLine.length) {
|
if (charIndexRef.current < currentLine.length) {
|
||||||
setText((t) => t + currentLine[charIndexRef.current])
|
setTypedLines((prev) => {
|
||||||
|
const next = [...prev]
|
||||||
|
next[next.length - 1] = (next[next.length - 1] || '') + currentLine[charIndexRef.current]
|
||||||
|
return next
|
||||||
|
})
|
||||||
charIndexRef.current += 1
|
charIndexRef.current += 1
|
||||||
timerRef.current = window.setTimeout(typeNext, typingSpeed)
|
timerRef.current = window.setTimeout(typeNext, typingSpeed)
|
||||||
} else {
|
} else {
|
||||||
// 行结束
|
// 行结束
|
||||||
if (lineIndexRef.current < lines.length - 1) {
|
if (lineIndexRef.current < lines.length - 1) {
|
||||||
setText((t) => t + '\n')
|
|
||||||
lineIndexRef.current += 1
|
lineIndexRef.current += 1
|
||||||
charIndexRef.current = 0
|
charIndexRef.current = 0
|
||||||
|
setTypedLines((prev) => [...prev, ''])
|
||||||
timerRef.current = window.setTimeout(typeNext, lineDelay)
|
timerRef.current = window.setTimeout(typeNext, lineDelay)
|
||||||
} else {
|
} else {
|
||||||
// 最后一行输入完毕
|
// 最后一行输入完毕
|
||||||
@@ -55,8 +61,8 @@ export default function Typewriter({
|
|||||||
}, [lines, typingSpeed, lineDelay])
|
}, [lines, typingSpeed, lineDelay])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<pre className={className}>
|
<pre className={className} style={style}>
|
||||||
{text}
|
{typedLines.join('\n')}
|
||||||
<span style={{ opacity: showCursor ? 1 : 0 }}> ▍</span>
|
<span style={{ opacity: showCursor ? 1 : 0 }}> ▍</span>
|
||||||
</pre>
|
</pre>
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user