index.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. import { __awaiter } from "tslib";
  2. import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
  3. import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState, } from "react";
  4. import { Amap, Marker } from "@amap/amap-react";
  5. import { AutoComplete, Button, Input, Space, message } from "antd";
  6. import { debounce, isNumber } from "lodash";
  7. import { DageMapGeocoder } from "./plugins";
  8. import { getAmapInputTips } from "./utils";
  9. export const DageMap = forwardRef(({ latitude, longitude, disabled, address, city, onlyCityArea, inputTipsApi, outCityAreaMessage, onAddressChange, onLngLatChange, onMapComplete, onError, }, ref) => {
  10. const mapRef = useRef();
  11. /** 是否禁用坐标解析地址 */
  12. const geocoderDisabled = useRef(false);
  13. const [loaded, setLoaded] = useState(false);
  14. /** 上一个坐标地址 */
  15. const prevPosition = useRef([longitude, latitude]);
  16. /** 输入框经度 */
  17. const [lng, setLng] = useState(longitude);
  18. /** 输入框纬度 */
  19. const [lat, setLat] = useState(latitude);
  20. const [options, setOptions] = useState([]);
  21. const [position, setPosition] = useState([longitude, latitude]);
  22. useImperativeHandle(ref, () => ({
  23. mapRef: mapRef.current,
  24. }));
  25. useEffect(() => {
  26. if (longitude === lng && latitude === lat)
  27. return;
  28. // 外部改动经纬度,不需要解析地址
  29. geocoderDisabled.current = true;
  30. setPosition([longitude, latitude]);
  31. setLat(latitude);
  32. setLng(longitude);
  33. prevPosition.current = [longitude, latitude];
  34. }, [longitude, latitude]);
  35. const handleSearch = useCallback(debounce((value) => __awaiter(void 0, void 0, void 0, function* () {
  36. if (!value) {
  37. setOptions([]);
  38. return;
  39. }
  40. const { tips } = yield getAmapInputTips(inputTipsApi, value, city);
  41. setOptions(tips || []);
  42. }), 500), [city]);
  43. const handleClick = useCallback((e, data) => {
  44. if (disabled)
  45. return;
  46. const { lng, lat } = data.lnglat;
  47. geocoderDisabled.current = false;
  48. setLat(lat);
  49. setLng(lng);
  50. setPosition([lng, lat]);
  51. onLngLatChange === null || onLngLatChange === void 0 ? void 0 : onLngLatChange({
  52. lat,
  53. lng,
  54. });
  55. }, [disabled, onLngLatChange]);
  56. /**
  57. * 地图初始化完成
  58. */
  59. const handleComplete = useCallback(() => {
  60. var _a;
  61. setLoaded(true);
  62. (_a = mapRef.current) === null || _a === void 0 ? void 0 : _a.setCenter([longitude, latitude], false, 1000);
  63. onMapComplete === null || onMapComplete === void 0 ? void 0 : onMapComplete();
  64. }, [longitude, latitude, onMapComplete]);
  65. const handleMarker = useCallback(debounce((e) => {
  66. const [lng, lat] = e._position;
  67. geocoderDisabled.current = false;
  68. setLat(lat);
  69. setLng(lng);
  70. onLngLatChange === null || onLngLatChange === void 0 ? void 0 : onLngLatChange({
  71. lat,
  72. lng,
  73. });
  74. setPosition(e._position);
  75. }, 200), [onLngLatChange]);
  76. const handlePosition = useCallback((long = lng, lati = lat) => {
  77. var _a;
  78. if (!long || !lati)
  79. return;
  80. onLngLatChange === null || onLngLatChange === void 0 ? void 0 : onLngLatChange({
  81. lat: lati,
  82. lng: long,
  83. });
  84. setPosition([long, lati]);
  85. (_a = mapRef.current) === null || _a === void 0 ? void 0 : _a.setCenter([long, lati], false, 1000);
  86. }, [lng, lat, onLngLatChange]);
  87. /**
  88. * 坐标搜索
  89. */
  90. const handleLngLatSearch = useCallback(() => {
  91. geocoderDisabled.current = false;
  92. handlePosition();
  93. }, [handlePosition]);
  94. const handleSelect = useCallback((val, opts) => {
  95. const [lng, lat] = opts.location.split(",").map((i) => Number(i));
  96. setLng(lng);
  97. setLat(lat);
  98. geocoderDisabled.current = true;
  99. handlePosition(lng, lat);
  100. onLngLatChange === null || onLngLatChange === void 0 ? void 0 : onLngLatChange({
  101. lat,
  102. lng,
  103. });
  104. prevPosition.current = [lng, lat];
  105. }, [handlePosition, onLngLatChange]);
  106. const handleAutoCompleteChange = useCallback((val) => {
  107. onAddressChange === null || onAddressChange === void 0 ? void 0 : onAddressChange(val);
  108. }, [onAddressChange]);
  109. const handleGeocoderAddress = (res) => {
  110. if (geocoderDisabled.current)
  111. return;
  112. if (onlyCityArea &&
  113. isNumber(city) &&
  114. !res.regeocode.addressComponent.adcode.startsWith(city.toString().substring(0, 2))) {
  115. // 超出市区范围
  116. handleOutCityAreaError();
  117. return;
  118. }
  119. onAddressChange === null || onAddressChange === void 0 ? void 0 : onAddressChange(res.regeocode.formattedAddress);
  120. prevPosition.current = [lng, lat];
  121. };
  122. const handleOutCityAreaError = () => {
  123. outCityAreaMessage && message.error(outCityAreaMessage, 2);
  124. onError === null || onError === void 0 ? void 0 : onError();
  125. setTimeout(() => {
  126. setLat(prevPosition.current[1]);
  127. setLng(prevPosition.current[0]);
  128. handlePosition(prevPosition.current[0], prevPosition.current[1]);
  129. }, 2000);
  130. };
  131. return (_jsxs(_Fragment, { children: [_jsx("div", { children: _jsx(AutoComplete, { allowClear: true, disabled: disabled, value: address, style: { width: 450 }, options: options.map((i) => (Object.assign(Object.assign({}, i), { value: i.name }))), onSearch: handleSearch, onSelect: handleSelect, onChange: handleAutoCompleteChange, children: _jsx(Input, { allowClear: true, placeholder: "\u8BF7\u8F93\u5165\u8BE6\u7EC6\u63CF\u8FF0" }) }) }), _jsxs(Space, { style: { margin: "15px 0" }, children: [_jsx(Input, { readOnly: disabled, value: lng, type: "number", placeholder: "\u8BF7\u8F93\u5165\u7ECF\u5EA6", onChange: (e) => setLng(Number(e.target.value)) }), _jsx(Input, { readOnly: disabled, value: lat, type: "number", placeholder: "\u8BF7\u8F93\u5165\u7EAC\u5EA6", onChange: (e) => setLat(Number(e.target.value)) }), !disabled && (_jsx(Button, { type: "primary", onClick: handleLngLatSearch, children: "\u67E5\u8BE2" }))] }), _jsx("div", { style: { width: 650, height: 400 }, children: _jsx(Amap, { ref: mapRef, zoom: 17, onComplete: handleComplete, onClick: handleClick, children: loaded && position ? (_jsxs(_Fragment, { children: [_jsx(Marker, { position: position, draggable: !disabled, onDragging: handleMarker }), !disabled && (_jsx(DageMapGeocoder, { city: city, position: position, onChange: handleGeocoderAddress, onError: handleOutCityAreaError }))] })) : (_jsx(_Fragment, {})) }) })] }));
  132. });
  133. export * from "./types";
  134. export * from "./utils";