问题背景
在使用 ol-ext 的 Transform 交互时,我发现了一个不符合预期的行为:
期望行为:拖动矩形的一个角时,对角的位置应该保持固定,从对角进行拉伸
实际行为:拖动一个角时,整个矩形都以中心点为基准进行缩放,所有角都在移动
这个行为对于需要精确调整区域边界的场景(比如地图区域选择工具)来说是不友好的。
问题分析
Transform 配置选项
首先,我查看了 Transform 交互的配置选项:
new Transform({
scale: true,
translate: true,
rotate: false,
stretch: false,
translateFeature: true,
})
初步尝试了以下几种配置组合:
scale: true, stretch: false- 从中心点缩放(不符合预期)scale: false, stretch: true- 依然从中心点缩放scale: true, stretch: true- 依然从中心点缩放
这些配置都没有实现从对角拉伸的效果。
关键发现:modifyCenter 参数
通过查阅 ol-ext Transform 源码,我找到了关键的 modifyCenter 参数:
// 默认值
modifyCenter: (options.modifyCenter || function (e) {
return e.originalEvent.metaKey || e.originalEvent.ctrlKey
})
这个参数控制缩放/拉伸的基准点:
- 返回
false(默认不按修饰键):从中心点缩放 - 返回
true(按住 Ctrl/Meta):从对角点缩放
源码解读
在 handleDragEvent_ 方法的 scale 模式中:
let center = this.center_
if (this.get('modifyCenter')(evt)) {
// 使用对角点作为缩放中心
const extentCoordinates = this.extent_
center = extentCoordinates[(Number(this.opt_) + 2) % 4]
}
// 基于中心点计算缩放比例
const scx = (dragCoordinate[0] - center[0]) / (downCoordinate[0] - center[0])
const scy = (dragCoordinate[1] - center[1]) / (downCoordinate[1] - center[1])
关键逻辑:
opt_表示用户拖动的控制点索引(0-3,对应四个角)(opt_ + 2) % 4计算出对角点的索引- 当
modifyCenter返回true时,使用对角点作为缩放中心
解决方案
最终配置
import Transform from 'ol-ext/interaction/Transform'
this.transform = new Transform({
// 启用缩放和拉伸
scale: true,
stretch: true,
translate: true,
rotate: false,
translateFeature: true,
selection: true,
// 关键配置:始终使用对角点作为缩放中心
modifyCenter: () => true,
})
效果对比
| 操作 | 修改前 (modifyCenter: false) | 修改后 (modifyCenter: true) |
|---|---|---|
| 拖动角 | 所有角都移动(中心缩放) | 对角固定,从对角拉伸 |
| 拖动边 | 两条边都变化 | 对边固定,单向拉伸 |
| 拖动内部 | 整体平移 | 整体平移 |
总结
通过深入阅读源码,我发现了 modifyCenter 这个关键参数。这个问题提醒我们:
- 遇到问题时先查阅源码:文档可能不够详细,但源码不会说谎
- 理解参数的真正含义:
modifyCenter的命名看起来是"修改中心点",但实际作用是"选择使用哪个点作为缩放中心" - 测试不同的配置组合:有时候需要同时启用多个选项才能达到预期效果
现在,用户可以通过拖动矩形的角或边来精确调整区域,体验更加符合直觉。