Appearance
事件系统
RayChart 提供了两种事件监听方式:Vue 声明式事件和命令式 API。
Vue 声明式事件(推荐)
使用 Vue 的 @ 语法监听事件,这是最符合 Vue 使用习惯的方式。
可用事件
| 事件名 | 触发时机 | 参数 |
|---|---|---|
click | 点击图表元素 | { seriesIndex, dataIndex, data, event } |
dblclick | 双击图表元素 | { seriesIndex, dataIndex, data, event } |
mouseover | 鼠标移入图表元素 | { seriesIndex, dataIndex, data, event } |
mouseout | 鼠标移出图表元素 | { seriesIndex, dataIndex, data, event } |
mousemove | 鼠标在图表上移动 | { seriesIndex, dataIndex, data, event } |
mousedown | 鼠标按下 | { seriesIndex, dataIndex, data, event } |
mouseup | 鼠标释放 | { seriesIndex, dataIndex, data, event } |
基础用法
vue
<template>
<RayBar
:option="chartOption"
@click="handleClick"
@mouseover="handleMouseOver"
@mouseout="handleMouseOut"
/>
</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 handleClick = (params) => {
console.log('Clicked:', params)
console.log('Series Index:', params.seriesIndex)
console.log('Data Index:', params.dataIndex)
console.log('Value:', params.data)
}
const handleMouseOver = (params) => {
console.log('Mouse over:', params)
}
const handleMouseOut = () => {
console.log('Mouse out')
}
</script>事件参数
所有鼠标事件都会传递以下参数:
typescript
interface EventParams {
seriesIndex: number // 系列索引
dataIndex: number // 数据点索引
data: any // 数据值
event: MouseEvent // 原始 DOM 事件
name?: string // 数据点名称(如果有)
value?: number // 数据点值(如果有)
}实际应用示例
点击高亮
vue
<template>
<RayBar :option="chartOption" @click="handleClick" />
</template>
<script setup>
import { ref } from 'vue'
import { RayBar } from 'raychart'
const selectedIndex = ref(-1)
const chartOption = ref({
series: [{
data: [120, 200, 150, 80, 70, 110, 130]
}],
xAxis3D: {
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
}
})
const handleClick = (params) => {
selectedIndex.value = params.dataIndex
console.log(`Selected: ${params.name} = ${params.value}`)
// 可以更新图表配置来高亮选中项
// chartOption.value = { ...chartOption.value, ... }
}
</script>悬停提示
vue
<template>
<div class="chart-wrapper">
<RayBar
:option="chartOption"
@mouseover="handleMouseOver"
@mouseout="handleMouseOut"
/>
<div v-if="tooltip.visible" class="custom-tooltip" :style="tooltipStyle">
<strong>{{ tooltip.name }}</strong>
<div>值: {{ tooltip.value }}</div>
</div>
</div>
</template>
<script setup>
import { ref, computed } from 'vue'
import { RayBar } from 'raychart'
const tooltip = ref({
visible: false,
name: '',
value: 0,
x: 0,
y: 0
})
const tooltipStyle = computed(() => ({
left: `${tooltip.value.x + 10}px`,
top: `${tooltip.value.y + 10}px`
}))
const chartOption = ref({
series: [{
data: [120, 200, 150, 80, 70, 110, 130]
}],
xAxis3D: {
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
}
})
const handleMouseOver = (params) => {
tooltip.value = {
visible: true,
name: params.name || `Item ${params.dataIndex}`,
value: params.value || params.data,
x: params.event.clientX,
y: params.event.clientY
}
}
const handleMouseOut = () => {
tooltip.value.visible = false
}
</script>
<style scoped>
.chart-wrapper {
position: relative;
}
.custom-tooltip {
position: fixed;
background: rgba(0, 0, 0, 0.8);
color: white;
padding: 8px 12px;
border-radius: 4px;
font-size: 14px;
pointer-events: none;
z-index: 1000;
}
</style>命令式 API(高级用法)
对于需要动态添加/移除监听器的场景,可以使用命令式 API。
方法
| 方法 | 说明 | 参数 |
|---|---|---|
on(event, handler) | 添加事件监听器 | event: 事件名, handler: 回调函数 |
once(event, handler) | 添加一次性事件监听器 | event: 事件名, handler: 回调函数 |
off(event, handler) | 移除事件监听器 | event: 事件名, handler: 回调函数 |
dispatch(event, payload) | 触发自定义事件 | event: 事件名, payload: 事件数据 |
基础用法
vue
<template>
<RayBar ref="chartRef" :option="chartOption" />
</template>
<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { RayBar } from 'raychart'
const chartRef = ref()
let unsubscribe: (() => void) | undefined
const chartOption = ref({
series: [{
data: [120, 200, 150]
}],
xAxis3D: {
data: ['A', 'B', 'C']
}
})
onMounted(() => {
// 添加监听器
unsubscribe = chartRef.value?.on('click', (payload) => {
console.log('Clicked:', payload)
})
})
onUnmounted(() => {
// 清理监听器
unsubscribe?.()
})
</script>一次性监听
javascript
// 只监听一次
chartRef.value?.once('click', (payload) => {
console.log('First click:', payload)
})移除监听器
javascript
const handler = (payload) => {
console.log('Clicked:', payload)
}
// 添加监听器
chartRef.value?.on('click', handler)
// 移除监听器
chartRef.value?.off('click', handler)自定义事件
javascript
// 触发自定义事件
chartRef.value?.dispatch('custom:event', {
data: 'custom data'
})
// 监听自定义事件
chartRef.value?.on('custom:event', (payload) => {
console.log('Custom event:', payload)
})事件冒泡
图表事件不会冒泡到 DOM 树,它们只在图表内部传播。
性能建议
1. 使用防抖
对于高频事件(如 mousemove),建议使用防抖:
vue
<script setup>
import { ref } from 'vue'
import { useDebounceFn } from '@vueuse/core'
const handleMouseMove = useDebounceFn((params) => {
console.log('Mouse move:', params)
}, 100)
</script>
<template>
<RayBar :option="chartOption" @mousemove="handleMouseMove" />
</template>2. 避免在事件处理中更新图表
javascript
// ❌ 不推荐:在事件中频繁更新图表
const handleMouseMove = (params) => {
chartOption.value = { ...chartOption.value, ... }
}
// ✅ 推荐:只更新必要的状态
const handleMouseMove = (params) => {
hoveredIndex.value = params.dataIndex
}3. 及时清理监听器
使用命令式 API 时,记得在组件卸载时清理监听器:
javascript
onUnmounted(() => {
unsubscribe?.()
})常见问题
Q: 为什么事件没有触发?
A: 检查以下几点:
- 确保图表已经渲染完成
- 确保事件名称正确(区分大小写)
- 确保图表元素可交互(没有被其他元素遮挡)
Q: 如何区分点击图表元素和点击空白区域?
A: 检查事件参数中的 seriesIndex 和 dataIndex:
javascript
const handleClick = (params) => {
if (params.seriesIndex >= 0 && params.dataIndex >= 0) {
console.log('Clicked on data point')
} else {
console.log('Clicked on empty area')
}
}Q: 声明式事件和命令式 API 可以混用吗?
A: 可以,但建议优先使用声明式事件,只在需要动态管理监听器时使用命令式 API。
