第四十六回:Transform Widget

TransformWidget是Flutter中的一个容器组件,用于对子组件进行平移、旋转、缩放和翻转操作。通过Transform的translate、rotate、scale和flip静态方法,可以实现各种变换效果。文中提供了具体的代码示例,如使用Transform对Text组件进行平移、旋转和翻转,并提示可参考上一章节的内容来实现缩放操作。


我们在上一章回中介绍了Checkbox Widget相关的内容,本章回中将介绍 Transform Widget.闲话休提,让我们一起Talk Flutter吧。

概念介绍

我们在这里说的Transform是一种容器类widget,它和Container组件类似。它可以包含其它的组件,并且对被包含的组件进行平移,旋转、翻转和缩放操作。本章回中将详细介绍它的使用方法。

其实我们在上一章回中已经使用过该组件,只是没有详细介绍而已。Checkbox有一个缺点就是无法控制自身的大小,我们可以将它放在Transform组件中,然后对它进行缩放操作,进而达到控制大小的目的。

使用方法

通常情况下使用组件时需要通过组件的构造方法来创建组件,Transform组件则不然,它提供了静态方法,通过静态方法可以创建Transform组件并且对其中的组件进行相关的操作,下面是常用的构造方法以及其功能:

  • translate方法:主要用来对被包含组件进行平移操作,通过参数offset来设置平移的距离;
  • rotate方法:主要用来对被包含组件进行旋转操作,通过参数angle来设置旋转的角度;
  • scale方法:主要用来对被包含组件进行缩放操作,通过参数scale来设置缩放的倍数;
  • flip方法:主要用来对被包含组件进行翻转操作,通过参数flipX来设置左右倒置,通过参数flipY来设置上下翻转;

这四种中方法中都有一个child属性,用来指定被包含的组件,这是容器类组件的特点。

示例代码

void Mw::initBoxWidgetWithObbData() { // === 1. 创建用于显示的 OBB 框架 actor === vtkSmartPointer<vtkPolyData> cube = createSingleColoredCube(); // 单位立方体 [-0.5,0.5] vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New(); mapper->SetInputData(cube); obbActor = vtkActor::New(); obbActor->SetMapper(mapper); obbActor->GetProperty()->SetEdgeColor(0, 1, 0); // 绿边 obbActor->GetProperty()->SetLineWidth(2); obbActor->GetProperty()->SetOpacity(0.7); pointCloudRenderer->AddActor(obbActor); // === 2. 获取 OBB 参数(来自你的 JSON)=== double pos_x = 27.19659302729935; double pos_y = -1.0806391767250558; double pos_z = 2.0502098276214245; double rot_x_rad = 0.08325045738799344; // 弧度 double rot_y_rad = -0.10858955119739604; double rot_z_rad = -0.22469717039816792; double scale_x = 46.19283650079597; // 总长度 X double scale_y = 7.944462581692713; // 总长度 Y double scale_z = 4.417756175940248; // 总长度 Z // 转换为角度(VTK 的 RotateX/Y/Z 接受角度) double rot_x_deg = vtkMath::DegreesFromRadians(rot_x_rad); double rot_y_deg = vtkMath::DegreesFromRadians(rot_y_rad); double rot_z_deg = vtkMath::DegreesFromRadians(rot_z_rad); // === 3. 构造变换:T * R * S(注意顺序!PostMultiply = 按代码顺序执行)=== vtkNew<vtkTransform> initialTransform; initialTransform->PostMultiply(); // 推荐:按调用顺序执行 initialTransform->Translate(pos_x, pos_y, pos_z); // 平移到中心 initialTransform->RotateZ(rot_z_deg); // Z 最后(内旋) initialTransform->RotateY(rot_y_deg); // Y 次之 initialTransform->RotateX(rot_x_deg); // X 最先 initialTransform->Scale(scale_x, scale_y, scale_z); // 缩放到实际尺寸 // === 4. 创建 BoxWidget 和 Representation === boxWidget = vtkBoxWidget2::New(); vtkBoxRepresentation* rep = vtkBoxRepresentation::SafeDownCast(boxWidget->GetRepresentation()); // 设置初始变换 rep->SetTransform(initialTransform); // 启用交互功能 rep->SetTranslationEnabled(true); rep->SetRotationEnabled(true); rep->SetScalingEnabled(true); // 外观样式 rep->GetOutlineProperty()->SetColor(1, 1, 0); // 黄色边框 rep->GetSelectedOutlineProperty()->SetColor(1, 0, 0); // 选中红色 rep->GetSelectedOutlineProperty()->SetLineWidth(3); // === 5. 关联到渲染窗口 === boxWidget->SetInteractor(vtkWidget->GetRenderWindow()->GetInteractor()); boxWidget->SetRepresentation(rep); // === 6. 添加同步回调:保持 obbActor 与 widget 一致 === class BoxCallback : public vtkCommand { public: static BoxCallback* New() { return new BoxCallback; } Mw* mainWindow = nullptr; vtkActor* actor = nullptr; void Execute(vtkObject*, unsigned long event, void*) override { if (!actor || !mainWindow) return; vtkBoxWidget2* w = vtkBoxWidget2::SafeDownCast(caller); vtkBoxRepresentation* r = vtkBoxRepresentation::SafeDownCast(w->GetRepresentation()); vtkTransform* t = vtkTransform::New(); r->GetTransform(t); actor->SetUserTransform(t); // 结束交互时更新投影 if (event == vtkCommand::EndInteractionEvent) { mainWindow->updateOBBProjection(); } t->Delete(); } }; BoxCallback* cb = BoxCallback::New(); cb->mainWindow = this; cb->actor = obbActor; boxWidget->AddObserver(vtkCommand::InteractionEvent, cb); boxWidget->AddObserver(vtkCommand::EndInteractionEvent, cb); cb->Delete(); // === 7. 开启 widget === boxWidget->On(); // === 8. 初始同步一次 actor 变换 === obbActor->SetUserTransform(initialTransform); // === 9. 渲染更新 === vtkWidget->GetRenderWindow()->Render(); } 这是我原本的,在这里面设置
10-26
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

talk_8

真诚赞赏,手有余香

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值