skip to content

Openlayers
OpenLayers Feature 实现对角固定拉伸

问题背景

在使用 ol-extTransform 交互时,我发现了一个不符合预期的行为:

期望行为:拖动矩形的一个角时,对角的位置应该保持固定,从对角进行拉伸

实际行为:拖动一个角时,整个矩形都以中心点为基准进行缩放,所有角都在移动

这个行为对于需要精确调整区域边界的场景(比如地图区域选择工具)来说是不友好的。

问题分析

Transform 配置选项

首先,我查看了 Transform 交互的配置选项:

new Transform({
  scale: true,
  translate: true,
  rotate: false,
  stretch: false,
  translateFeature: true,
})

初步尝试了以下几种配置组合:

  1. scale: true, stretch: false - 从中心点缩放(不符合预期)
  2. scale: false, stretch: true - 依然从中心点缩放
  3. 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 这个关键参数。这个问题提醒我们:

  1. 遇到问题时先查阅源码:文档可能不够详细,但源码不会说谎
  2. 理解参数的真正含义modifyCenter 的命名看起来是"修改中心点",但实际作用是"选择使用哪个点作为缩放中心"
  3. 测试不同的配置组合:有时候需要同时启用多个选项才能达到预期效果

现在,用户可以通过拖动矩形的角或边来精确调整区域,体验更加符合直觉。

参考资源