Skip to content

🎰 High-Performance Text Diff Motion Component. Make your text flow like water. 高性能文本 Diff 动画组件:让你的文本平滑演变,支持任意字符 (数字/中英文/Emoji),支持 React & Vue & Svelte

License

Notifications You must be signed in to change notification settings

tombcato/smart-ticker

Repository files navigation

Smart Ticker Smart Ticker

Smart Ticker

🇨🇳 简体中文  |  🇬🇧 English

High-Performance Text Diff Motion Component based on Levenshtein diff algorithm. Make your text flow like water. Live Demo >

Supports any characters
Demo

Supports Prefix/Suffix, Intl Formatting, Auto-Scale, Fading Edges
Demo

Demo

React Vue Svelte TypeScript npm

🌏 Multi-Charset Support
Supports CJK, Numbers, Emojis, and mixed text rolling. Auto-adjusts spacing based on Unicode width.
🧠 Smart Diff Animation
Uses Levenshtein algorithm to find the shortest change path; identical characters remain static.
⚡ Smooth Interruption
Seamlessly transitions to new targets if the value changes dynamically during animation.
📈 Rich Motion
Built-in variety of easings.Supports custom easing function. Supports charWidth fine-tuning.
🦄 Multi-Framework
React (Hooks), Vue 3 (Composition), and Svelte 4+ components with a unified API.
🚀 High Performance
Powered by RAF, supporting Auto-scale, Fading Edge, and Disable Animation.

📦 Installation

NPM (Recommended)

npm install @tombcato/smart-ticker

From Source

# Clone repository
git clone https://github.com/tombcato/smart-ticker.git

# Install dependencies
cd smart-ticker
npm install

# Start dev server
npm run dev

🚀 Usage

📦 Import Styles

When using NPM, you MUST explicitly import the style file for the component to work.

import '@tombcato/smart-ticker/style.css'

Source Integration: If copying source code, ensure React version imports Ticker.css and Vue version uses the built-in styles.

React

// NPM Usage
import { Ticker } from '@tombcato/smart-ticker';
import '@tombcato/smart-ticker/style.css';

// Source Usage
// import { Ticker } from './components/Ticker';

function App() {
  const [price, setPrice] = useState(73.18);

  return (
    <Ticker
      value={price.toFixed(2)}
      duration={800}
      easing="easeInOut"
      charWidth={1}
      characterLists={['0123456789.,']}
    />
  );
}

Vue

<script setup>
// NPM Usage
import { Ticker } from '@tombcato/smart-ticker/vue';
import '@tombcato/smart-ticker/style.css';

// Source Usage
// import Ticker from './components/vue/Ticker.vue';

import { ref } from 'vue';

const price = ref('73.18');
</script>
<template>
  <Ticker
    :value="price"
    :duration="800"
    easing="easeInOut"
    :char-width="1"
    :character-lists="['0123456789.,']"
  />
</template>

Svelte

<script>
  // NPM Usage
  import { Ticker } from '@tombcato/smart-ticker/svelte';
  import '@tombcato/smart-ticker/style.css';

  let price = 73.18;
</script>

<Ticker
  value={price.toFixed(2)}
  duration={800}
  easing="easeInOut"
  charWidth={1}
  characterLists={['0123456789.,']}
/>

💅 Customization

Custom Fonts

The component uses the system monospace stack by default. To use a custom font (e.g., JetBrains Mono), ensure it is monospace and override via CSS:

/* In global styles or component styles */
.ticker {
  font-family: 'JetBrains Mono', monospace !important;
}

Note: Must be a monospace font, otherwise alignment issues may occur during scrolling animations.

⚙️ API

Props

