mapbox-gl-draw-square.js 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. "use strict";
  2. var doubleClickZoom = {
  3. enable: function enable(ctx) {
  4. setTimeout(function () {
  5. // 首先检查我们是否有地图和一些背景信息
  6. if (!ctx.map || !ctx.map.doubleClickZoom || !ctx._ctx || !ctx._ctx.store || !ctx._ctx.store.getInitialConfigValue) return;
  7. // 现在检查初始状态是不是假(如果是这样,我们将其禁用)
  8. if (!ctx._ctx.store.getInitialConfigValue("doubleClickZoom")) return;
  9. ctx.map.doubleClickZoom.enable();
  10. }, 0);
  11. },
  12. disable: function disable(ctx) {
  13. setTimeout(function () {
  14. if (!ctx.map || !ctx.map.doubleClickZoom) return;
  15. // 在这里总是禁用,因为在某些情况下这是必要的。
  16. ctx.map.doubleClickZoom.disable();
  17. }, 0);
  18. }
  19. };
  20. var DrawSquare = {
  21. onSetup: function onSetup(opts) {
  22. var square = this.newFeature({
  23. type: "Feature",
  24. properties: {},
  25. geometry: {
  26. type: "Polygon",
  27. coordinates: [[]]
  28. }
  29. });
  30. this.addFeature(square);
  31. this.clearSelectedFeatures();
  32. doubleClickZoom.disable(this);
  33. this.updateUIClasses({mouse: "add"});
  34. this.setActionableState({
  35. trash: true
  36. });
  37. return {
  38. square: square
  39. };
  40. },
  41. // 支持移动端触摸
  42. onTap: function onTap(state, e) {
  43. // 模拟“移动鼠标”以更新要素坐标
  44. if (state.startPoint) this.onMouseMove(state, e);
  45. // 模拟onClick
  46. this.onClick(state, e);
  47. },
  48. // 每当用户点击地图时,Draw将调用`onClick`
  49. onClick: function onClick(state, e) {
  50. // 如果state.startPoint存在,则表示其第二次单击
  51. // 更改为simple_select模式
  52. if (state.startPoint && state.startPoint[0] !== e.lngLat.lng && state.startPoint[1] !== e.lngLat.lat) {
  53. this.updateUIClasses({mouse: "pointer"});
  54. this.changeMode("simple_select", {featuresId: state.square.id});
  55. }
  56. // 在第一次单击时,保存单击的点坐标作为正方形的开始
  57. state.startPoint = [e.lngLat.lng, e.lngLat.lat];
  58. },
  59. onMouseMove: function onMouseMove(state, e) {
  60. // 如果是startPoint,更新要素坐标,使用边界框概念
  61. // 使用startPoint坐标和当前鼠标位置坐标来动态计算边界框
  62. // 将经度跨度和纬度跨度的最大值作为正方形的边长,操作体验更好
  63. if (state.startPoint) {
  64. var xLength = e.lngLat.lng - state.startPoint[0];
  65. var yLength = e.lngLat.lat - state.startPoint[1];
  66. var sideLength = Math.max(Math.abs(xLength), Math.abs(yLength));
  67. var lng = state.startPoint[0] + sideLength * (xLength > 0 ? 1 : -1);
  68. var lat = state.startPoint[1] + sideLength * (yLength > 0 ? 1 : -1);
  69. state.square.updateCoordinate("0.0", state.startPoint[0], state.startPoint[1]); //minX, minY - 起点
  70. state.square.updateCoordinate("0.1", lng, state.startPoint[1]); // maxX, minY
  71. state.square.updateCoordinate("0.2", lng, lat); // maxX, maxY
  72. state.square.updateCoordinate("0.3", state.startPoint[0], lat); // minX,maxY
  73. state.square.updateCoordinate("0.4", state.startPoint[0], state.startPoint[1]); //minX,minY - 终点 (跟起点一样)
  74. }
  75. },
  76. // 每当用户在聚焦地图时点击某个键时,它将在此处发送
  77. onKeyUp: function onKeyUp(state, e) {
  78. if (e.keyCode === 27) return this.changeMode("simple_select");
  79. },
  80. onStop: function onStop(state) {
  81. doubleClickZoom.enable(this);
  82. this.updateUIClasses({mouse: "none"});
  83. this.activateUIButton();
  84. // 检查我们是否删除了此要素
  85. if (this.getFeature(state.square.id) === undefined) return;
  86. // 删除最后添加的坐标
  87. state.square.removeCoordinate("0.4");
  88. if (state.square.isValid()) {
  89. this.map.fire("draw.create", {
  90. features: [state.square.toGeoJSON()]
  91. });
  92. } else {
  93. this.deleteFeature([state.square.id], {silent: true});
  94. this.changeMode("simple_select", {}, {silent: true});
  95. }
  96. },
  97. toDisplayFeatures: function toDisplayFeatures(state, geojson, display) {
  98. var isActivePolygon = geojson.properties.id === state.square.id;
  99. geojson.properties.active = isActivePolygon ? "true" : "false";
  100. if (!isActivePolygon) return display(geojson);
  101. // 仅在具有起点的正方形时才渲染
  102. if (!state.startPoint) return;
  103. return display(geojson);
  104. },
  105. onTrash: function onTrash(state) {
  106. this.deleteFeature([state.square.id], {silent: true});
  107. this.changeMode("simple_select");
  108. }
  109. };