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>

自动过渡

RayChart 会自动为数据更新添加平滑过渡动画。

增量更新

大数据量场景,只更新变化部分:

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: [] }],
  xAxis3D: { type: 'value' }
})

let timer = null

onMounted(() => {
  timer = setInterval(() => {
    // 添加新数据点
    const newData = [...chartOption.value.series[0].data, Math.random() * 100]
    
    // 保持最多 50 个数据点
    if (newData.length > 50) {
      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: [] }],
  xAxis3D: { type: 'value' }
})

let ws = null

onMounted(() => {
  ws = new WebSocket('ws://localhost:8080')
  
  ws.onmessage = (event) => {
    const newValue = JSON.parse(event.data)
    
    chartOption.value = {
      ...chartOption.value,
      series: [{
        ...chartOption.value.series[0],
        data: [...chartOption.value.series[0].data, newValue]
      }]
    }
  }
})

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

动画配置

自定义更新动画:

javascript
{
  animation: {
    duration: 1000,      // 动画时长(毫秒)
    easing: 'cubicOut'   // 缓动函数
  }
}

性能优化

防抖更新

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 = 100

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: [], lineWidth: 0.3, smooth: true }],
  xAxis3D: { type: 'value' },
  yAxis3D: { type: 'value', 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 > 50) {
      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
// ✅ 限制数据点数量
const MAX_POINTS = 100

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

及时清理

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

相关文档