Prop Type Default Description
value string|number - The text value to display (Required)
duration number 500 Animation duration (ms)
easing EasingName | function 'easeInOut' Easing: linear, easeIn, easeOut, easeInOut, bounce, or custom (t: number) => number
direction string 'ANY' Scroll direction: UP, DOWN, ANY (shortest path)
charWidth number 1 Character width multiplier (base 0.8em)
characterLists string[] ['0123456789'] Allowed character sets
className string '' Custom CSS class name
animateOnMount boolean false Animate on initial render
disableAnimation boolean false Disable animation, show final value immediately
autoScale boolean false Enable auto-scaling to fit container width
fadingEdge boolean false Enable top/bottom fading edge effect
prefix string - Static prefix (not animated)
suffix string - Static suffix (not animated)
numberFormat Intl.NumberFormat - Intl formatter number value
onAnimationEnd () => void - Callback when animation ends (Vue: @animation-end)

🧩 Character Configuration (characterLists)

characterLists controls the core animation logic. It accepts an array of strings, where each string represents a group of characters that can scroll into each other.

Presets (Common Character Lists)

For convenience, we provide built-in constants for common character sets:

import { Presets } from '@tombcato/smart-ticker';

Presets.NUMBER        // '0123456789'
Presets.ALPHABET      // 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
Presets.ALPHANUMERIC  // '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
Presets.CURRENCY      // '0123456789.,'

Animation Rules

  1. Scroll: If both the old and new characters belong to the same group string (e.g., 0 to 9 in Presets.NUMBER), they will scroll.
  2. Switch: If they are in different groups, or if a character is not in any list (e.g., Chinese characters), they will switch instantly (fade/flip) without scrolling.

Configuration Tips

  • Common Use Case: Simply use Presets.ALPHANUMERIC to support most alphanumeric scrolling.
  • Case Isolation: To prevent scrolling between cases (e.g., a -> A), list them as separate groups: [Presets.NUMBER, 'abc...', 'ABC...'].

Code Example:

<Ticker
  value={val}
  characterLists={[
    Presets.NUMBER,                 // Numbers
    'abcdefghijklmnopqrstuvwxyz', // Lowercase Group
    'ABCDEFGHIJKLMNOPQRSTUVWXYZ', // Uppercase Group
    '.,!@#$%^&*'                  // Symbols
  ]}
/>

💻 Running Demos

This project includes complete NPM-based user examples for React, Vue, and Svelte in the examples directory.

Start React Demo

cd examples/react-demo
npm install
npm run dev

Start Vue Demo

cd examples/vue-demo
npm install
npm run dev

Start Svelte Demo

cd examples/svelte-demo
npm install
npm run dev

📁 Project Structure

smart-ticker/
├── src/
│   ├── components/
│   │   ├── Ticker.tsx      # React Component
│   │   ├── Ticker.css      # Core Styles
│   │   ├── vue/
│   │   │   └── Ticker.vue  # Vue Component
│   │   └── svelte/
│   │       └── Ticker.svelte # Svelte Component
│   ├── core/
│   │   └── TickerCore.ts   # Core Logic (Levenshtein diff algo)
│   └── ...
├── examples/               # Standalone Example Projects
│   ├── react-demo/         # React Demo (Vite + React + TS)
│   ├── vue-demo/           # Vue Demo (Vite + Vue + TS)
│   └── svelte-demo/        # Svelte Demo (Vite + Svelte + TS)
└── package.json

🎨 Example Scenarios

  • Financial Data - Stock prices, crypto rates
  • Counters - Page views, likes
  • Scoreboards - Real-time sports scores
  • Airport Info - Flight numbers, gates
  • Privacy Mode - Balance hide/show toggle

🔧 Tech Stack

  • Build Tool: Vite
  • Language: TypeScript
  • Frameworks: React 18 / Vue 3 / Svelte 4+
  • Styling: CSS Variables + Responsive Design

📝 Changelog

See CHANGELOG_EN.md for version history.

📄 License

MIT

About

🎰 High-Performance Text Diff Motion Component. Make your text flow like water. 高性能文本 Diff 动画组件:让你的文本平滑演变,支持任意字符 (数字/中英文/Emoji),支持 React & Vue & Svelte

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published