index.ts 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  1. if (!window) {
  2. throw Error("AMap JSAPI can only be used in Browser.");
  3. }
  4. enum LoadStatus {
  5. notload = "notload",
  6. loading = "loading",
  7. loaded = "loaded",
  8. failed = "failed",
  9. }
  10. let config = {
  11. key: "",
  12. AMap: {
  13. version: "1.4.15",
  14. plugins: [],
  15. },
  16. AMapUI: {
  17. version: "1.1",
  18. plugins: [],
  19. },
  20. Loca: {
  21. version: "1.3.2",
  22. },
  23. };
  24. let Status = {
  25. AMap: LoadStatus.notload,
  26. AMapUI: LoadStatus.notload,
  27. Loca: LoadStatus.notload,
  28. };
  29. let Callback = {
  30. AMap: [],
  31. AMapUI: [],
  32. Loca: [],
  33. };
  34. let onloadCBKs = [];
  35. const onload = function (callback) {
  36. if (typeof callback == "function") {
  37. if (Status.AMap === LoadStatus.loaded) {
  38. callback(window.AMap);
  39. return;
  40. }
  41. onloadCBKs.push(callback);
  42. }
  43. };
  44. interface LoadOption {
  45. key: string;
  46. version?: string;
  47. plugins?: string[];
  48. AMapUI?: {
  49. version?: string;
  50. plugins?: string[];
  51. };
  52. Loca?: {
  53. version?: string;
  54. };
  55. }
  56. function appendOther(option: LoadOption): Promise<any> {
  57. let pros: Promise<void>[] = [];
  58. if (option.AMapUI) {
  59. pros.push(loadAMapUI(option.AMapUI));
  60. }
  61. if (option.Loca) {
  62. pros.push(loadLoca(option.Loca));
  63. }
  64. return Promise.all(pros);
  65. }
  66. function loadAMapUI(params: { version?: string; plugins?: string[] }): Promise<void> {
  67. return new Promise((res, rej) => {
  68. const newPlugins: string[] = [];
  69. if (params.plugins) {
  70. for (var i = 0; i < params.plugins.length; i += 1) {
  71. if (config.AMapUI.plugins.indexOf(params.plugins[i]) == -1) {
  72. newPlugins.push(params.plugins[i]);
  73. }
  74. }
  75. }
  76. if (Status.AMapUI === LoadStatus.failed) {
  77. rej("前次请求 AMapUI 失败");
  78. } else if (Status.AMapUI === LoadStatus.notload) {
  79. Status.AMapUI = LoadStatus.loading;
  80. config.AMapUI.version = params.version || config.AMapUI.version;
  81. const version = config.AMapUI.version;
  82. const parentNode = document.body || document.head;
  83. const script = document.createElement("script");
  84. script.type = "text/javascript";
  85. script.src = `https://webapi.amap.com/ui/${version}/main.js`;
  86. script.onerror = (e) => {
  87. Status.AMapUI = LoadStatus.failed;
  88. rej("请求 AMapUI 失败");
  89. };
  90. script.onload = () => {
  91. Status.AMapUI = LoadStatus.loaded;
  92. if (newPlugins.length) {
  93. window.AMapUI.loadUI(newPlugins, function () {
  94. for (let i = 0, len = newPlugins.length; i < len; i++) {
  95. const path = newPlugins[i];
  96. const name = path.split("/").slice(-1)[0];
  97. window.AMapUI[name] = arguments[i];
  98. }
  99. res();
  100. while (Callback.AMapUI.length) {
  101. Callback.AMapUI.splice(0, 1)[0]();
  102. }
  103. });
  104. } else {
  105. res();
  106. while (Callback.AMapUI.length) {
  107. Callback.AMapUI.splice(0, 1)[0]();
  108. }
  109. }
  110. };
  111. parentNode.appendChild(script);
  112. } else if (Status.AMapUI === LoadStatus.loaded) {
  113. if (params.version && params.version !== config.AMapUI.version) {
  114. rej("不允许多个版本 AMapUI 混用");
  115. } else {
  116. if (newPlugins.length) {
  117. window.AMapUI.loadUI(newPlugins, function () {
  118. for (let i = 0, len = newPlugins.length; i < len; i++) {
  119. const path = newPlugins[i];
  120. const name = path.split("/").slice(-1)[0];
  121. window.AMapUI[name] = arguments[i];
  122. }
  123. res();
  124. });
  125. } else {
  126. res();
  127. }
  128. }
  129. } else {
  130. if (params.version && params.version !== config.AMapUI.version) {
  131. rej("不允许多个版本 AMapUI 混用");
  132. } else {
  133. Callback.AMapUI.push((err) => {
  134. if (err) {
  135. rej(err);
  136. } else {
  137. if (newPlugins.length) {
  138. window.AMapUI.loadUI(newPlugins, function () {
  139. for (let i = 0, len = newPlugins.length; i < len; i++) {
  140. const path = newPlugins[i];
  141. const name = path.split("/").slice(-1)[0];
  142. window.AMapUI[name] = arguments[i];
  143. }
  144. res();
  145. });
  146. } else {
  147. res();
  148. }
  149. }
  150. });
  151. }
  152. }
  153. });
  154. }
  155. function loadLoca(params: { version?: string }): Promise<void> {
  156. return new Promise((res, rej) => {
  157. if (Status.Loca === LoadStatus.failed) {
  158. rej("前次请求 Loca 失败");
  159. } else if (Status.Loca === LoadStatus.notload) {
  160. Status.Loca = LoadStatus.loading;
  161. config.Loca.version = params.version || config.Loca.version;
  162. const version = config.Loca.version;
  163. const isApiV2 = config.AMap.version.startsWith("2");
  164. const isLocaV2 = version.startsWith("2");
  165. if ((isApiV2 && !isLocaV2) || (!isApiV2 && isLocaV2)) {
  166. rej("JSAPI 与 Loca 版本不对应!!");
  167. return;
  168. }
  169. const key = config.key;
  170. const parentNode = document.body || document.head;
  171. const script = document.createElement("script");
  172. script.type = "text/javascript";
  173. script.src = `https://webapi.amap.com/loca?v=${version}&key=${key}`;
  174. script.onerror = (e) => {
  175. Status.Loca = LoadStatus.failed;
  176. rej("请求 AMapUI 失败");
  177. };
  178. script.onload = () => {
  179. Status.Loca = LoadStatus.loaded;
  180. res();
  181. while (Callback.Loca.length) {
  182. Callback.Loca.splice(0, 1)[0]();
  183. }
  184. };
  185. parentNode.appendChild(script);
  186. } else if (Status.Loca === LoadStatus.loaded) {
  187. if (params.version && params.version !== config.Loca.version) {
  188. rej("不允许多个版本 Loca 混用");
  189. } else {
  190. res();
  191. }
  192. } else {
  193. if (params.version && params.version !== config.Loca.version) {
  194. rej("不允许多个版本 Loca 混用");
  195. } else {
  196. Callback.Loca.push((err) => {
  197. if (err) {
  198. rej(err);
  199. } else {
  200. rej();
  201. }
  202. });
  203. }
  204. }
  205. });
  206. }
  207. const load = function (options: LoadOption) {
  208. return new Promise((resolve, reject) => {
  209. if (Status.AMap == LoadStatus.failed) {
  210. reject("");
  211. } else if (Status.AMap == LoadStatus.notload) {
  212. //初次加载
  213. let { key, version, plugins } = options;
  214. if (!key) {
  215. reject("请填写key");
  216. return;
  217. }
  218. if (window.AMap && location.host !== "lbs.amap.com") {
  219. reject("禁止多种API加载方式混用");
  220. }
  221. config.key = key;
  222. config.AMap.version = version || config.AMap.version;
  223. config.AMap.plugins = plugins || config.AMap.plugins;
  224. Status.AMap = LoadStatus.loading;
  225. const parentNode = document.body || document.head;
  226. window.___onAPILoaded = function (err) {
  227. delete window.___onAPILoaded;
  228. if (err) {
  229. Status.AMap = LoadStatus.failed;
  230. reject(err);
  231. } else {
  232. Status.AMap = LoadStatus.loaded;
  233. appendOther(options)
  234. .then(() => {
  235. resolve(window.AMap);
  236. })
  237. .catch(reject);
  238. while (onloadCBKs.length) {
  239. onloadCBKs.splice(0, 1)[0]();
  240. }
  241. }
  242. };
  243. const script = document.createElement("script");
  244. script.type = "text/javascript";
  245. script.src =
  246. "https://webapi.amap.com/maps?callback=___onAPILoaded&v=" +
  247. config.AMap.version +
  248. "&key=" +
  249. key +
  250. "&plugin=" +
  251. config.AMap.plugins.join(",");
  252. script.onerror = (e) => {
  253. Status.AMap = LoadStatus.failed;
  254. reject(e);
  255. };
  256. parentNode.appendChild(script);
  257. } else if (Status.AMap == LoadStatus.loaded) {
  258. //deal multi load
  259. if (options.key && options.key !== config.key) {
  260. reject("多个不一致的 key");
  261. return;
  262. }
  263. if (options.version && options.version !== config.AMap.version) {
  264. reject("不允许多个版本 JSAPI 混用");
  265. return;
  266. }
  267. const newPlugins = [];
  268. if (options.plugins) {
  269. for (var i = 0; i < options.plugins.length; i += 1) {
  270. if (config.AMap.plugins.indexOf(options.plugins[i]) == -1) {
  271. newPlugins.push(options.plugins[i]);
  272. }
  273. }
  274. }
  275. if (newPlugins.length) {
  276. window.AMap.plugin(newPlugins, () => {
  277. appendOther(options)
  278. .then(() => {
  279. resolve(window.AMap);
  280. })
  281. .catch(reject);
  282. });
  283. } else {
  284. appendOther(options)
  285. .then(() => {
  286. resolve(window.AMap);
  287. })
  288. .catch(reject);
  289. }
  290. } else {
  291. // loading
  292. if (options.key && options.key !== config.key) {
  293. reject("多个不一致的 key");
  294. return;
  295. }
  296. if (options.version && options.version !== config.AMap.version) {
  297. reject("不允许多个版本 JSAPI 混用");
  298. return;
  299. }
  300. const newPlugins = [];
  301. if (options.plugins) {
  302. for (var i = 0; i < options.plugins.length; i += 1) {
  303. if (config.AMap.plugins.indexOf(options.plugins[i]) == -1) {
  304. newPlugins.push(options.plugins[i]);
  305. }
  306. }
  307. }
  308. onload(() => {
  309. if (newPlugins.length) {
  310. window.AMap.plugin(newPlugins, () => {
  311. appendOther(options)
  312. .then(() => {
  313. resolve(window.AMap);
  314. })
  315. .catch(reject);
  316. });
  317. } else {
  318. appendOther(options)
  319. .then(() => {
  320. resolve(window.AMap);
  321. })
  322. .catch(reject);
  323. }
  324. });
  325. }
  326. });
  327. };
  328. function reset() {
  329. delete window.AMap;
  330. delete window.AMapUI;
  331. delete window.Loca;
  332. config = {
  333. key: "",
  334. AMap: {
  335. version: "1.4.15",
  336. plugins: [],
  337. },
  338. AMapUI: {
  339. version: "1.1",
  340. plugins: [],
  341. },
  342. Loca: {
  343. version: "1.3.2",
  344. },
  345. };
  346. Status = {
  347. AMap: LoadStatus.notload,
  348. AMapUI: LoadStatus.notload,
  349. Loca: LoadStatus.notload,
  350. };
  351. Callback = {
  352. AMap: [],
  353. AMapUI: [],
  354. Loca: [],
  355. };
  356. }
  357. export default { load, reset };