#数据分页
#基础示例
通过配置 page 属性,可以指定图表展示特定维度值的数据。
field: 分页字段。currentValue: 当前展示的值。
Loading...
#自定义播放器
通过 page 属性结合 React 状态管理,可以实现自定义的播放器控制。
import { useRef, useEffect, useState, memo } from 'react'
import VChart from '@visactor/vchart'
import { ListTable, PivotTable } from '@visactor/vtable'
import { registerAll, VSeed, Builder, isTable, isPivotTable } from '@visactor/vseed'
registerAll()
const Demo = memo(() => {
const ref = useRef<HTMLDivElement>(null)
const vseed = {
chartType: 'table',
page: {
field: 'province',
currentValue: '浙江',
},
label: {
enable: false,
},
sort: {
order: 'asc',
orderBy: 'customer_type',
},
dataset: [
{
sales: 147841.624,
profit: -47982.53600000001,
province: '浙江',
customer_type: '公司',
},
{
sales: 219726.89199999993,
profit: -44532.76799999998,
province: '四川',
customer_type: '消费者',
},
{
sales: 198200.26799999998,
profit: -27816.15199999998,
province: '江苏',
customer_type: '公司',
},
{
sales: 672289.4079999998,
profit: 165998.4480000001,
province: '广东',
customer_type: '消费者',
},
{
sales: 140259.67200000002,
profit: 34161.93199999999,
province: '江西',
customer_type: '消费者',
},
{
sales: 53158.33599999999,
profit: 9246.916000000001,
province: '陕西',
customer_type: '小型企业',
},
{
sales: 561529.15,
profit: 122722.38999999993,
province: '黑龙江',
customer_type: '消费者',
},
{
sales: 687618.1200000003,
profit: 176467.61999999988,
province: '山东',
customer_type: '消费者',
},
{
sales: 297415.048,
profit: 62825.02799999997,
province: '上海',
customer_type: '消费者',
},
{
sales: 289444.81999999983,
profit: 67988.76000000001,
province: '河北',
customer_type: '公司',
},
{
sales: 208516.56000000008,
profit: 56162.54000000002,
province: '福建',
customer_type: '公司',
},
{
sales: 342357.0219999997,
profit: 75962.082,
province: '安徽',
customer_type: '消费者',
},
{
sales: 43096.76,
profit: -6335.840000000001,
province: '甘肃',
customer_type: '公司',
},
{
sales: 130678.85599999997,
profit: -25424.084,
province: '江苏',
customer_type: '小型企业',
},
{
sales: 66693.92799999999,
profit: 4316.368,
province: '江西',
customer_type: '小型企业',
},
{
sales: 122349.24800000005,
profit: -35107.212000000014,
province: '四川',
customer_type: '公司',
},
{
sales: 358227.28899999993,
profit: 80145.28899999998,
province: '吉林',
customer_type: '消费者',
},
{
sales: 404229.16799999995,
profit: -81843.41200000001,
province: '辽宁',
customer_type: '消费者',
},
{
sales: 258096.46800000005,
profit: -47849.45200000001,
province: '湖北',
customer_type: '公司',
},
{
sales: 137146.40800000002,
profit: 32675.887999999995,
province: '陕西',
customer_type: '公司',
},
{
sales: 512082.96300000005,
profit: 114809.02300000003,
province: '广东',
customer_type: '公司',
},
{
sales: 388299.3240000001,
profit: 86599.32400000001,
province: '河南',
customer_type: '消费者',
},
{
sales: 500182.6760000004,
profit: 118908.49600000009,
province: '山东',
customer_type: '公司',
},
{
sales: 341513.8649999998,
profit: 77265.68500000007,
province: '湖南',
customer_type: '消费者',
},
{
sales: 233123.22600000008,
profit: 51707.02599999998,
province: '黑龙江',
customer_type: '小型企业',
},
{
sales: 69576.92000000001,
profit: 15303.259999999997,
province: '北京',
customer_type: '小型企业',
},
{
sales: 138525.23999999996,
profit: 19478.75999999999,
province: '重庆',
customer_type: '公司',
},
{
sales: 228866.23199999996,
profit: -57701.16799999997,
province: '浙江',
customer_type: '消费者',
},
{
sales: 267383.42399999994,
profit: 63891.883999999984,
province: '陕西',
customer_type: '消费者',
},
{
sales: 30375.100000000002,
profit: 9328.76,
province: '江西',
customer_type: '公司',
},
{
sales: 152763.212,
profit: -24982.747999999985,
province: '辽宁',
customer_type: '小型企业',
},
{
sales: 16596.86,
profit: 6437.62,
province: '青海',
customer_type: '公司',
},
{
sales: 318756.3960000001,
profit: -76162.74400000002,
province: '湖北',
customer_type: '消费者',
},
{
sales: 321088.0960000001,
profit: -54362.78400000001,
province: '江苏',
customer_type: '消费者',
},
{
sales: 56745.91999999999,
profit: 17817.94,
province: '广西',
customer_type: '公司',
},
{
sales: 269754.072,
profit: 73708.29200000002,
province: '福建',
customer_type: '消费者',
},
{
sales: 69766.20000000001,
profit: 16662.379999999994,
province: '天津',
customer_type: '小型企业',
},
{
sales: 133490.00000000006,
profit: 33141.5,
province: '北京',
customer_type: '公司',
},
{
sales: 237066.52900000004,
profit: 61232.829000000005,
province: '河南',
customer_type: '公司',
},
{
sales: 268557.1419999999,
profit: 57187.522000000026,
province: '广东',
customer_type: '小型企业',
},
{
sales: 173732.24400000004,
profit: 33409.54399999998,
province: '重庆',
customer_type: '消费者',
},
{
sales: 101922.43600000003,
profit: -28635.124000000014,
province: '甘肃',
customer_type: '消费者',
},
{
sales: 234209.42999999996,
profit: 44159.009999999995,
province: '湖南',
customer_type: '公司',
},
{
sales: 75400.38800000004,
profit: -26045.291999999994,
province: '浙江',
customer_type: '小型企业',
},
{
sales: 147192.89200000005,
profit: 34970.151999999995,
province: '云南',
customer_type: '公司',
},
{
sales: 98213.52799999998,
profit: 24624.348000000005,
province: '海南',
customer_type: '消费者',
},
{
sales: 384148.78599999996,
profit: 82742.646,
province: '黑龙江',
customer_type: '公司',
},
{
sales: 153845.93,
profit: 27573.070000000003,
province: '天津',
customer_type: '公司',
},
{
sales: 45618.35599999999,
profit: 7013.075999999999,
province: '贵州',
customer_type: '消费者',
},
{
sales: 398982.1920000001,
profit: 90086.89200000008,
province: '山东',
customer_type: '小型企业',
},
{
sales: 145116.685,
profit: 35448.245,
province: '吉林',
customer_type: '公司',
},
{
sales: 172408.21500000003,
profit: 46269.89500000002,
province: '山西',
customer_type: '公司',
},
{
sales: 305577.356,
profit: -61212.56400000002,
province: '辽宁',
customer_type: '公司',
},
{
sales: 62222.132,
profit: -14090.607999999997,
province: '内蒙古',
customer_type: '小型企业',
},
{
sales: 348074.51000000007,
profit: 67881.59,
province: '河北',
customer_type: '消费者',
},
{
sales: 55580.50399999998,
profit: -8528.016000000001,
province: '内蒙古',
customer_type: '公司',
},
{
sales: 34250.832,
profit: -7711.228,
province: '甘肃',
customer_type: '小型企业',
},
{
sales: 228208.94599999997,
profit: 51696.526000000005,
province: '河南',
customer_type: '小型企业',
},
{
sales: 155650.3759999999,
profit: -35089.26399999998,
province: '内蒙古',
customer_type: '消费者',
},
{
sales: 165429.18000000002,
profit: 37820.3,
province: '安徽',
customer_type: '公司',
},
{
sales: 206080.28000000006,
profit: 43517.18000000003,
province: '北京',
customer_type: '消费者',
},
{
sales: 80865.12,
profit: 18863.040000000005,
province: '上海',
customer_type: '小型企业',
},
{
sales: 185693.78799999994,
profit: 46341.98800000001,
province: '云南',
customer_type: '消费者',
},
{
sales: 326294.49999999994,
profit: 73468.64,
province: '天津',
customer_type: '消费者',
},
{
sales: 284908.2529999999,
profit: 58712.913,
province: '广西',
customer_type: '消费者',
},
{
sales: 121178.98800000001,
profit: 35246.42799999999,
province: '安徽',
customer_type: '小型企业',
},
{
sales: 35999.656,
profit: 8193.416,
province: '广西',
customer_type: '小型企业',
},
{
sales: 58801.45600000001,
profit: -9847.544,
province: '四川',
customer_type: '小型企业',
},
{
sales: 147718.91400000002,
profit: 35311.234,
province: '湖南',
customer_type: '小型企业',
},
{
sales: 48688.863999999994,
profit: 8323.784,
province: '贵州',
customer_type: '公司',
},
{
sales: 184330.89500000008,
profit: 42236.63499999996,
province: '山西',
customer_type: '消费者',
},
{
sales: 136852.597,
profit: 37464.636999999995,
province: '吉林',
customer_type: '小型企业',
},
{
sales: 14852.32,
profit: 3642.3799999999997,
province: '宁夏',
customer_type: '小型企业',
},
{
sales: 49504.44799999999,
profit: 11543.447999999995,
province: '重庆',
customer_type: '小型企业',
},
{
sales: 46722.63399999998,
profit: 9672.054,
province: '海南',
customer_type: '公司',
},
{
sales: 45107.46800000001,
profit: -8020.152000000001,
province: '湖北',
customer_type: '小型企业',
},
{
sales: 153396.07500000007,
profit: 36161.33499999999,
province: '河北',
customer_type: '小型企业',
},
{
sales: 15298.052,
profit: 953.7920000000001,
province: '宁夏',
customer_type: '消费者',
},
{
sales: 204170.39999999994,
profit: 39962.01999999999,
province: '上海',
customer_type: '公司',
},
{
sales: 13834.380000000001,
profit: 3661.5600000000004,
province: '贵州',
customer_type: '小型企业',
},
{
sales: 28647.528000000002,
profit: 7371.448,
province: '新疆',
customer_type: '公司',
},
{
sales: 67139.66,
profit: 18556.860000000004,
province: '山西',
customer_type: '小型企业',
},
{
sales: 24320.681,
profit: 5425.721,
province: '海南',
customer_type: '小型企业',
},
{
sales: 68632.9,
profit: 12730.899999999996,
province: '福建',
customer_type: '小型企业',
},
{
sales: 28039.088,
profit: 5327.028000000001,
province: '云南',
customer_type: '小型企业',
},
{
sales: 40187.67199999999,
profit: 6972.952,
province: '新疆',
customer_type: '消费者',
},
{
sales: 27970.628,
profit: 3941.448000000001,
province: '宁夏',
customer_type: '公司',
},
{
sales: 6487.599999999999,
profit: 699.58,
province: '西藏自治区',
customer_type: '消费者',
},
{
sales: 33266.520000000004,
profit: 5839.68,
province: '青海',
customer_type: '消费者',
},
{
sales: 3326.8199999999997,
profit: 563.22,
province: '西藏自治区',
customer_type: '公司',
},
{
sales: 1261.82,
profit: 261.66,
province: '新疆',
customer_type: '小型企业',
},
{
sales: 200.76,
profit: 3.78,
province: '西藏自治区',
customer_type: '小型企业',
},
],
theme: 'light',
}
const order = Array.from(new Set(vseed.dataset.map((d) => d[vseed?.page.field])))
// 播放器状态
const [currentIndex, setCurrentIndex] = useState(() => {
const idx = order.indexOf(vseed?.page?.currentValue)
return idx === -1 ? 0 : idx
})
const [current, setCurrent] = useState(order[currentIndex])
const [isPlaying, setIsPlaying] = useState(false)
// 同步 current 值
useEffect(() => {
setCurrent(order[currentIndex])
}, [currentIndex])
// 自动播放逻辑
useEffect(() => {
let timer: number
if (isPlaying) {
timer = window.setInterval(() => {
setCurrentIndex((prev) => (prev + 1) % order.length)
}, 1000)
}
return () => clearInterval(timer)
}, [isPlaying, order.length])
// 事件处理
const handlePrev = () => setCurrentIndex((prev) => (prev - 1 + order.length) % order.length)
const handleNext = () => setCurrentIndex((prev) => (prev + 1) % order.length)
const togglePlay = () => setIsPlaying(!isPlaying)
const tableRef = useRef(null)
const chartRef = useRef(null)
useEffect(() => {
if (!ref.current) {
return
}
const seed: VSeed = {
...vseed,
page: {
...(vseed?.page || {}),
currentValue: current,
},
}
const builder = Builder.from(seed)
const spec = builder.build()
console.log(spec)
if (isTable(seed)) {
if (tableRef.current) {
tableRef.current.updateOption(spec)
} else {
tableRef.current = new ListTable(ref.current, spec)
}
} else if (isPivotTable(seed)) {
if (tableRef.current) {
tableRef.current.updateOption(spec)
} else {
tableRef.current = new PivotTable(ref.current, spec)
}
} else {
if (chartRef.current) {
chartRef.current.updateSpec(spec)
} else {
chartRef.current = new VChart(spec, { dom: ref.current })
chartRef.current.renderSync()
}
}
}, [current])
const btnStyle = {
border: '1px solid #e2e8f0',
background: '#fff',
borderRadius: '6px',
height: '32px',
padding: '0 12px',
cursor: 'pointer',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: '14px',
transition: 'all 0.2s',
color: '#333',
}
const iconStyle = {
width: 16,
height: 16,
fill: 'currentColor',
}
return (
<div style={{ fontFamily: 'sans-serif' }}>
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: 12,
marginBottom: 16,
padding: 16,
border: '1px solid #eee',
borderRadius: 8,
background: '#f8fafc',
}}
>
{/* 第一行:播放控制 */}
<div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
<button onClick={handlePrev} style={btnStyle} title="Previous">
<svg viewBox="0 0 24 24" style={iconStyle}>
<path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z" />
</svg>
</button>
<select
style={{
flex: 1,
height: '32px',
border: '1px solid #e2e8f0',
borderRadius: '6px',
padding: '0 8px',
outline: 'none',
}}
value={currentIndex}
onChange={(e) => setCurrentIndex(Number(e.target.value))}
>
{order.map((d, i) => (
<option key={i} value={i}>
{d}
</option>
))}
</select>
<button onClick={handleNext} style={btnStyle} title="Next">
<svg viewBox="0 0 24 24" style={iconStyle}>
<path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z" />
</svg>
</button>
<button onClick={togglePlay} style={{ ...btnStyle, minWidth: 80 }} title={isPlaying ? 'Pause' : 'Play'}>
{isPlaying ? (
<>
<svg viewBox="0 0 24 24" style={{ ...iconStyle, marginRight: 4 }}>
<path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z" />
</svg>
Pause
</>
) : (
<>
<svg viewBox="0 0 24 24" style={{ ...iconStyle, marginRight: 4 }}>
<path d="M8 5v14l11-7z" />
</svg>
Play
</>
)}
</button>
</div>
{/* 第二行:进度条 */}
<div style={{ display: 'flex', alignItems: 'center' }}>
<input
type="range"
min="0"
max={order.length - 1}
value={currentIndex}
onChange={(e) => setCurrentIndex(Number(e.target.value))}
style={{ width: '100%', cursor: 'pointer' }}
/>
</div>
</div>
<div ref={ref} style={{ height: 260, width: '100%' }} />
</div>
)
})
export default Demo