#Animation
Die Animationsfunktionen von VSeed unterstützen Phasen wie Erscheinen, Schleife, Atmosphäre, Aktualisierung und Verlassen. Dieser Leitfaden fasst Beispiele für Balken-, Linien-/Flächen-, Kreis-, Radar- und Streudiagramme zusammen, damit Sie die Konfigurationen über Diagrammtypen hinweg vergleichen können.
#Balken-/Säulendiagramm-Animation
Alle Beispiele basieren auf dem Large-Screen-Theme (dunkel) und bieten eine Auswahlliste zum Wechseln zwischen verschiedenen Themes.
Themes werden geladen von: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json
#1. Eingangsanimation
Die Eingangsanimation ist die Bewegung, die abgespielt wird, wenn ein Diagramm erstmals angezeigt wird.
Für Balken-/Säulenserien unterstützt der Eingangseffekt derzeit growth.
#1.1 growth (Wachstum)
import { useEffect, useState } from 'react'
import { VSeedRender } from '@components'
import { registerTokenThemes } from '@visactor/vseed'
const THEME_URL = 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json'
const DATASET = [
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 24,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 24,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 40,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 40,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 50,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 50,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2022',
},
]
const DIMENSIONS = [
{ id: 'HqlYadRdHJ5c', alias: 'Category' },
{ id: '7ti8XuX4kcY1', alias: 'Year' },
]
const MEASURES = [{ id: 'Tn97A7q0XVDq', alias: 'Sales' }]
const useLargeScreenThemes = () => {
const [themes, setThemes] = useState({})
const [themeKey, setThemeKey] = useState('')
useEffect(() => {
fetch(THEME_URL)
.then((r) => r.json())
.then((remote) => {
const registry = {}
Object.entries(remote).forEach(([key, value]) => {
const colors = value?.colors || []
registry[key] = {
baseTheme: 'dark',
colorScheme: colors.length >= 2 ? colors : [colors[0] || '#00D5FF', '#227BFF'],
linearColorScheme: [colors[0] || '#003B73', colors[1] || '#00D5FF'],
textPrimary: '#EAF7FF',
textSecondary: '#8FC7FF',
borderColor: 'rgba(82, 191, 255, 0.28)',
surfaceColor: '#071A33',
tooltipBackgroundColor: 'rgba(5, 18, 38, 0.92)',
axisGridColor: 'rgba(82, 191, 255, 0.18)',
accentColor: colors[0] || '#00D5FF',
}
})
registerTokenThemes(registry, { ensureRegisterAll: false })
setThemes(remote)
const firstKey = Object.keys(remote)[0] || ''
setThemeKey(firstKey)
})
.catch(() => {})
}, [])
return { themes, themeKey, setThemeKey }
}
const ThemeSelect = ({ themes, themeKey, onChange }) => (
<select
value={themeKey}
onChange={(e) => onChange(e.target.value)}
style={{
marginBottom: 12,
color: '#EAF7FF',
background: 'rgba(0, 213, 255, 0.18)',
border: '1px solid rgba(0, 213, 255, 0.45)',
padding: '6px 12px',
}}
>
{Object.entries(themes).map(([key, value]) => (
<option key={key} value={key} style={{ color: '#000' }}>
{value?.name || key}
</option>
))}
</select>
)
export default () => {
const { themes, themeKey, setThemeKey } = useLargeScreenThemes()
if (!themeKey) return null
const vseedConfig = {
theme: themeKey,
chartType: 'columnParallel',
dataset: DATASET,
dimensions: DIMENSIONS,
measures: MEASURES,
label: { enable: false },
animation: {
enable: true,
params: {
appear: { enable: true, effects: ['growth'], ease: 'circInOut', duration: 1 },
},
},
}
return (
<div style={{ padding: 16, background: '#061A33' }}>
<ThemeSelect themes={themes} themeKey={themeKey} onChange={setThemeKey} />
<VSeedRender vseed={vseedConfig} />
</div>
)
}#2. Schleifenanimation
Die Schleifenanimation ist die fortlaufende Bewegung nach dem ersten Rendern und eignet sich für Hervorhebung und dynamischen Rhythmus.
#2.1 highlight (Gruppenhervorhebung) + atmosphere (Atmosphäreneffekt)
import { useEffect, useState } from 'react'
import { VSeedRender } from '@components'
import { registerTokenThemes } from '@visactor/vseed'
const THEME_URL = 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json'
const DATASET = [
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 24,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 24,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 40,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 40,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 50,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 50,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2022',
},
]
export default () => {
const [themes, setThemes] = useState({})
const [themeKey, setThemeKey] = useState('')
useEffect(() => {
fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json')
.then((r) => r.json())
.then((remote) => {
const registry = {}
Object.entries(remote).forEach(([key, value]) => {
const colors = value?.colors || []
registry[key] = {
baseTheme: 'dark',
colorScheme: colors.length >= 2 ? colors : [colors[0] || '#00D5FF', '#227BFF'],
linearColorScheme: [colors[0] || '#003B73', colors[1] || '#00D5FF'],
textPrimary: '#EAF7FF',
textSecondary: '#8FC7FF',
borderColor: 'rgba(82, 191, 255, 0.28)',
surfaceColor: '#071A33',
tooltipBackgroundColor: 'rgba(5, 18, 38, 0.92)',
axisGridColor: 'rgba(82, 191, 255, 0.18)',
accentColor: colors[0] || '#00D5FF',
}
})
registerTokenThemes(registry, { ensureRegisterAll: false })
setThemes(remote)
setThemeKey(Object.keys(remote)[0] || '')
})
.catch(() => {})
}, [])
if (!themeKey) return null
const vseedConfig = {
theme: themeKey,
chartType: 'columnParallel',
dataset: DATASET,
dimensions: [
{ id: 'HqlYadRdHJ5c', alias: 'Category' },
{ id: '7ti8XuX4kcY1', alias: 'Year' },
],
measures: [{ id: 'Tn97A7q0XVDq', alias: 'Sales' }],
label: { enable: false },
animation: {
enable: true,
params: {
appear: { enable: true, effects: ['growth'], ease: 'linear', duration: 1 },
loop: {
enable: true,
interval: 3,
loop: { enable: true, effects: ['highLight'], ease: 'linear', duration: 1 },
atmosphere: { effect: 'breath', ease: 'linear', color: '#4A90E2' },
},
},
},
}
return (
<div style={{ padding: 16, background: '#061A33' }}>
<select
value={themeKey}
onChange={(e) => setThemeKey(e.target.value)}
style={{
marginBottom: 12,
color: '#EAF7FF',
background: 'rgba(0, 213, 255, 0.18)',
border: '1px solid rgba(0, 213, 255, 0.45)',
padding: '6px 12px',
}}
>
{Object.entries(themes).map(([key, value]) => (
<option key={key} value={key} style={{ color: '#000' }}>
{value?.name || key}
</option>
))}
</select>
<VSeedRender vseed={vseedConfig} />
</div>
)
}#2.2 growth (Schleife) + atmosphere (Atmosphäreneffekt)
import { useEffect, useState } from 'react'
import { VSeedRender } from '@components'
import { registerTokenThemes } from '@visactor/vseed'
const DATASET = [
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 24,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 24,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 40,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 40,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 50,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 50,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2022',
},
]
export default () => {
const [themes, setThemes] = useState({})
const [themeKey, setThemeKey] = useState('')
useEffect(() => {
fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json')
.then((r) => r.json())
.then((remote) => {
const registry = {}
Object.entries(remote).forEach(([key, value]) => {
const colors = value?.colors || []
registry[key] = {
baseTheme: 'dark',
colorScheme: colors.length >= 2 ? colors : [colors[0] || '#00D5FF', '#227BFF'],
linearColorScheme: [colors[0] || '#003B73', colors[1] || '#00D5FF'],
textPrimary: '#EAF7FF',
textSecondary: '#8FC7FF',
borderColor: 'rgba(82, 191, 255, 0.28)',
surfaceColor: '#071A33',
tooltipBackgroundColor: 'rgba(5, 18, 38, 0.92)',
axisGridColor: 'rgba(82, 191, 255, 0.18)',
accentColor: colors[0] || '#00D5FF',
}
})
registerTokenThemes(registry, { ensureRegisterAll: false })
setThemes(remote)
setThemeKey(Object.keys(remote)[0] || '')
})
.catch(() => {})
}, [])
if (!themeKey) return null
const vseedConfig = {
theme: themeKey,
chartType: 'barParallel',
dataset: DATASET,
dimensions: [
{ id: 'HqlYadRdHJ5c', alias: 'Category' },
{ id: '7ti8XuX4kcY1', alias: 'Year' },
],
measures: [{ id: 'Tn97A7q0XVDq', alias: 'Sales' }],
label: { enable: false },
animation: {
enable: true,
params: {
appear: { enable: true, effects: ['growth'], ease: 'linear', duration: 1 },
loop: {
enable: true,
interval: 2,
loop: { enable: true, effects: ['growth'], ease: 'linear', duration: 1 },
atmo: { effect: 'breath', ease: 'linear', color: '#4A90E2' },
},
},
},
}
return (
<div style={{ padding: 16, background: '#061A33' }}>
<select
value={themeKey}
onChange={(e) => setThemeKey(e.target.value)}
style={{
marginBottom: 12,
color: '#EAF7FF',
background: 'rgba(0, 213, 255, 0.18)',
border: '1px solid rgba(0, 213, 255, 0.45)',
padding: '6px 12px',
}}
>
{Object.entries(themes).map(([key, value]) => (
<option key={key} value={key} style={{ color: '#000' }}>
{value?.name || key}
</option>
))}
</select>
<VSeedRender vseed={vseedConfig} />
</div>
)
}#2.3 moveIn (Schleife) + atmosphere (Atmosphäreneffekt)
import { useEffect, useState } from 'react'
import { VSeedRender } from '@components'
import { registerTokenThemes } from '@visactor/vseed'
const DATASET = [
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 24,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 24,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 40,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 40,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 50,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 50,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2022',
},
]
export default () => {
const [themes, setThemes] = useState({})
const [themeKey, setThemeKey] = useState('')
useEffect(() => {
fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json')
.then((r) => r.json())
.then((remote) => {
const registry = {}
Object.entries(remote).forEach(([key, value]) => {
const colors = value?.colors || []
registry[key] = {
baseTheme: 'dark',
colorScheme: colors.length >= 2 ? colors : [colors[0] || '#00D5FF', '#227BFF'],
linearColorScheme: [colors[0] || '#003B73', colors[1] || '#00D5FF'],
textPrimary: '#EAF7FF',
textSecondary: '#8FC7FF',
borderColor: 'rgba(82, 191, 255, 0.28)',
surfaceColor: '#071A33',
tooltipBackgroundColor: 'rgba(5, 18, 38, 0.92)',
axisGridColor: 'rgba(82, 191, 255, 0.18)',
accentColor: colors[0] || '#00D5FF',
}
})
registerTokenThemes(registry, { ensureRegisterAll: false })
setThemes(remote)
setThemeKey(Object.keys(remote)[0] || '')
})
.catch(() => {})
}, [])
if (!themeKey) return null
const vseedConfig = {
theme: themeKey,
chartType: 'columnParallel',
dataset: DATASET,
dimensions: [
{ id: 'HqlYadRdHJ5c', alias: 'Category' },
{ id: '7ti8XuX4kcY1', alias: 'Year' },
],
measures: [{ id: 'Tn97A7q0XVDq', alias: 'Sales' }],
label: { enable: false },
animation: {
enable: true,
params: {
appear: { enable: true, effects: ['growth'], ease: 'linear', duration: 1 },
loop: {
enable: true,
interval: 2,
loop: { enable: true, effects: ['moveIn'], ease: 'linear', duration: 1 },
atmo: { effect: 'breath', ease: 'linear', color: '#4A90E2' },
},
},
},
}
return (
<div style={{ padding: 16, background: '#061A33' }}>
<select
value={themeKey}
onChange={(e) => setThemeKey(e.target.value)}
style={{
marginBottom: 12,
color: '#EAF7FF',
background: 'rgba(0, 213, 255, 0.18)',
border: '1px solid rgba(0, 213, 255, 0.45)',
padding: '6px 12px',
}}
>
{Object.entries(themes).map(([key, value]) => (
<option key={key} value={key} style={{ color: '#000' }}>
{value?.name || key}
</option>
))}
</select>
<VSeedRender vseed={vseedConfig} />
</div>
)
}#Linien-/Flächendiagramm-Animation
Alle Beispiele basieren auf dem Large-Screen-Theme (dunkel) und bieten eine Auswahlliste zum Wechseln zwischen verschiedenen Themes.
Themes werden geladen von: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json
#1. Eingangsanimation
Die Eingangsanimation führt das Diagramm visuell ein, wenn es erstmals auf der Seite erscheint.
#1.1 load (Laden)
import { useEffect, useState } from 'react'
import { VSeedRender } from '@components'
import { registerTokenThemes, Builder } from '@visactor/vseed'
const THEME_URL = 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json'
const DATASET = [
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 24,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 24,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 40,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 40,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 50,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 50,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2022',
},
]
const DIMENSIONS = [
{ id: 'HqlYadRdHJ5c', alias: 'Category' },
{ id: '7ti8XuX4kcY1', alias: 'Year' },
]
const MEASURES = [{ id: 'Tn97A7q0XVDq', alias: 'Sales' }]
const useLargeScreenThemes = () => {
const [themes, setThemes] = useState({})
const [themeKey, setThemeKey] = useState('')
useEffect(() => {
Builder.updateSpec('line', (spec) => ({
...spec,
point: { ...spec.point, style: { ...(spec.point && spec.point.style), lineWidth: 0, stroke: null } },
}))
Builder.updateSpec('area', (spec) => ({
...spec,
point: { ...spec.point, style: { ...(spec.point && spec.point.style), lineWidth: 0, stroke: null } },
}))
Builder.updateSpec('areaPercent', (spec) => ({
...spec,
point: { ...spec.point, style: { ...(spec.point && spec.point.style), lineWidth: 0, stroke: null } },
}))
fetch(THEME_URL)
.then((r) => r.json())
.then((remote) => {
const registry = {}
Object.entries(remote).forEach(([key, value]) => {
const colors = value?.colors || []
registry[key] = {
baseTheme: 'dark',
colorScheme: colors.length >= 2 ? colors : [colors[0] || '#00D5FF', '#227BFF'],
linearColorScheme: [colors[0] || '#003B73', colors[1] || '#00D5FF'],
textPrimary: '#EAF7FF',
textSecondary: '#8FC7FF',
borderColor: 'rgba(82, 191, 255, 0.28)',
surfaceColor: '#071A33',
tooltipBackgroundColor: 'rgba(5, 18, 38, 0.92)',
axisGridColor: 'rgba(82, 191, 255, 0.18)',
accentColor: colors[0] || '#00D5FF',
}
})
registerTokenThemes(registry, { ensureRegisterAll: false })
setThemes(remote)
setThemeKey(Object.keys(remote)[0] || '')
})
.catch(() => {})
}, [])
return { themes, themeKey, setThemeKey }
}
const ThemeSelect = ({ themes, themeKey, onChange }) => (
<select
value={themeKey}
onChange={(e) => onChange(e.target.value)}
style={{
marginBottom: 12,
color: '#EAF7FF',
background: 'rgba(0, 213, 255, 0.18)',
border: '1px solid rgba(0, 213, 255, 0.45)',
padding: '6px 12px',
}}
>
{Object.entries(themes).map(([key, value]) => (
<option key={key} value={key} style={{ color: '#000' }}>
{value?.name || key}
</option>
))}
</select>
)
export default () => {
const { themes, themeKey, setThemeKey } = useLargeScreenThemes()
if (!themeKey) return null
const vseedConfig = {
theme: themeKey,
chartType: 'line',
dataset: DATASET,
dimensions: DIMENSIONS,
measures: MEASURES,
label: { enable: false },
animation: {
enable: true,
params: { appear: { enable: true, effects: ['load'], ease: 'circInOut', duration: 1 } },
},
}
return (
<div style={{ padding: 16, background: '#061A33' }}>
<ThemeSelect themes={themes} themeKey={themeKey} onChange={setThemeKey} />
<VSeedRender vseed={vseedConfig} />
</div>
)
}#1.2 growth (Wachstum)
import { useEffect, useState } from 'react'
import { VSeedRender } from '@components'
import { registerTokenThemes, Builder } from '@visactor/vseed'
const DATASET = [
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 24,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 24,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 40,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 40,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 50,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 50,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2022',
},
]
export default () => {
const [themes, setThemes] = useState({})
const [themeKey, setThemeKey] = useState('')
useEffect(() => {
Builder.updateSpec('line', (spec) => ({
...spec,
point: { ...spec.point, style: { ...(spec.point && spec.point.style), lineWidth: 0, stroke: null } },
}))
Builder.updateSpec('area', (spec) => ({
...spec,
point: { ...spec.point, style: { ...(spec.point && spec.point.style), lineWidth: 0, stroke: null } },
}))
Builder.updateSpec('areaPercent', (spec) => ({
...spec,
point: { ...spec.point, style: { ...(spec.point && spec.point.style), lineWidth: 0, stroke: null } },
}))
fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json')
.then((r) => r.json())
.then((remote) => {
const registry = {}
Object.entries(remote).forEach(([key, value]) => {
const colors = value?.colors || []
registry[key] = {
baseTheme: 'dark',
colorScheme: colors.length >= 2 ? colors : [colors[0] || '#00D5FF', '#227BFF'],
linearColorScheme: [colors[0] || '#003B73', colors[1] || '#00D5FF'],
textPrimary: '#EAF7FF',
textSecondary: '#8FC7FF',
borderColor: 'rgba(82, 191, 255, 0.28)',
surfaceColor: '#071A33',
tooltipBackgroundColor: 'rgba(5, 18, 38, 0.92)',
axisGridColor: 'rgba(82, 191, 255, 0.18)',
accentColor: colors[0] || '#00D5FF',
}
})
registerTokenThemes(registry, { ensureRegisterAll: false })
setThemes(remote)
setThemeKey(Object.keys(remote)[0] || '')
})
.catch(() => {})
}, [])
if (!themeKey) return null
const vseedConfig = {
theme: themeKey,
chartType: 'area',
dataset: DATASET,
dimensions: [
{ id: 'HqlYadRdHJ5c', alias: 'Category' },
{ id: '7ti8XuX4kcY1', alias: 'Year' },
],
measures: [{ id: 'Tn97A7q0XVDq', alias: 'Sales' }],
label: { enable: false },
animation: {
enable: true,
params: { appear: { enable: true, effects: ['growth'], ease: 'linear', duration: 1 } },
},
}
return (
<div style={{ padding: 16, background: '#061A33' }}>
<select
value={themeKey}
onChange={(e) => setThemeKey(e.target.value)}
style={{
marginBottom: 12,
color: '#EAF7FF',
background: 'rgba(0, 213, 255, 0.18)',
border: '1px solid rgba(0, 213, 255, 0.45)',
padding: '6px 12px',
}}
>
{Object.entries(themes).map(([key, value]) => (
<option key={key} value={key} style={{ color: '#000' }}>
{value?.name || key}
</option>
))}
</select>
<VSeedRender vseed={vseedConfig} />
</div>
)
}#2. Schleifenanimation
Die Schleifenanimation hält das Diagramm bei lang laufenden Anzeigezuständen in zyklischer Bewegung.
#2.1 load (Schleife) + atmosphere (breath)
import { useEffect, useState } from 'react'
import { VSeedRender } from '@components'
import { registerTokenThemes, Builder } from '@visactor/vseed'
const DATASET = [
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 24,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 24,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 40,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 40,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 50,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 50,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2022',
},
]
export default () => {
const [themes, setThemes] = useState({})
const [themeKey, setThemeKey] = useState('')
useEffect(() => {
Builder.updateSpec('line', (spec) => ({
...spec,
point: { ...spec.point, style: { ...(spec.point && spec.point.style), lineWidth: 0, stroke: null } },
}))
Builder.updateSpec('area', (spec) => ({
...spec,
point: { ...spec.point, style: { ...(spec.point && spec.point.style), lineWidth: 0, stroke: null } },
}))
Builder.updateSpec('areaPercent', (spec) => ({
...spec,
point: { ...spec.point, style: { ...(spec.point && spec.point.style), lineWidth: 0, stroke: null } },
}))
fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json')
.then((r) => r.json())
.then((remote) => {
const registry = {}
Object.entries(remote).forEach(([key, value]) => {
const colors = value?.colors || []
registry[key] = {
baseTheme: 'dark',
colorScheme: colors.length >= 2 ? colors : [colors[0] || '#00D5FF', '#227BFF'],
linearColorScheme: [colors[0] || '#003B73', colors[1] || '#00D5FF'],
textPrimary: '#EAF7FF',
textSecondary: '#8FC7FF',
borderColor: 'rgba(82, 191, 255, 0.28)',
surfaceColor: '#071A33',
tooltipBackgroundColor: 'rgba(5, 18, 38, 0.92)',
axisGridColor: 'rgba(82, 191, 255, 0.18)',
accentColor: colors[0] || '#00D5FF',
}
})
registerTokenThemes(registry, { ensureRegisterAll: false })
setThemes(remote)
setThemeKey(Object.keys(remote)[0] || '')
})
.catch(() => {})
}, [])
if (!themeKey) return null
const vseedConfig = {
theme: themeKey,
chartType: 'line',
dataset: DATASET,
dimensions: [
{ id: 'HqlYadRdHJ5c', alias: 'Category' },
{ id: '7ti8XuX4kcY1', alias: 'Year' },
],
measures: [{ id: 'Tn97A7q0XVDq', alias: 'Sales' }],
label: { enable: false },
animation: {
enable: true,
params: {
appear: { enable: true, effects: ['load'], ease: 'linear', duration: 1 },
loop: {
enable: true,
interval: 2,
loop: { enable: true, effects: ['load'], ease: 'linear', duration: 1 },
atmosphere: { effect: 'breath', ease: 'linear' },
},
},
},
}
return (
<div style={{ padding: 16, background: '#061A33' }}>
<select
value={themeKey}
onChange={(e) => setThemeKey(e.target.value)}
style={{
marginBottom: 12,
color: '#EAF7FF',
background: 'rgba(0, 213, 255, 0.18)',
border: '1px solid rgba(0, 213, 255, 0.45)',
padding: '6px 12px',
}}
>
{Object.entries(themes).map(([key, value]) => (
<option key={key} value={key} style={{ color: '#000' }}>
{value?.name || key}
</option>
))}
</select>
<VSeedRender vseed={vseedConfig} />
</div>
)
}#2.2 load (Schleife) + atmosphere (ripple)
import { useEffect, useState } from 'react'
import { VSeedRender } from '@components'
import { registerTokenThemes, Builder } from '@visactor/vseed'
const DATASET = [
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 24,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 24,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 40,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 40,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 50,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 50,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2022',
},
]
export default () => {
const [themes, setThemes] = useState({})
const [themeKey, setThemeKey] = useState('')
useEffect(() => {
Builder.updateSpec('line', (spec) => ({
...spec,
point: { ...spec.point, style: { ...(spec.point && spec.point.style), lineWidth: 0, stroke: null } },
}))
Builder.updateSpec('area', (spec) => ({
...spec,
point: { ...spec.point, style: { ...(spec.point && spec.point.style), lineWidth: 0, stroke: null } },
}))
Builder.updateSpec('areaPercent', (spec) => ({
...spec,
point: { ...spec.point, style: { ...(spec.point && spec.point.style), lineWidth: 0, stroke: null } },
}))
fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json')
.then((r) => r.json())
.then((remote) => {
const registry = {}
Object.entries(remote).forEach(([key, value]) => {
const colors = value?.colors || []
registry[key] = {
baseTheme: 'dark',
colorScheme: colors.length >= 2 ? colors : [colors[0] || '#00D5FF', '#227BFF'],
linearColorScheme: [colors[0] || '#003B73', colors[1] || '#00D5FF'],
textPrimary: '#EAF7FF',
textSecondary: '#8FC7FF',
borderColor: 'rgba(82, 191, 255, 0.28)',
surfaceColor: '#071A33',
tooltipBackgroundColor: 'rgba(5, 18, 38, 0.92)',
axisGridColor: 'rgba(82, 191, 255, 0.18)',
accentColor: colors[0] || '#00D5FF',
}
})
registerTokenThemes(registry, { ensureRegisterAll: false })
setThemes(remote)
setThemeKey(Object.keys(remote)[0] || '')
})
.catch(() => {})
}, [])
if (!themeKey) return null
const vseedConfig = {
theme: themeKey,
chartType: 'areaPercent',
dataset: DATASET,
dimensions: [
{ id: 'HqlYadRdHJ5c', alias: 'Category' },
{ id: '7ti8XuX4kcY1', alias: 'Year' },
],
measures: [{ id: 'Tn97A7q0XVDq', alias: 'Sales' }],
label: { enable: false },
animation: {
enable: true,
params: {
appear: { enable: true, effects: ['growth'], ease: 'linear', duration: 1 },
loop: {
enable: true,
interval: 3,
loop: { enable: true, effects: ['load'], ease: 'circInOut', duration: 1 },
atmosphere: { effect: 'ripple', ease: 'linear' },
},
},
},
}
return (
<div style={{ padding: 16, background: '#061A33' }}>
<select
value={themeKey}
onChange={(e) => setThemeKey(e.target.value)}
style={{
marginBottom: 12,
color: '#EAF7FF',
background: 'rgba(0, 213, 255, 0.18)',
border: '1px solid rgba(0, 213, 255, 0.45)',
padding: '6px 12px',
}}
>
{Object.entries(themes).map(([key, value]) => (
<option key={key} value={key} style={{ color: '#000' }}>
{value?.name || key}
</option>
))}
</select>
<VSeedRender vseed={vseedConfig} />
</div>
)
}#Kreis-/Donut-/Rose-Diagramm-Animation
Alle Beispiele basieren auf dem Large-Screen-Theme (dunkel) und bieten eine Auswahlliste zum Wechseln zwischen verschiedenen Themes.
Themes werden geladen von: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json
#1. Eingangsanimation
Die Eingangsanimation steuert, wie Segmente erstmals in die Ansicht gelangen.
#1.1 radial (vom Zentrum nach außen)
import { useEffect, useState } from 'react'
import { VSeedRender } from '@components'
import { registerTokenThemes } from '@visactor/vseed'
const THEME_URL = 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json'
const DATASET = [
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 24,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 24,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 40,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 40,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 50,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 50,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2022',
},
]
const DIMENSIONS = [{ id: 'HqlYadRdHJ5c', alias: 'Category' }]
const MEASURES = [{ id: 'Tn97A7q0XVDq', alias: 'Sales' }]
const useLargeScreenThemes = () => {
const [themes, setThemes] = useState({})
const [themeKey, setThemeKey] = useState('')
useEffect(() => {
fetch(THEME_URL)
.then((r) => r.json())
.then((remote) => {
const registry = {}
Object.entries(remote).forEach(([key, value]) => {
const colors = value?.colors || []
registry[key] = {
baseTheme: 'dark',
colorScheme: colors.length >= 2 ? colors : [colors[0] || '#00D5FF', '#227BFF'],
linearColorScheme: [colors[0] || '#003B73', colors[1] || '#00D5FF'],
textPrimary: '#EAF7FF',
textSecondary: '#8FC7FF',
borderColor: 'rgba(82, 191, 255, 0.28)',
surfaceColor: '#071A33',
tooltipBackgroundColor: 'rgba(5, 18, 38, 0.92)',
axisGridColor: 'rgba(82, 191, 255, 0.18)',
accentColor: colors[0] || '#00D5FF',
}
})
registerTokenThemes(registry, { ensureRegisterAll: false })
setThemes(remote)
setThemeKey(Object.keys(remote)[0] || '')
})
.catch(() => {})
}, [])
return { themes, themeKey, setThemeKey }
}
const ThemeSelect = ({ themes, themeKey, onChange }) => (
<select
value={themeKey}
onChange={(e) => onChange(e.target.value)}
style={{
marginBottom: 12,
color: '#EAF7FF',
background: 'rgba(0, 213, 255, 0.18)',
border: '1px solid rgba(0, 213, 255, 0.45)',
padding: '6px 12px',
}}
>
{Object.entries(themes).map(([key, value]) => (
<option key={key} value={key} style={{ color: '#000' }}>
{value?.name || key}
</option>
))}
</select>
)
export default () => {
const { themes, themeKey, setThemeKey } = useLargeScreenThemes()
if (!themeKey) return null
const vseedConfig = {
theme: themeKey,
chartType: 'pie',
dataset: DATASET,
dimensions: DIMENSIONS,
measures: MEASURES,
label: { enable: false },
animation: {
enable: true,
params: { appear: { enable: true, effects: ['radial'], ease: 'circInOut', duration: 1 } },
},
}
return (
<div style={{ padding: 16, background: '#061A33' }}>
<ThemeSelect themes={themes} themeKey={themeKey} onChange={setThemeKey} />
<VSeedRender vseed={vseedConfig} />
</div>
)
}#1.2 scale (Skalierung)
import { useEffect, useState } from 'react'
import { VSeedRender } from '@components'
import { registerTokenThemes } from '@visactor/vseed'
const DATASET = [
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 24,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 24,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 40,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 40,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 50,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 50,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2022',
},
]
export default () => {
const [themes, setThemes] = useState({})
const [themeKey, setThemeKey] = useState('')
useEffect(() => {
fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json')
.then((r) => r.json())
.then((remote) => {
const registry = {}
Object.entries(remote).forEach(([key, value]) => {
const colors = value?.colors || []
registry[key] = {
baseTheme: 'dark',
colorScheme: colors.length >= 2 ? colors : [colors[0] || '#00D5FF', '#227BFF'],
linearColorScheme: [colors[0] || '#003B73', colors[1] || '#00D5FF'],
textPrimary: '#EAF7FF',
textSecondary: '#8FC7FF',
borderColor: 'rgba(82, 191, 255, 0.28)',
surfaceColor: '#071A33',
tooltipBackgroundColor: 'rgba(5, 18, 38, 0.92)',
axisGridColor: 'rgba(82, 191, 255, 0.18)',
accentColor: colors[0] || '#00D5FF',
}
})
registerTokenThemes(registry, { ensureRegisterAll: false })
setThemes(remote)
setThemeKey(Object.keys(remote)[0] || '')
})
.catch(() => {})
}, [])
if (!themeKey) return null
const vseedConfig = {
theme: themeKey,
chartType: 'donut',
dataset: DATASET,
dimensions: [{ id: 'HqlYadRdHJ5c', alias: 'Category' }],
measures: [{ id: 'Tn97A7q0XVDq', alias: 'Sales' }],
label: { enable: false },
animation: {
enable: true,
params: { appear: { enable: true, effects: ['scale'], ease: 'circInOut', duration: 1 } },
},
}
return (
<div style={{ padding: 16, background: '#061A33' }}>
<select
value={themeKey}
onChange={(e) => setThemeKey(e.target.value)}
style={{
marginBottom: 12,
color: '#EAF7FF',
background: 'rgba(0, 213, 255, 0.18)',
border: '1px solid rgba(0, 213, 255, 0.45)',
padding: '6px 12px',
}}
>
{Object.entries(themes).map(([key, value]) => (
<option key={key} value={key} style={{ color: '#000' }}>
{value?.name || key}
</option>
))}
</select>
<VSeedRender vseed={vseedConfig} />
</div>
)
}#2. Schleifenanimation
Die Schleifenanimation hebt bestimmte Segmente periodisch hervor.
#2.1 enlarge (Größe ändern)
import { useEffect, useState } from 'react'
import { VSeedRender } from '@components'
import { registerTokenThemes } from '@visactor/vseed'
const DATASET = [
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 24,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 24,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 40,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 40,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 50,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 50,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2022',
},
]
export default () => {
const [themes, setThemes] = useState({})
const [themeKey, setThemeKey] = useState('')
useEffect(() => {
fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json')
.then((r) => r.json())
.then((remote) => {
const registry = {}
Object.entries(remote).forEach(([key, value]) => {
const colors = value?.colors || []
registry[key] = {
baseTheme: 'dark',
colorScheme: colors.length >= 2 ? colors : [colors[0] || '#00D5FF', '#227BFF'],
linearColorScheme: [colors[0] || '#003B73', colors[1] || '#00D5FF'],
textPrimary: '#EAF7FF',
textSecondary: '#8FC7FF',
borderColor: 'rgba(82, 191, 255, 0.28)',
surfaceColor: '#071A33',
tooltipBackgroundColor: 'rgba(5, 18, 38, 0.92)',
axisGridColor: 'rgba(82, 191, 255, 0.18)',
accentColor: colors[0] || '#00D5FF',
}
})
registerTokenThemes(registry, { ensureRegisterAll: false })
setThemes(remote)
setThemeKey(Object.keys(remote)[0] || '')
})
.catch(() => {})
}, [])
if (!themeKey) return null
const vseedConfig = {
theme: themeKey,
chartType: 'pie',
dataset: DATASET,
dimensions: [{ id: 'HqlYadRdHJ5c', alias: 'Category' }],
measures: [{ id: 'Tn97A7q0XVDq', alias: 'Sales' }],
label: { enable: false },
animation: {
enable: true,
params: {
appear: { enable: true, effects: ['scale'], ease: 'linear', duration: 1 },
loop: { enable: true, interval: 2, loop: { enable: true, effects: ['enlarge'], ease: 'linear', duration: 1 } },
},
},
}
return (
<div style={{ padding: 16, background: '#061A33' }}>
<select
value={themeKey}
onChange={(e) => setThemeKey(e.target.value)}
style={{
marginBottom: 12,
color: '#EAF7FF',
background: 'rgba(0, 213, 255, 0.18)',
border: '1px solid rgba(0, 213, 255, 0.45)',
padding: '6px 12px',
}}
>
{Object.entries(themes).map(([key, value]) => (
<option key={key} value={key} style={{ color: '#000' }}>
{value?.name || key}
</option>
))}
</select>
<VSeedRender vseed={vseedConfig} />
</div>
)
}#2.2 relocate (Zentrum verschieben)
import { useEffect, useState } from 'react'
import { VSeedRender } from '@components'
import { registerTokenThemes } from '@visactor/vseed'
const DATASET = [
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 24,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 24,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 40,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 40,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 50,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 50,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2022',
},
]
export default () => {
const [themes, setThemes] = useState({})
const [themeKey, setThemeKey] = useState('')
useEffect(() => {
fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json')
.then((r) => r.json())
.then((remote) => {
const registry = {}
Object.entries(remote).forEach(([key, value]) => {
const colors = value?.colors || []
registry[key] = {
baseTheme: 'dark',
colorScheme: colors.length >= 2 ? colors : [colors[0] || '#00D5FF', '#227BFF'],
linearColorScheme: [colors[0] || '#003B73', colors[1] || '#00D5FF'],
textPrimary: '#EAF7FF',
textSecondary: '#8FC7FF',
borderColor: 'rgba(82, 191, 255, 0.28)',
surfaceColor: '#071A33',
tooltipBackgroundColor: 'rgba(5, 18, 38, 0.92)',
axisGridColor: 'rgba(82, 191, 255, 0.18)',
accentColor: colors[0] || '#00D5FF',
}
})
registerTokenThemes(registry, { ensureRegisterAll: false })
setThemes(remote)
setThemeKey(Object.keys(remote)[0] || '')
})
.catch(() => {})
}, [])
if (!themeKey) return null
const vseedConfig = {
theme: themeKey,
chartType: 'pie',
dataset: DATASET,
dimensions: [{ id: 'HqlYadRdHJ5c', alias: 'Category' }],
measures: [{ id: 'Tn97A7q0XVDq', alias: 'Sales' }],
label: { enable: false },
animation: {
enable: true,
params: {
appear: { enable: true, effects: ['radial'], ease: 'linear', duration: 1 },
loop: { enable: true, interval: 2, loop: { enable: true, effects: ['relocate'], ease: 'linear', duration: 1 } },
},
},
}
return (
<div style={{ padding: 16, background: '#061A33' }}>
<select
value={themeKey}
onChange={(e) => setThemeKey(e.target.value)}
style={{
marginBottom: 12,
color: '#EAF7FF',
background: 'rgba(0, 213, 255, 0.18)',
border: '1px solid rgba(0, 213, 255, 0.45)',
padding: '6px 12px',
}}
>
{Object.entries(themes).map(([key, value]) => (
<option key={key} value={key} style={{ color: '#000' }}>
{value?.name || key}
</option>
))}
</select>
<VSeedRender vseed={vseedConfig} />
</div>
)
}#Radar-Animation
Alle Beispiele basieren auf dem Large-Screen-Theme (dunkel) und bieten eine Auswahlliste zum Wechseln zwischen verschiedenen Themes.
Themes werden geladen von: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json
#1. Eingangsanimation
Die Eingangsanimation steuert das erste Erscheinen von Radarflächen und Punkten.
#1.1 radial (vom Zentrum nach außen)
import { useEffect, useState } from 'react'
import { VSeedRender } from '@components'
import { registerTokenThemes, Builder } from '@visactor/vseed'
const THEME_URL = 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json'
const DATASET = [
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 24,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 24,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 40,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 40,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 50,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 50,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2022',
},
]
const DIMENSIONS = [{ id: 'HqlYadRdHJ5c', alias: 'Category' }]
const MEASURES = [{ id: 'Tn97A7q0XVDq', alias: 'Sales' }]
const useLargeScreenThemes = () => {
const [themes, setThemes] = useState({})
const [themeKey, setThemeKey] = useState('')
useEffect(() => {
Builder.updateSpec('radar', (spec) => ({
...spec,
point: { ...spec.point, style: { ...(spec.point && spec.point.style), lineWidth: 0, stroke: null } },
axes: [
{
orient: 'radius',
tick: { forceTickCount: 3 },
grid: { smooth: false, style: { stroke: 'rgba(255,255,255,0.15)', lineWidth: 1 } },
label: { visible: false, style: { fontFamily: 'D-DIN' } },
},
{
orient: 'angle',
sampling: false,
tick: { visible: true, style: () => ({ visible: false }) },
domainLine: { style: { visible: false } },
grid: { style: () => ({ stroke: 'rgba(255,255,255,0.15)', lineDash: [2, 1], lineWidth: 1 }) },
label: { style: { fontFamily: 'D-DIN', fill: 'rgba(255,255,255,0.65)', fontSize: 12 }, visible: true },
},
],
}))
fetch(THEME_URL)
.then((r) => r.json())
.then((remote) => {
const registry = {}
Object.entries(remote).forEach(([key, value]) => {
const colors = value?.colors || []
registry[key] = {
baseTheme: 'dark',
colorScheme: colors.length >= 2 ? colors : [colors[0] || '#00D5FF', '#227BFF'],
linearColorScheme: [colors[0] || '#003B73', colors[1] || '#00D5FF'],
textPrimary: '#EAF7FF',
textSecondary: '#8FC7FF',
borderColor: 'rgba(82, 191, 255, 0.28)',
surfaceColor: '#071A33',
tooltipBackgroundColor: 'rgba(5, 18, 38, 0.92)',
axisGridColor: 'rgba(82, 191, 255, 0.18)',
accentColor: colors[0] || '#00D5FF',
}
})
registerTokenThemes(registry, { ensureRegisterAll: false })
setThemes(remote)
setThemeKey(Object.keys(remote)[0] || '')
})
.catch(() => {})
}, [])
return { themes, themeKey, setThemeKey }
}
const ThemeSelect = ({ themes, themeKey, onChange }) => (
<select
value={themeKey}
onChange={(e) => onChange(e.target.value)}
style={{
marginBottom: 12,
color: '#EAF7FF',
background: 'rgba(0, 213, 255, 0.18)',
border: '1px solid rgba(0, 213, 255, 0.45)',
padding: '6px 12px',
}}
>
{Object.entries(themes).map(([key, value]) => (
<option key={key} value={key} style={{ color: '#000' }}>
{value?.name || key}
</option>
))}
</select>
)
export default () => {
const { themes, themeKey, setThemeKey } = useLargeScreenThemes()
if (!themeKey) return null
const vseedConfig = {
theme: themeKey,
chartType: 'radar',
dataset: DATASET,
dimensions: DIMENSIONS,
measures: MEASURES,
label: { enable: false },
animation: {
enable: true,
params: { appear: { enable: true, effects: ['radial'], ease: 'circInOut', duration: 1 } },
},
}
return (
<div style={{ padding: 16, background: '#061A33' }}>
<ThemeSelect themes={themes} themeKey={themeKey} onChange={setThemeKey} />
<VSeedRender vseed={vseedConfig} />
</div>
)
}#1.2 scale (Skalierung)
import { useEffect, useState } from 'react'
import { VSeedRender } from '@components'
import { registerTokenThemes, Builder } from '@visactor/vseed'
const DATASET = [
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 24,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 24,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 40,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 40,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 50,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 50,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2022',
},
]
export default () => {
const [themes, setThemes] = useState({})
const [themeKey, setThemeKey] = useState('')
useEffect(() => {
Builder.updateSpec('radar', (spec) => ({
...spec,
point: { ...spec.point, style: { ...(spec.point && spec.point.style), lineWidth: 0, stroke: null } },
axes: [
{
orient: 'radius',
tick: { forceTickCount: 3 },
grid: { smooth: false, style: { stroke: 'rgba(255,255,255,0.15)', lineWidth: 1 } },
label: { visible: false, style: { fontFamily: 'D-DIN' } },
},
{
orient: 'angle',
sampling: false,
tick: { visible: true, style: () => ({ visible: false }) },
domainLine: { style: { visible: false } },
grid: { style: () => ({ stroke: 'rgba(255,255,255,0.15)', lineDash: [2, 1], lineWidth: 1 }) },
label: { style: { fontFamily: 'D-DIN', fill: 'rgba(255,255,255,0.65)', fontSize: 12 }, visible: true },
},
],
}))
fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json')
.then((r) => r.json())
.then((remote) => {
const registry = {}
Object.entries(remote).forEach(([key, value]) => {
const colors = value?.colors || []
registry[key] = {
baseTheme: 'dark',
colorScheme: colors.length >= 2 ? colors : [colors[0] || '#00D5FF', '#227BFF'],
linearColorScheme: [colors[0] || '#003B73', colors[1] || '#00D5FF'],
textPrimary: '#EAF7FF',
textSecondary: '#8FC7FF',
borderColor: 'rgba(82, 191, 255, 0.28)',
surfaceColor: '#071A33',
tooltipBackgroundColor: 'rgba(5, 18, 38, 0.92)',
axisGridColor: 'rgba(82, 191, 255, 0.18)',
accentColor: colors[0] || '#00D5FF',
}
})
registerTokenThemes(registry, { ensureRegisterAll: false })
setThemes(remote)
setThemeKey(Object.keys(remote)[0] || '')
})
.catch(() => {})
}, [])
if (!themeKey) return null
const vseedConfig = {
theme: themeKey,
chartType: 'radar',
dataset: DATASET,
dimensions: [{ id: 'HqlYadRdHJ5c', alias: 'Category' }],
measures: [{ id: 'Tn97A7q0XVDq', alias: 'Sales' }],
label: { enable: false },
animation: {
enable: true,
params: { appear: { enable: true, effects: ['scale'], ease: 'circInOut', duration: 1 } },
},
}
return (
<div style={{ padding: 16, background: '#061A33' }}>
<select
value={themeKey}
onChange={(e) => setThemeKey(e.target.value)}
style={{
marginBottom: 12,
color: '#EAF7FF',
background: 'rgba(0, 213, 255, 0.18)',
border: '1px solid rgba(0, 213, 255, 0.45)',
padding: '6px 12px',
}}
>
{Object.entries(themes).map(([key, value]) => (
<option key={key} value={key} style={{ color: '#000' }}>
{value?.name || key}
</option>
))}
</select>
<VSeedRender vseed={vseedConfig} />
</div>
)
}#2. Schleifenanimation
Radar-Schleifenanimationen werden über atmosphere.effect als fortlaufende atmosphärische Bewegung ausgedrückt.
#2.1 none (Schleife) + atmosphere (ripple)
import { useEffect, useState } from 'react'
import { VSeedRender } from '@components'
import { registerTokenThemes, Builder } from '@visactor/vseed'
const DATASET = [
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 24,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 24,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 40,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 40,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 50,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 50,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2022',
},
]
export default () => {
const [themes, setThemes] = useState({})
const [themeKey, setThemeKey] = useState('')
useEffect(() => {
Builder.updateSpec('radar', (spec) => ({
...spec,
point: { ...spec.point, style: { ...(spec.point && spec.point.style), lineWidth: 0, stroke: null } },
axes: [
{
orient: 'radius',
tick: { forceTickCount: 3 },
grid: { smooth: false, style: { stroke: 'rgba(255,255,255,0.15)', lineWidth: 1 } },
label: { visible: false, style: { fontFamily: 'D-DIN' } },
},
{
orient: 'angle',
sampling: false,
tick: { visible: true, style: () => ({ visible: false }) },
domainLine: { style: { visible: false } },
grid: { style: () => ({ stroke: 'rgba(255,255,255,0.15)', lineDash: [2, 1], lineWidth: 1 }) },
label: { style: { fontFamily: 'D-DIN', fill: 'rgba(255,255,255,0.65)', fontSize: 12 }, visible: true },
},
],
}))
fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json')
.then((r) => r.json())
.then((remote) => {
const registry = {}
Object.entries(remote).forEach(([key, value]) => {
const colors = value?.colors || []
registry[key] = {
baseTheme: 'dark',
colorScheme: colors.length >= 2 ? colors : [colors[0] || '#00D5FF', '#227BFF'],
linearColorScheme: [colors[0] || '#003B73', colors[1] || '#00D5FF'],
textPrimary: '#EAF7FF',
textSecondary: '#8FC7FF',
borderColor: 'rgba(82, 191, 255, 0.28)',
surfaceColor: '#071A33',
tooltipBackgroundColor: 'rgba(5, 18, 38, 0.92)',
axisGridColor: 'rgba(82, 191, 255, 0.18)',
accentColor: colors[0] || '#00D5FF',
}
})
registerTokenThemes(registry, { ensureRegisterAll: false })
setThemes(remote)
setThemeKey(Object.keys(remote)[0] || '')
})
.catch(() => {})
}, [])
if (!themeKey) return null
const vseedConfig = {
theme: themeKey,
chartType: 'radar',
dataset: DATASET,
dimensions: [{ id: 'HqlYadRdHJ5c', alias: 'Category' }],
measures: [{ id: 'Tn97A7q0XVDq', alias: 'Sales' }],
label: { enable: false },
animation: {
enable: true,
params: {
appear: { enable: true, effects: ['radial'], ease: 'linear', duration: 1 },
loop: { enable: true, interval: 2, atmosphere: { effect: 'ripple', ease: 'linear' } },
},
},
}
return (
<div style={{ padding: 16, background: '#061A33' }}>
<select
value={themeKey}
onChange={(e) => setThemeKey(e.target.value)}
style={{
marginBottom: 12,
color: '#EAF7FF',
background: 'rgba(0, 213, 255, 0.18)',
border: '1px solid rgba(0, 213, 255, 0.45)',
padding: '6px 12px',
}}
>
{Object.entries(themes).map(([key, value]) => (
<option key={key} value={key} style={{ color: '#000' }}>
{value?.name || key}
</option>
))}
</select>
<VSeedRender vseed={vseedConfig} />
</div>
)
}#2.2 none (Schleife) + atmosphere (reveal)
import { useEffect, useState } from 'react'
import { VSeedRender } from '@components'
import { registerTokenThemes, Builder } from '@visactor/vseed'
const DATASET = [
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 24,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 24,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 40,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 40,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 50,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 50,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2022',
},
]
export default () => {
const [themes, setThemes] = useState({})
const [themeKey, setThemeKey] = useState('')
useEffect(() => {
Builder.updateSpec('radar', (spec) => ({
...spec,
point: { ...spec.point, style: { ...(spec.point && spec.point.style), lineWidth: 0, stroke: null } },
axes: [
{
orient: 'radius',
tick: { forceTickCount: 3 },
grid: { smooth: false, style: { stroke: 'rgba(255,255,255,0.15)', lineWidth: 1 } },
label: { visible: false, style: { fontFamily: 'D-DIN' } },
},
{
orient: 'angle',
sampling: false,
tick: { visible: true, style: () => ({ visible: false }) },
domainLine: { style: { visible: false } },
grid: { style: () => ({ stroke: 'rgba(255,255,255,0.15)', lineDash: [2, 1], lineWidth: 1 }) },
label: { style: { fontFamily: 'D-DIN', fill: 'rgba(255,255,255,0.65)', fontSize: 12 }, visible: true },
},
],
}))
fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json')
.then((r) => r.json())
.then((remote) => {
const registry = {}
Object.entries(remote).forEach(([key, value]) => {
const colors = value?.colors || []
registry[key] = {
baseTheme: 'dark',
colorScheme: colors.length >= 2 ? colors : [colors[0] || '#00D5FF', '#227BFF'],
linearColorScheme: [colors[0] || '#003B73', colors[1] || '#00D5FF'],
textPrimary: '#EAF7FF',
textSecondary: '#8FC7FF',
borderColor: 'rgba(82, 191, 255, 0.28)',
surfaceColor: '#071A33',
tooltipBackgroundColor: 'rgba(5, 18, 38, 0.92)',
axisGridColor: 'rgba(82, 191, 255, 0.18)',
accentColor: colors[0] || '#00D5FF',
}
})
registerTokenThemes(registry, { ensureRegisterAll: false })
setThemes(remote)
setThemeKey(Object.keys(remote)[0] || '')
})
.catch(() => {})
}, [])
if (!themeKey) return null
const vseedConfig = {
theme: themeKey,
chartType: 'radar',
dataset: DATASET,
dimensions: [{ id: 'HqlYadRdHJ5c', alias: 'Category' }],
measures: [{ id: 'Tn97A7q0XVDq', alias: 'Sales' }],
label: { enable: false },
animation: {
enable: true,
params: {
appear: { enable: true, effects: ['scale'], ease: 'linear', duration: 1 },
loop: { enable: true, interval: 3, atmosphere: { effect: 'reveal', ease: 'linear' } },
},
},
}
return (
<div style={{ padding: 16, background: '#061A33' }}>
<select
value={themeKey}
onChange={(e) => setThemeKey(e.target.value)}
style={{
marginBottom: 12,
color: '#EAF7FF',
background: 'rgba(0, 213, 255, 0.18)',
border: '1px solid rgba(0, 213, 255, 0.45)',
padding: '6px 12px',
}}
>
{Object.entries(themes).map(([key, value]) => (
<option key={key} value={key} style={{ color: '#000' }}>
{value?.name || key}
</option>
))}
</select>
<VSeedRender vseed={vseedConfig} />
</div>
)
}#2.3 none (Schleife) + atmosphere (breath)
import { useEffect, useState } from 'react'
import { VSeedRender } from '@components'
import { registerTokenThemes, Builder } from '@visactor/vseed'
const DATASET = [
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 24,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 24,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 40,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 40,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 50,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 50,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2022',
},
]
export default () => {
const [themes, setThemes] = useState({})
const [themeKey, setThemeKey] = useState('')
useEffect(() => {
Builder.updateSpec('radar', (spec) => ({
...spec,
point: { ...spec.point, style: { ...(spec.point && spec.point.style), lineWidth: 0, stroke: null } },
axes: [
{
orient: 'radius',
tick: { forceTickCount: 3 },
grid: { smooth: false, style: { stroke: 'rgba(255,255,255,0.15)', lineWidth: 1 } },
label: { visible: false, style: { fontFamily: 'D-DIN' } },
},
{
orient: 'angle',
sampling: false,
tick: { visible: true, style: () => ({ visible: false }) },
domainLine: { style: { visible: false } },
grid: { style: () => ({ stroke: 'rgba(255,255,255,0.15)', lineDash: [2, 1], lineWidth: 1 }) },
label: { style: { fontFamily: 'D-DIN', fill: 'rgba(255,255,255,0.65)', fontSize: 12 }, visible: true },
},
],
}))
fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json')
.then((r) => r.json())
.then((remote) => {
const registry = {}
Object.entries(remote).forEach(([key, value]) => {
const colors = value?.colors || []
registry[key] = {
baseTheme: 'dark',
colorScheme: colors.length >= 2 ? colors : [colors[0] || '#00D5FF', '#227BFF'],
linearColorScheme: [colors[0] || '#003B73', colors[1] || '#00D5FF'],
textPrimary: '#EAF7FF',
textSecondary: '#8FC7FF',
borderColor: 'rgba(82, 191, 255, 0.28)',
surfaceColor: '#071A33',
tooltipBackgroundColor: 'rgba(5, 18, 38, 0.92)',
axisGridColor: 'rgba(82, 191, 255, 0.18)',
accentColor: colors[0] || '#00D5FF',
}
})
registerTokenThemes(registry, { ensureRegisterAll: false })
setThemes(remote)
setThemeKey(Object.keys(remote)[0] || '')
})
.catch(() => {})
}, [])
if (!themeKey) return null
const vseedConfig = {
theme: themeKey,
chartType: 'radar',
dataset: DATASET,
dimensions: [{ id: 'HqlYadRdHJ5c', alias: 'Category' }],
measures: [{ id: 'Tn97A7q0XVDq', alias: 'Sales' }],
label: { enable: false },
animation: {
enable: true,
params: {
appear: { enable: true, effects: ['scale'], ease: 'linear', duration: 1 },
loop: { enable: true, interval: 2, atmosphere: { effect: 'breath', ease: 'linear' } },
},
},
}
return (
<div style={{ padding: 16, background: '#061A33' }}>
<select
value={themeKey}
onChange={(e) => setThemeKey(e.target.value)}
style={{
marginBottom: 12,
color: '#EAF7FF',
background: 'rgba(0, 213, 255, 0.18)',
border: '1px solid rgba(0, 213, 255, 0.45)',
padding: '6px 12px',
}}
>
{Object.entries(themes).map(([key, value]) => (
<option key={key} value={key} style={{ color: '#000' }}>
{value?.name || key}
</option>
))}
</select>
<VSeedRender vseed={vseedConfig} />
</div>
)
}#Streudiagramm-Animation
Alle Beispiele basieren auf dem Large-Screen-Theme (dunkel) und bieten eine Auswahlliste zum Wechseln zwischen verschiedenen Themes.
Themes werden geladen von: https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json
#1. Eingangsanimation
Die Eingangsanimation steuert, wie Streupunkte erstmals erscheinen.
#1.1 scale (Skalierung)
import { useEffect, useState } from 'react'
import { VSeedRender } from '@components'
import { registerTokenThemes } from '@visactor/vseed'
const THEME_URL = 'https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json'
const DATASET = [
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 24,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 24,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 40,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 40,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 50,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 50,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2022',
},
]
const DIMENSIONS = [{ id: 'HqlYadRdHJ5c', alias: 'Category' }]
const MEASURES = [{ id: 'Tn97A7q0XVDq', alias: 'Sales' }]
const useLargeScreenThemes = () => {
const [themes, setThemes] = useState({})
const [themeKey, setThemeKey] = useState('')
useEffect(() => {
fetch(THEME_URL)
.then((r) => r.json())
.then((remote) => {
const registry = {}
Object.entries(remote).forEach(([key, value]) => {
const colors = value?.colors || []
registry[key] = {
baseTheme: 'dark',
colorScheme: colors.length >= 2 ? colors : [colors[0] || '#00D5FF', '#227BFF'],
linearColorScheme: [colors[0] || '#003B73', colors[1] || '#00D5FF'],
textPrimary: '#EAF7FF',
textSecondary: '#8FC7FF',
borderColor: 'rgba(82, 191, 255, 0.28)',
surfaceColor: '#071A33',
tooltipBackgroundColor: 'rgba(5, 18, 38, 0.92)',
axisGridColor: 'rgba(82, 191, 255, 0.18)',
accentColor: colors[0] || '#00D5FF',
}
})
registerTokenThemes(registry, { ensureRegisterAll: false })
setThemes(remote)
setThemeKey(Object.keys(remote)[0] || '')
})
.catch(() => {})
}, [])
return { themes, themeKey, setThemeKey }
}
const ThemeSelect = ({ themes, themeKey, onChange }) => (
<select
value={themeKey}
onChange={(e) => onChange(e.target.value)}
style={{
marginBottom: 12,
color: '#EAF7FF',
background: 'rgba(0, 213, 255, 0.18)',
border: '1px solid rgba(0, 213, 255, 0.45)',
padding: '6px 12px',
}}
>
{Object.entries(themes).map(([key, value]) => (
<option key={key} value={key} style={{ color: '#000' }}>
{value?.name || key}
</option>
))}
</select>
)
export default () => {
const { themes, themeKey, setThemeKey } = useLargeScreenThemes()
if (!themeKey) return null
const vseedConfig = {
theme: themeKey,
chartType: 'scatter',
dataset: DATASET,
dimensions: DIMENSIONS,
measures: MEASURES,
label: { enable: false },
animation: {
enable: true,
params: { appear: { enable: true, effects: ['scale'], ease: 'circInOut', duration: 1 } },
},
}
return (
<div style={{ padding: 16, background: '#061A33' }}>
<ThemeSelect themes={themes} themeKey={themeKey} onChange={setThemeKey} />
<VSeedRender vseed={vseedConfig} />
</div>
)
}#1.2 fadeIn (Einblenden)
import { useEffect, useState } from 'react'
import { VSeedRender } from '@components'
import { registerTokenThemes } from '@visactor/vseed'
const DATASET = [
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 24,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 24,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 40,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 40,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 50,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 50,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2022',
},
]
export default () => {
const [themes, setThemes] = useState({})
const [themeKey, setThemeKey] = useState('')
useEffect(() => {
fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json')
.then((r) => r.json())
.then((remote) => {
const registry = {}
Object.entries(remote).forEach(([key, value]) => {
const colors = value?.colors || []
registry[key] = {
baseTheme: 'dark',
colorScheme: colors.length >= 2 ? colors : [colors[0] || '#00D5FF', '#227BFF'],
linearColorScheme: [colors[0] || '#003B73', colors[1] || '#00D5FF'],
textPrimary: '#EAF7FF',
textSecondary: '#8FC7FF',
borderColor: 'rgba(82, 191, 255, 0.28)',
surfaceColor: '#071A33',
tooltipBackgroundColor: 'rgba(5, 18, 38, 0.92)',
axisGridColor: 'rgba(82, 191, 255, 0.18)',
accentColor: colors[0] || '#00D5FF',
}
})
registerTokenThemes(registry, { ensureRegisterAll: false })
setThemes(remote)
setThemeKey(Object.keys(remote)[0] || '')
})
.catch(() => {})
}, [])
if (!themeKey) return null
const vseedConfig = {
theme: themeKey,
chartType: 'scatter',
dataset: DATASET,
dimensions: [{ id: 'HqlYadRdHJ5c', alias: 'Category' }],
measures: [{ id: 'Tn97A7q0XVDq', alias: 'Sales' }],
label: { enable: false },
animation: {
enable: true,
params: { appear: { enable: true, effects: ['fadeIn'], ease: 'circInOut', duration: 1 } },
},
}
return (
<div style={{ padding: 16, background: '#061A33' }}>
<select
value={themeKey}
onChange={(e) => setThemeKey(e.target.value)}
style={{
marginBottom: 12,
color: '#EAF7FF',
background: 'rgba(0, 213, 255, 0.18)',
border: '1px solid rgba(0, 213, 255, 0.45)',
padding: '6px 12px',
}}
>
{Object.entries(themes).map(([key, value]) => (
<option key={key} value={key} style={{ color: '#000' }}>
{value?.name || key}
</option>
))}
</select>
<VSeedRender vseed={vseedConfig} />
</div>
)
}#2. Schleifenanimation
Schleifenanimationen für Streudiagramme werden typischerweise mit atmosphere für einen kontinuierlichen Rhythmus ausgedrückt.
#2.1 none (Schleife) + atmosphere (ripple)
import { useEffect, useState } from 'react'
import { VSeedRender } from '@components'
import { registerTokenThemes } from '@visactor/vseed'
const DATASET = [
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 24,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 24,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 40,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 40,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 50,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 50,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2022',
},
]
export default () => {
const [themes, setThemes] = useState({})
const [themeKey, setThemeKey] = useState('')
useEffect(() => {
fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json')
.then((r) => r.json())
.then((remote) => {
const registry = {}
Object.entries(remote).forEach(([key, value]) => {
const colors = value?.colors || []
registry[key] = {
baseTheme: 'dark',
colorScheme: colors.length >= 2 ? colors : [colors[0] || '#00D5FF', '#227BFF'],
linearColorScheme: [colors[0] || '#003B73', colors[1] || '#00D5FF'],
textPrimary: '#EAF7FF',
textSecondary: '#8FC7FF',
borderColor: 'rgba(82, 191, 255, 0.28)',
surfaceColor: '#071A33',
tooltipBackgroundColor: 'rgba(5, 18, 38, 0.92)',
axisGridColor: 'rgba(82, 191, 255, 0.18)',
accentColor: colors[0] || '#00D5FF',
}
})
registerTokenThemes(registry, { ensureRegisterAll: false })
setThemes(remote)
setThemeKey(Object.keys(remote)[0] || '')
})
.catch(() => {})
}, [])
if (!themeKey) return null
const vseedConfig = {
theme: themeKey,
chartType: 'scatter',
dataset: DATASET,
dimensions: [{ id: 'HqlYadRdHJ5c', alias: 'Category' }],
measures: [{ id: 'Tn97A7q0XVDq', alias: 'Sales' }],
label: { enable: false },
animation: {
enable: true,
params: {
appear: { enable: true, effects: ['scale'], ease: 'linear', duration: 1 },
loop: { enable: true, interval: 2, atmosphere: { effect: 'ripple', ease: 'linear' } },
},
},
}
return (
<div style={{ padding: 16, background: '#061A33' }}>
<select
value={themeKey}
onChange={(e) => setThemeKey(e.target.value)}
style={{
marginBottom: 12,
color: '#EAF7FF',
background: 'rgba(0, 213, 255, 0.18)',
border: '1px solid rgba(0, 213, 255, 0.45)',
padding: '6px 12px',
}}
>
{Object.entries(themes).map(([key, value]) => (
<option key={key} value={key} style={{ color: '#000' }}>
{value?.name || key}
</option>
))}
</select>
<VSeedRender vseed={vseedConfig} />
</div>
)
}#2.2 none (Schleife) + atmosphere (breath)
import { useEffect, useState } from 'react'
import { VSeedRender } from '@components'
import { registerTokenThemes } from '@visactor/vseed'
const DATASET = [
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 24,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 24,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 40,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 40,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 50,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 50,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2022',
},
]
export default () => {
const [themes, setThemes] = useState({})
const [themeKey, setThemeKey] = useState('')
useEffect(() => {
fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json')
.then((r) => r.json())
.then((remote) => {
const registry = {}
Object.entries(remote).forEach(([key, value]) => {
const colors = value?.colors || []
registry[key] = {
baseTheme: 'dark',
colorScheme: colors.length >= 2 ? colors : [colors[0] || '#00D5FF', '#227BFF'],
linearColorScheme: [colors[0] || '#003B73', colors[1] || '#00D5FF'],
textPrimary: '#EAF7FF',
textSecondary: '#8FC7FF',
borderColor: 'rgba(82, 191, 255, 0.28)',
surfaceColor: '#071A33',
tooltipBackgroundColor: 'rgba(5, 18, 38, 0.92)',
axisGridColor: 'rgba(82, 191, 255, 0.18)',
accentColor: colors[0] || '#00D5FF',
}
})
registerTokenThemes(registry, { ensureRegisterAll: false })
setThemes(remote)
setThemeKey(Object.keys(remote)[0] || '')
})
.catch(() => {})
}, [])
if (!themeKey) return null
const vseedConfig = {
theme: themeKey,
chartType: 'scatter',
dataset: DATASET,
dimensions: [{ id: 'HqlYadRdHJ5c', alias: 'Category' }],
measures: [{ id: 'Tn97A7q0XVDq', alias: 'Sales' }],
label: { enable: false },
animation: {
enable: true,
params: {
appear: { enable: true, effects: ['fadeIn'], ease: 'linear', duration: 1 },
loop: { enable: true, interval: 2, atmosphere: { effect: 'breath', ease: 'linear' } },
},
},
}
return (
<div style={{ padding: 16, background: '#061A33' }}>
<select
value={themeKey}
onChange={(e) => setThemeKey(e.target.value)}
style={{
marginBottom: 12,
color: '#EAF7FF',
background: 'rgba(0, 213, 255, 0.18)',
border: '1px solid rgba(0, 213, 255, 0.45)',
padding: '6px 12px',
}}
>
{Object.entries(themes).map(([key, value]) => (
<option key={key} value={key} style={{ color: '#000' }}>
{value?.name || key}
</option>
))}
</select>
<VSeedRender vseed={vseedConfig} />
</div>
)
}#2.3 none (Schleife) + atmosphere (reveal)
import { useEffect, useState } from 'react'
import { VSeedRender } from '@components'
import { registerTokenThemes } from '@visactor/vseed'
const DATASET = [
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 24,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Labels',
Tn97A7q0XVDq: 24,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Tables',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 40,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 40,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 20,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Storage',
Tn97A7q0XVDq: 20,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 10,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Furn',
Tn97A7q0XVDq: 10,
'7ti8XuX4kcY1': '2022',
},
{
10001: 'Sales',
10002: 50,
10003: 'Tn97A7q0XVDq',
30001: '2023',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 50,
'7ti8XuX4kcY1': '2023',
},
{
10001: 'Sales',
10002: 30,
10003: 'Tn97A7q0XVDq',
30001: '2022',
HqlYadRdHJ5c: 'Art',
Tn97A7q0XVDq: 30,
'7ti8XuX4kcY1': '2022',
},
]
export default () => {
const [themes, setThemes] = useState({})
const [themeKey, setThemeKey] = useState('')
useEffect(() => {
fetch('https://lf9-dp-fe-cms-tos.byteorg.com/obj/bit-cloud/theme.json')
.then((r) => r.json())
.then((remote) => {
const registry = {}
Object.entries(remote).forEach(([key, value]) => {
const colors = value?.colors || []
registry[key] = {
baseTheme: 'dark',
colorScheme: colors.length >= 2 ? colors : [colors[0] || '#00D5FF', '#227BFF'],
linearColorScheme: [colors[0] || '#003B73', colors[1] || '#00D5FF'],
textPrimary: '#EAF7FF',
textSecondary: '#8FC7FF',
borderColor: 'rgba(82, 191, 255, 0.28)',
surfaceColor: '#071A33',
tooltipBackgroundColor: 'rgba(5, 18, 38, 0.92)',
axisGridColor: 'rgba(82, 191, 255, 0.18)',
accentColor: colors[0] || '#00D5FF',
}
})
registerTokenThemes(registry, { ensureRegisterAll: false })
setThemes(remote)
setThemeKey(Object.keys(remote)[0] || '')
})
.catch(() => {})
}, [])
if (!themeKey) return null
const vseedConfig = {
theme: themeKey,
chartType: 'scatter',
dataset: DATASET,
dimensions: [{ id: 'HqlYadRdHJ5c', alias: 'Category' }],
measures: [{ id: 'Tn97A7q0XVDq', alias: 'Sales' }],
label: { enable: false },
animation: {
enable: true,
params: {
appear: { enable: true, effects: ['scale'], ease: 'linear', duration: 1 },
loop: { enable: true, interval: 3, atmosphere: { effect: 'reveal', ease: 'linear' } },
},
},
}
return (
<div style={{ padding: 16, background: '#061A33' }}>
<select
value={themeKey}
onChange={(e) => setThemeKey(e.target.value)}
style={{
marginBottom: 12,
color: '#EAF7FF',
background: 'rgba(0, 213, 255, 0.18)',
border: '1px solid rgba(0, 213, 255, 0.45)',
padding: '6px 12px',
}}
>
{Object.entries(themes).map(([key, value]) => (
<option key={key} value={key} style={{ color: '#000' }}>
{value?.name || key}
</option>
))}
</select>
<VSeedRender vseed={vseedConfig} />
</div>
)
}