VTK中的vtkFullScreenRenderWindow默认交互器Style是InteractorStyleTrackballCamera
但是这个交互器默认只能处理以下的events:
- Left Mouse: Rotate
- Left Mouse + Shift: Pan
- Left Mouse + Ctrl/Alt: Spin
- Left Mouse + Shift + Ctrl/Alt: Dolly
- Mouse Wheel: Dolly
- Multi-Touch Rotate: Rotate
- Multi-Touch Pinch: Dolly
- Multi-Touch Pan: Pan
- 3D Events: Camera Pose
由于现在的需求是左键平移 滚轮放大 右键来进行旋转 ,这就导致当前的右键事件缺失以及相应的功能事件无法完成。
所以这个时候需要进行多交互器的设计。
本章你将会学到以下知识:
- vtkFullScreenRenderWindow的源码中是用了哪一种Interactor和interactorStyle.
- 如何使用多交互器操纵器来进行有效的事件分发来处理不同的事件
- 实现移动 缩放和旋转功能
1:查看vtkFullScreenRenderWindow中的代码:
model.interactor = vtkRenderWindowInteractor.newInstance();
model.interactor.setInteractorStyle(vtkInteractorStyleTrackballCamera.newInstance());
发现这个interactor 是用的RenderWindowInteractor,interactorStyle 是用的InteractorStyleTrackballCamera
vtkRenderWindowInteractor用于获取渲染窗口上发生的鼠标,键盘,事件事件。该类提供了独立于平台的与渲染窗口进行交互的机制,包括picking 和帧速率控制。当vtkRenderWindowInteractor(事实上是他的一个子类)观察到平台的某个事件发生时,他就通过InvokeEvent()方法把该事件转换为VTK事件,而interactorStyle 就是处理这些事件的类。
2:添加多交互器收集不同的事件来做相应的处理
去interaction下面的Manipulators 下面去看有那些对应鼠标的交互器
编辑
添加图片注释,不超过 140 字(可选)
根据这些名字应该找包含CameraTrackBall中的,发现
MouseCameraTrackballPanManipulator 这个里面有个Pan 去对应的API文档看看
好家伙,直接是源码。
其他二个也是类似:
MouseCameraTrackballRotateManipulator和MouseCameraTrackballZoomManipulator
但是光有这3个交互器 如何和窗口绑定呢?继续看
这个interactorStyle 中带有Manipulator 说明是否和它有关系呢?
看源码中
function applyDefinitions(definitions, manipulatorStyle) {
manipulatorStyle.removeAllManipulators();
for (let idx = 0; idx < definitions.length; idx++) {
const definition = definitions[idx];
const instance = MANIPULTOR_TYPES[definition.type].newInstance(
definition.options
);
if (instance.isA('vtkCompositeVRManipulator')) {
manipulatorStyle.addVRManipulator(instance);
} else if (instance.isA('vtkCompositeGestureManipulator')) {
manipulatorStyle.addGestureManipulator(instance);
} else if (instance.isA('vtkCompositeKeyboardManipulator')) {
manipulatorStyle.addKeyboardManipulator(instance);
} else {
manipulatorStyle.addMouseManipulator(instance);
}
}
return true;
}
manipulatorStyle.addMouseManipulator这句话不就是可以增加其他的交互器,如是乎我有个大胆的猜测就是它了。为了验证,下面代码来实现:
本实例是介入上次的实例继续添加代码的
导入vtk 需要的类
import vtkInteractorStyleManipulator from "@/vtk.js/Interaction/Style/InteractorStyleManipulator";
import vtkMouseCameraTrackballPanManipulator from "@/vtk.js/Interaction/Manipulators/MouseCameraTrackballPanManipulator";
import vtkMouseCameraTrackballRotateManipulator from "@/vtk.js/Interaction/Manipulators/MouseCameraTrackballRotateManipulator";
import vtkMouseCameraTrackballZoomManipulator from "@/vtk.js/Interaction/Manipulators/MouseCameraTrackballZoomManipulator";
获取对应的interactor 以及设置Style
const interactorStyle = vtkInteractorStyleManipulator.newInstance();
const interator = fullScreenRenderWindow.getInteractor();
interator.setInteractorStyle(interactorStyle);
声明对应的变量和初始化
const uiComponents = {};
uiComponents["leftButton"] = {
manipName: "Pan",
};
uiComponents["rightButton"] = {
manipName: "Rotate",
};
uiComponents["scrollMiddleButton"] = {
manipName: "Zoom",
};
const selectMap = {
leftButton: { button: 1 },
middleButton: { button: 2 },
rightButton: { button: 3 },
scrollMiddleButton: { scrollEnabled: true, dragEnabled: false },
};
const manipulatorFactory = {
Pan: vtkMouseCameraTrackballPanManipulator,
Zoom: vtkMouseCameraTrackballZoomManipulator,
Rotate: vtkMouseCameraTrackballRotateManipulator,
};
注册对应的manipulator,在注册前先要remove所有的Manipulators ,防止多添加了。
function reassignManipulators(interactorStyle) {
interactorStyle.removeAllMouseManipulators();
Object.keys(uiComponents).forEach((keyName) => {
const klass = manipulatorFactory[uiComponents[keyName].manipName];
if (klass) {
const manipulator = klass.newInstance();
manipulator.setButton(selectMap[keyName].button);
if (selectMap[keyName].scrollEnabled !== undefined) {
manipulator.setScrollEnabled(selectMap[keyName].scrollEnabled);
}
if (selectMap[keyName].dragEnabled !== undefined) {
manipulator.setDragEnabled(selectMap[keyName].dragEnabled);
}
interactorStyle.addMouseManipulator(manipulator);
}
});
}
将以上函数放入以下代码前即可
reassignManipulators(interactorStyle);
const renderer = fullScreenRenderWindow.getRenderer();