Skip to content

数据更新

支持动态更新数据,实现实时图表。

响应式更新

vue
<template>
  <div>
    <RayBar :option="chartOption" />
    <button @click="updateData">更新数据</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { RayBar } from 'raychart'

const chartOption = ref({
  series: [{ data: [120, 200, 150, 80, 70, 110, 130] }],
  xAxis3D: { data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] }
})

const updateData = () => {
  chartOption.value = {
    ...chartOption.value,
    series: [{
      ...chartOption.value.series[0],
      data: [150, 230, 180, 90, 85, 120, 140]
    }]
  }
}
</script>

更新动画

数据更新会触发图表重新渲染,并播放入场动画:柱状图柱体生长、折线图管线生长、散点图逐点放大。动画时长为内置值,暂不支持配置。

更新指定字段

大数据量场景,只替换需要变化的部分,其余配置保持不变:

vue
<script setup>
const updateData = () => {
  // 只更新 series.data
  chartOption.value = {
    ...chartOption.value,
    series: [{
      ...chartOption.value.series[0],
      data: newData
    }]
  }
}
</script>

实时数据

定时更新

vue
<template>
  <RayLine :option="chartOption" />
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { RayLine } from 'raychart'

const chartOption = ref({
  series: [{ data: [] }],
  // 窗口模式:只渲染最近 20 个数据点(数据在应用层同步裁剪)
  xAxis3D: { window: { enabled: true, size: 20 } }
})

let timer = null

onMounted(() => {
  timer = setInterval(() => {
    // 添加新数据点
    const newData = [...chartOption.value.series[0].data, Math.random() * 100]
    
    // 与窗口大小保持一致(超出时移除最旧数据)
    if (newData.length > 20) {
      newData.shift()
    }
    
    chartOption.value = {
      ...chartOption.value,
      series: [{
        ...chartOption.value.series[0],
        data: newData
      }]
    }
  }, 1000)
})

onUnmounted(() => {
  if (timer) {
    clearInterval(timer)
  }
})
</script>

WebSocket 数据

vue
<template>
  <RayLine :option="chartOption" />
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { RayLine } from 'raychart'

const chartOption = ref({
  series: [{ data: [] }],
  // 窗口模式:只渲染最近 20 个数据点(数据在应用层同步裁剪)
  xAxis3D: { window: { enabled: true, size: 20 } }
})

let ws = null

onMounted(() => {
  ws = new WebSocket('ws://localhost:8080')
  
  ws.onmessage = (event) => {
    const newValue = JSON.parse(event.data)
    
    const newData = [...chartOption.value.series[0].data, Number(newValue)]
    
    // 与窗口大小保持一致(超出时移除最旧数据)
    if (newData.length > 20) {
      newData.shift()
    }
    
    chartOption.value = {
      ...chartOption.value,
      series: [{
        ...chartOption.value.series[0],
        data: newData
      }]
    }
  }
})

onUnmounted(() => {
  if (ws) {
    ws.close()
  }
})
</script>

动画配置

数据更新会触发图表重新渲染,并播放入场动画:

  • 柱状图 - 柱体生长动画
  • 折线图 - 管线从起点向终点生长
  • 散点图 - 数据点逐个放大出现

动画时长为内置值,暂不支持通过 option 配置。

性能优化

防抖更新

vue
<script setup>
import { ref } from 'vue'
import { useDebounceFn } from '@vueuse/core'
import { RayBar } from 'raychart'

const chartOption = ref({
  series: [{ data: [120, 200, 150] }],
  xAxis3D: { data: ['A', 'B', 'C'] }
})

const updateData = useDebounceFn((newData) => {
  chartOption.value = {
    ...chartOption.value,
    series: [{
      ...chartOption.value.series[0],
      data: newData
    }]
  }
}, 300)
</script>

批量更新

javascript
// ❌ 不好的做法 - 多次更新
data.forEach(item => {
  chartOption.value = { ...chartOption.value, ... }
})

// ✅ 好的做法 - 批量更新
const newData = data.map(item => item.value)
chartOption.value = {
  ...chartOption.value,
  series: [{
    ...chartOption.value.series[0],
    data: newData
  }]
}

限制数据量

javascript
const MAX_DATA_POINTS = 20  // 与 xAxis3D.window.size 保持一致

const addDataPoint = (newValue) => {
  const currentData = chartOption.value.series[0].data
  const newData = [...currentData, newValue]
  
  // 超过限制时移除最旧的数据
  if (newData.length > MAX_DATA_POINTS) {
    newData.shift()
  }
  
  chartOption.value = {
    ...chartOption.value,
    series: [{
      ...chartOption.value.series[0],
      data: newData
    }]
  }
}

完整示例

vue
<template>
  <div class="realtime-chart">
    <RayLine :option="chartOption" />
    <div class="controls">
      <button @click="startUpdate">开始</button>
      <button @click="stopUpdate">停止</button>
      <button @click="clearData">清空</button>
    </div>
  </div>
</template>

<script setup>
import { ref, onUnmounted } from 'vue'
import { RayLine } from 'raychart'

const chartOption = ref({
  series: [{ data: [], lineStyle: { width: 0.3 }, smooth: true }],
  xAxis3D: { window: { enabled: true, size: 20 } },
  yAxis3D: { min: 0, max: 100 }
})

let timer = null

const startUpdate = () => {
  if (timer) return
  
  timer = setInterval(() => {
    const newData = [...chartOption.value.series[0].data, Math.random() * 100]
    
    if (newData.length > 20) {
      newData.shift()
    }
    
    chartOption.value = {
      ...chartOption.value,
      series: [{
        ...chartOption.value.series[0],
        data: newData
      }]
    }
  }, 1000)
}

const stopUpdate = () => {
  if (timer) {
    clearInterval(timer)
    timer = null
  }
}

const clearData = () => {
  stopUpdate()
  chartOption.value = {
    ...chartOption.value,
    series: [{
      ...chartOption.value.series[0],
      data: []
    }]
  }
}

onUnmounted(() => {
  stopUpdate()
})
</script>

<style scoped>
.realtime-chart {
  padding: 20px;
}

.controls {
  margin-top: 20px;
  display: flex;
  gap: 10px;
}

button {
  padding: 8px 16px;
  border: 1px solid #ddd;
  border-radius: 4px;
  background: white;
  cursor: pointer;
}

button:hover {
  background: #f5f5f5;
}
</style>

最佳实践

合理的更新频率

javascript
// ✅ 推荐:1秒更新一次
setInterval(updateData, 1000)

// ⚠️ 谨慎:100ms 更新(高频)
setInterval(updateData, 100)

// ❌ 不推荐:10ms 更新(过于频繁)
setInterval(updateData, 10)

数据量控制

javascript
// ✅ 限制数据点数量(与 xAxis3D.window.size 保持一致)
const MAX_POINTS = 20

// ❌ 无限增长会导致性能问题和内存泄漏

及时清理

javascript
// ✅ 组件卸载时清理定时器
onUnmounted(() => {
  clearInterval(timer)
  ws?.close()
})

相关文档