index.ts 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  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 (config.AMap.version.startsWith("2.0")) {
  158. rej("Loca 暂不适配 JSAPI 2.0,请使用 1.4.15");
  159. } else if (Status.Loca === LoadStatus.failed) {
  160. rej("前次请求 Loca 失败");
  161. } else if (Status.Loca === LoadStatus.notload) {
  162. Status.Loca = LoadStatus.loading;
  163. config.Loca.version = params.version || config.Loca.version;
  164. const version = config.Loca.version;
  165. const key = config.key;
  166. const parentNode = document.body || document.head;
  167. const script = document.createElement("script");
  168. script.type = "text/javascript";
  169. script.src = `https://webapi.amap.com/loca?v=${version}&key=${key}`;
  170. script.onerror = (e) => {
  171. Status.Loca = LoadStatus.failed;
  172. rej("请求 AMapUI 失败");
  173. };
  174. script.onload = () => {
  175. Status.Loca = LoadStatus.loaded;
  176. res();
  177. while (Callback.Loca.length) {
  178. Callback.Loca.splice(0, 1)[0]();
  179. }
  180. };
  181. parentNode.appendChild(script);
  182. } else if (Status.Loca === LoadStatus.loaded) {
  183. if (params.version && params.version !== config.Loca.version) {
  184. rej("不允许多个版本 Loca 混用");
  185. } else {
  186. res();
  187. }
  188. } else {
  189. if (params.version && params.version !== config.Loca.version) {
  190. rej("不允许多个版本 Loca 混用");
  191. } else {
  192. Callback.Loca.push((err) => {
  193. if (err) {
  194. rej(err);
  195. } else {
  196. rej();
  197. }
  198. });
  199. }
  200. }
  201. });
  202. }
  203. const load = function (options: LoadOption) {
  204. return new Promise((resolve, reject) => {
  205. if (Status.AMap == LoadStatus.failed) {
  206. reject("");
  207. } else if (Status.AMap == LoadStatus.notload) {
  208. //初次加载
  209. let { key, version, plugins } = options;
  210. if (!key) {
  211. reject("请填写key");
  212. return;
  213. }
  214. if (window.AMap && location.host !== "lbs.amap.com") {
  215. reject("禁止多种API加载方式混用");
  216. }
  217. config.key = key;
  218. config.AMap.version = version || config.AMap.version;
  219. config.AMap.plugins = plugins || config.AMap.plugins;
  220. Status.AMap = LoadStatus.loading;
  221. const parentNode = document.body || document.head;
  222. window.___onAPILoaded = function (err) {
  223. delete window.___onAPILoaded;
  224. if (err) {
  225. Status.AMap = LoadStatus.failed;
  226. reject(err);
  227. } else {
  228. Status.AMap = LoadStatus.loaded;
  229. appendOther(options)
  230. .then(() => {
  231. resolve(window.AMap);
  232. })
  233. .catch(reject);
  234. while (onloadCBKs.length) {
  235. onloadCBKs.splice(0, 1)[0]();
  236. }
  237. }
  238. };
  239. const script = document.createElement("script");
  240. script.type = "text/javascript";
  241. script.src =
  242. "https://webapi.amap.com/maps?callback=___onAPILoaded&v=" +
  243. config.AMap.version +
  244. "&key=" +
  245. key +
  246. "&plugin=" +
  247. config.AMap.plugins.join(",");
  248. script.onerror = (e) => {
  249. Status.AMap = LoadStatus.failed;
  250. reject(e);
  251. };
  252. parentNode.appendChild(script);
  253. } else if (Status.AMap == LoadStatus.loaded) {
  254. //deal multi load
  255. if (options.key && options.key !== config.key) {
  256. reject("多个不一致的 key");
  257. return;
  258. }
  259. if (options.version && options.version !== config.AMap.version) {
  260. reject("不允许多个版本 JSAPI 混用");
  261. return;
  262. }
  263. const newPlugins = [];
  264. if (options.plugins) {
  265. for (var i = 0; i < options.plugins.length; i += 1) {
  266. if (config.AMap.plugins.indexOf(options.plugins[i]) == -1) {
  267. newPlugins.push(options.plugins[i]);
  268. }
  269. }
  270. }
  271. if (newPlugins.length) {
  272. window.AMap.plugin(newPlugins, () => {
  273. appendOther(options)
  274. .then(() => {
  275. resolve(window.AMap);
  276. })
  277. .catch(reject);
  278. });
  279. } else {
  280. appendOther(options)
  281. .then(() => {
  282. resolve(window.AMap);
  283. })
  284. .catch(reject);
  285. }
  286. } else {
  287. // loading
  288. if (options.key && options.key !== config.key) {
  289. reject("多个不一致的 key");
  290. return;
  291. }
  292. if (options.version && options.version !== config.AMap.version) {
  293. reject("不允许多个版本 JSAPI 混用");
  294. return;
  295. }
  296. const newPlugins = [];
  297. if (options.plugins) {
  298. for (var i = 0; i < options.plugins.length; i += 1) {
  299. if (config.AMap.plugins.indexOf(options.plugins[i]) == -1) {
  300. newPlugins.push(options.plugins[i]);
  301. }
  302. }
  303. }
  304. onload(() => {
  305. if (newPlugins.length) {
  306. window.AMap.plugin(newPlugins, () => {
  307. appendOther(options)
  308. .then(() => {
  309. resolve(window.AMap);
  310. })
  311. .catch(reject);
  312. });
  313. } else {
  314. appendOther(options)
  315. .then(() => {
  316. resolve(window.AMap);
  317. })
  318. .catch(reject);
  319. }
  320. });
  321. }
  322. });
  323. };
  324. function reset() {
  325. delete window.AMap;
  326. delete window.AMapUI;
  327. delete window.Loca;
  328. config = {
  329. key: "",
  330. AMap: {
  331. version: "1.4.15",
  332. plugins: [],
  333. },
  334. AMapUI: {
  335. version: "1.1",
  336. plugins: [],
  337. },
  338. Loca: {
  339. version: "1.3.2",
  340. },
  341. };
  342. Status = {
  343. AMap: LoadStatus.notload,
  344. AMapUI: LoadStatus.notload,
  345. Loca: LoadStatus.notload,
  346. };
  347. Callback = {
  348. AMap: [],
  349. AMapUI: [],
  350. Loca: [],
  351. };
  352. }
  353. export default { load, reset };