vue-amap
Version:
275 lines (191 loc) • 5.25 kB
JavaScript
// http://a.amap.com/jsapi_demos/static/remogeo/remogeo.js
function RemoGeoLocation() {
this._remoteSvrUrl = 'https://webapi.amap.com/html/geolocate.html';
this._callbackList = [];
this._seqBase = 1;
this._frameReady = 0;
this._watchIdMap = {};
}
RemoGeoLocation.prototype = {
_getSeq: function() {
return this._seqBase++;
},
_onRrameReady: function(callback) {
if (this._frameReady === 0) {
if (!this._frameReadyList) {
this._frameReadyList = [];
}
this._frameReadyList.push(callback);
this._prepareIframe();
return;
}
callback.call(this);
},
_prepareIframe: function() {
if (this._iframeWin) {
return;
}
var ifrm = document.createElement('iframe');
ifrm.src = this._remoteSvrUrl +
(this._remoteSvrUrl.indexOf('?') > 0 ? '&' : '?');
ifrm.width = '0px';
ifrm.height = '0px';
ifrm.style.position = 'absolute';
ifrm.style.display = 'none';
ifrm.allow = 'geolocation';
var self = this;
var timeoutId = setTimeout(function() {
self._frameReady = false;
self._callbackFrameReadyList();
}, 5000);
ifrm.onload = function() {
clearTimeout(timeoutId);
self._frameReady = true;
self._callbackFrameReadyList();
ifrm.onload = null;
};
document.body.appendChild(ifrm);
this._iframeWin = ifrm.contentWindow;
window.addEventListener('message', function(e) {
if (self._remoteSvrUrl.indexOf(e['origin']) !== 0) {
return;
}
self._handleRemoteMsg(e['data']);
}, false);
},
_callbackFrameReadyList: function() {
if (this._frameReadyList) {
var list = this._frameReadyList;
this._frameReadyList = null;
for (var i = 0, len = list.length; i < len; i++) {
list[i].call(this, this._frameReady);
}
}
},
_pickCallback: function(seqNum, keepInList) {
var callbackList = this._callbackList;
for (var i = 0, len = callbackList.length; i < len; i++) {
var cbkInfo = callbackList[i];
if (seqNum === cbkInfo.seq) {
if (!keepInList) {
callbackList.splice(i, 1);
}
return cbkInfo;
}
}
},
_handleRemoteMsg: function(msg) {
var seqNum = msg['seq'];
var cbkInfo = this._pickCallback(seqNum, !!msg['notify']);
if (cbkInfo) {
cbkInfo.cbk.call(null, msg['error'], msg['result']);
} else {
console.warn('Receive remote msg: ', msg);
}
},
_postMessage: function(cmd, args, callback, seq) {
this._prepareIframe();
var msg = {
'cmd': cmd,
'args': args,
'seq': seq || this._getSeq()
};
this._callbackList.push({
cbk: callback,
seq: msg['seq']
});
this._onRrameReady(function() {
if (this._frameReady === true) {
try {
this._iframeWin.postMessage(msg, '*');
} catch (e) {
this._pickCallback(msg['seq']);
callback(e);
}
} else {
this._pickCallback(msg['seq']);
callback({
'message': 'iFrame load failed!'
});
}
});
},
'getCurrentPosition': function(succHandler, errHandler, options) {
this._postMessage('getCurrentPosition', [options], function(err, result) {
if (err) {
if (errHandler) {
errHandler(err);
}
return;
}
if (succHandler) {
succHandler(result);
}
});
},
'watchPosition': function(succHandler, errHandler, options) {
var watchKey = 'wk' + this._getSeq();
var cmdSeq = this._getSeq();
this._watchIdMap[watchKey] = {
stat: 0,
seq: cmdSeq
};
var self = this;
this._postMessage('watchPosition', [options], function(err, result) {
var id = null;
if (result) {
id = result['id'];
}
var watchInfo = self._watchIdMap[watchKey];
watchInfo.id = id;
watchInfo.stat = 1;
if (watchInfo.callbackList) {
var list = watchInfo.callbackList;
watchInfo.callbackList = null;
for (var i = 0, len = list.length; i < len; i++) {
list[i].call(self, id);
}
}
if (err) {
if (errHandler) {
errHandler(err);
}
return;
}
if (succHandler) {
succHandler(result['pos']);
}
}, cmdSeq);
return watchKey;
},
'clearWatch': function(watchKey, callback) {
if (!this._watchIdMap[watchKey]) {
callback('Id not exists: ' + watchKey);
return;
}
var watchInfo = this._watchIdMap[watchKey];
var self = this;
function clearId(id) {
self._postMessage('clearWatch', [id], function(err, result) {
if (!err) {
self._pickCallback(watchInfo.seq);
delete self._watchIdMap[watchKey];
}
if (callback) {
callback(err, result);
}
});
}
if (watchInfo.stat < 1) {
if (!watchInfo.callbackList) {
watchInfo.callbackList = [];
}
watchInfo.callbackList.push(function(id) {
clearId(id);
});
} else {
clearId(watchInfo.id);
}
}
};
export default RemoGeoLocation;