教程区块链区块链技术ch1717.7 投票动画与实时更新实现

本页目录

flowchart TD
    Sub[WebSocket 订阅<br/>solana_account_sub] --> Event[Account/Slot 变动事件]
    Event --> Act[查询 RPC 获取最新数据]
    Act --> Opt{数据有变更?}
    Opt -->|是| Anim[React 动画过渡<br/>react-spring / GSAP]
    Anim --> UI[更新展示组件<br/>Chart/表格]
    Opt -->|否| Idle[丢弃更新]
    UI --> Sub
    style Anim fill:#ffe0b2
    style UI fill:#c8e6c9

数据变化需要视觉反馈。投票后条形图应平滑增长,票数应闪烁更新。


17.7.1 React 动画方案

tsx
// CSS 过渡动画
// components/VoteBar.tsx
import { useEffect, useState } from 'react';

export const VoteBar = ({ current, previous, label }: { current: number; previous: number; label: string; }) => {
  const [display, setDisplay] = useState(previous);
  
  // 数字递增动画
  useEffect(() => {
    if (current <= display) { setDisplay(current); return; }
    const step = Math.max(1, Math.ceil((current - display) / 20));
    const timer = setInterval(() => {
      setDisplay(d => {
        if (d >= current) { clearInterval(timer); return d; }
        return Math.min(d + step, current);
      });
    }, 50);
    return () => clearInterval(timer);
  }, [current]);

  return (
    <div className="vote-bar">
      <div className="label">{label}</div>
      <div className="bar-container">
        <div className="bar-fill" style={{ 
          width: `${display}%`,
          transition: 'width 1s ease-out',
        }} />
      </div>
      <div className="count">{display} 票</div>
    </div>
  );
};

17.7.2 事件监听(WebSocket 替代轮询)

typescript
// 使用 Solana 的 WebSocket 订阅
import { Connection, clusterApiUrl, PublicKey } from '@solana/web3.js';

const wsConnection = new Connection(clusterApiUrl('devnet'), 'confirmed');

export function subscribeToPoll(pollAddress: string, onUpdate: (data: any) => void) {
  const pubKey = new PublicKey(pollAddress);
  
  // 订阅账户变化
  const subId = wsConnection.onAccountChange(pubKey, (accountInfo) => {
    // 反序列化数据
    onUpdate(accountInfo.data);
  });
  
  return () => wsConnection.removeAccountChangeListener(subId);
}

17.7.3 动画 UX 原则

动画时长缓动
票数变化300msease-out
条形增长1000mscubic-bezier(0.4, 0, 0.2, 1)
新投票出现500msslide-down + fade
投票成功800msscale(1.05) → 1.0

, 前往 → 17.8 测试 |*

评论

0

评论加载中…

发表评论

0/2000