Skip to content

交互控制

包括相机控制和事件监听。相机基于 OrbitControls 实现,支持旋转、缩放、平移和触摸手势。

相机控制

vue
<script setup>
const chartOption = ref({
  series: [{ data: [120, 200, 150] }],
  xAxis3D: { data: ['A', 'B', 'C'] },
  controlSettings: {
    enableRotate: true,
    enableZoom: true,
    enablePan: true,
  },
});
</script>

控制配置

配置项类型默认值说明
enableRotatebooleantrue启用旋转
enableZoombooleantrue启用缩放
enablePanbooleantrue启用平移
minPolarAnglenumber自动垂直旋转下限(弧度)
maxPolarAnglenumber自动垂直旋转上限(弧度)
minAzimuthAnglenumber自动水平旋转下限(弧度)
maxAzimuthAnglenumber自动水平旋转上限(弧度)
fitToScreenFactornumber0.8相机适配距离系数(0-1,越大离得越远、留白越多)
cameraDirectionobject-自定义相机观察方向,y 越大视角越偏俯视,如 { x: 1, y: 1.5, z: 1 }
限制旋转角度
javascript
controlSettings: {
  minPolarAngle: Math.PI / 4,     // 最小仰角 45°
  maxPolarAngle: (Math.PI * 3) / 4, // 最大仰角 135°
  minAzimuthAngle: -Math.PI / 2,  // 水平旋转 -90°
  maxAzimuthAngle: Math.PI / 2,   // 水平旋转 +90°
}
调整初始视角
javascript
controlSettings: {
  cameraDirection: { x: 1, y: 1.5, z: 1 }, // y 越大越俯视
  fitToScreenFactor: 0.9, // 增大留白
}

事件监听

支持 Vue 声明式事件监听,详见 事件系统

vue
<template>
  <RayBar
    :option="chartOption"
    @click="handleClick"
    @mouseover="handleMouseOver"
    @mouseout="handleMouseOut"
  />
</template>

<script setup>
const handleClick = (params) => {
  console.log('点击:', params.name, params.value)
}

const handleMouseOver = (params) => {
  console.log('悬停:', params.dataIndex)
}

const handleMouseOut = (params) => {
  console.log('离开:', params.dataIndex)
}
</script>

也支持编程式监听(适用于所有 16 个语义化组件暴露的 on/off 方法):

javascript
const chartRef = ref();

// 添加监听
const handler = (params) => console.log('点击:', params);
chartRef.value?.on('click', handler);

// 移除监听
chartRef.value?.off('click', handler);

常见场景

禁用所有交互

javascript
controlSettings: {
  enableRotate: false,
  enableZoom: false,
  enablePan: false,
}

只读展示 + 手动复位

交互被禁用后,仍可通过组件暴露的 fitToScreen() 方法复位相机到最佳视角:

vue
<template>
  <div>
    <RayBar ref="chartRef" :option="chartOption" />
    <button @click="chartRef?.fitToScreen()">复位视角</button>
  </div>
</template>

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

const chartRef = ref();
const chartOption = ref({
  series: [{ data: [120, 200, 150, 80, 70, 110, 130] }],
  xAxis3D: { data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] },
  controlSettings: {
    enableRotate: false,
    enableZoom: false,
    enablePan: false,
  },
});
</script>

点击高亮

vue
<template>
  <RayBar :option="chartOption" @click="handleClick" />
</template>

<script setup>
import { ref } from 'vue';

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(`选中: ${params.name} = ${params.value}`);
};
</script>

触摸控制

RayChart 基于 OrbitControls,自动支持触摸设备:

手势操作
单指拖动旋转视角
双指捏合缩放
双指拖动平移

完整示例

vue
<template>
  <div class="chart-container">
    <RayBar
      :option="chartOption"
      @click="handleClick"
      @mouseover="handleMouseOver"
      @mouseout="handleMouseOut"
    />
    <div v-if="hoveredData" class="tooltip">
      {{ hoveredData.name }}: {{ hoveredData.value }}
    </div>
  </div>
</template>

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

const hoveredData = ref(null);

const chartOption = ref({
  series: [{ data: [120, 200, 150, 80, 70, 110, 130] }],
  xAxis3D: { data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'] },
  controlSettings: {
    enableRotate: true,
    enableZoom: true,
    enablePan: true,
    minPolarAngle: Math.PI / 6,
    maxPolarAngle: Math.PI / 2,
  },
});

const handleClick = (params) => {
  console.log('点击:', params.name, params.value);
};

const handleMouseOver = (params) => {
  hoveredData.value = params;
};

const handleMouseOut = () => {
  hoveredData.value = null;
};
</script>

<style scoped>
.chart-container {
  position: relative;
}

.tooltip {
  position: absolute;
  top: 10px;
  right: 10px;
  background: rgba(0, 0, 0, 0.8);
  color: white;
  padding: 8px 12px;
  border-radius: 4px;
  font-size: 14px;
}
</style>

性能建议

  1. 避免频繁更新 - 事件处理中避免频繁更新配置
  2. 使用防抖 - 高频事件(mousemove)处理逻辑使用防抖
  3. 合理设置范围 - 限制旋转角度范围可提升操作体验
  4. 移动端优化 - 交互速度由系统自动适配触摸设备

相关文档

基础概念

深入学习

API 参考

图表示例

在线体验