geo-for-http
Version:
a small tool to getCurrentPosition in http protocol
271 lines (255 loc) • 8.24 kB
JavaScript
import Promise from 'bluebird'
/**
* [geo Object will be exported]
* @type {Object}
*/
const geo = {
register: register,
getCurrentPosition: getCurrentPosition
}
const DEFAULT_APP_NAME = 'yourappname' + (+new Date())
const DEFAULT_APP_KEY = 'yourkey'
const MAP_TYPES = {
HTML5: {
type: 'h5',
map_js_url: '',
app_key: DEFAULT_APP_KEY,
app_name: DEFAULT_APP_NAME
},
QQMAP: {
type: 'qq',
app_key: 'OB4BZ-D4W3U-B7VVO-4PJWW-6TKDJ-WPB77', // official example app key, please use geo.register() to replace it to your key.
app_name: DEFAULT_APP_NAME
},
BMAP: {
type: 'baidu',
app_key: DEFAULT_APP_KEY,
app_name: DEFAULT_APP_NAME
},
AMAP: {
type: 'ali',
app_key: DEFAULT_APP_KEY,
app_name: DEFAULT_APP_NAME
},
GMAP: {
type: 'google',
app_key: DEFAULT_APP_KEY,
app_name: DEFAULT_APP_NAME
}
}
const ERROR_TYPE = {
1: 'PERMISSION_DENIED',
2: 'POSITION_UNAVAILABLE',
3: 'TIMEOUT'
}
const util = {
isHttps: window.location.protocol === 'https:',
isSupportGeo: !!window.navigator.geolocation,
isObject: function (obj) {
return Object.prototype.toString.call(obj) === '[object Object]'
},
isFunction: function (obj) {
return Object.prototype.toString.call(obj) === '[object Function]'
}
}
/**
* [cacheURL cache for maps js url]
* @type {Array}
*/
let cacheURL = []
/**
* [register appkey and appname for a Map Applicaiton]
* @param {[Object]} appInfo [description]
* @return {[type]} [description]
*/
function register (appInfo = MAP_TYPES.QQMAP) {
let mapKeys = Object.keys(MAP_TYPES)
let targetMap = mapKeys.filter((item, index) => {
return MAP_TYPES[item].type === appInfo.type
})[0]
MAP_TYPES[targetMap] = {
type: appInfo.type,
app_key: appInfo.app_key,
app_name: appInfo.app_name
}
}
/**
* [getCurrentPosition description]
* @param {[String]} mapType [valid value: 'qq'、'baidu'、'ali'、'h5']
* @param {Object} posOptions [depends on which map you choose]
* @return {[type]} [description]
*/
function getCurrentPosition (mapType = MAP_TYPES.QQMAP.type, posOptions = {}) {
if (util.isObject(mapType)) { // only 1 Object-type param passed in
posOptions = mapType
mapType = MAP_TYPES.QQMAP.type
}
return new Promise((resolve, reject) => {
if (util.isSupportGeo) {
if (mapType === MAP_TYPES.HTML5.type) {
_H5Location(successFn, errorFn, posOptions)
} else {
_useMapLocation(successFn, errorFn, posOptions, mapType)
}
} else {
_useMapLocation(successFn, errorFn, posOptions, mapType)
}
function successFn (pos) {
let position = {}
if (pos.coords) {
position = {lat: pos.coords.latitude, lng: pos.coords.longitude, maptype: MAP_TYPES.HTML5.type}
} else if (pos.point) {
position = {lat: pos.point.lat, lng: pos.point.lng, maptype: MAP_TYPES.BMAP.type}
} else if (pos.position) {
position = {lat: pos.position.lat, lng: pos.position.lng, maptype: MAP_TYPES.AMAP.type}
} else {
position = {lat: pos.lat, lng: pos.lng, maptype: MAP_TYPES.QQMAP.type}
}
resolve(position)
}
function errorFn (err) {
if (err && err.code) { // html5 PositionError
console.error('Error: Failed when call navigator.geolocation.getCurrentPosition() . (ERROR_CODE:' + err.code + ', ERROR_TYPE:' + ERROR_TYPE[err.code] + ', ERROR_MESSAGE:' + err.message + ')')
}
reject(err)
}
})
}
/**
* [_useMapLocation description]
* @param {[Function]} successFn [success callback function]
* @param {[Function]} errorFn [error callback function]
* @param {[Object]} posOptions [depends on which map you choose]
* @param {[String]} mapType [valid value: 'qq'、'baidu'、'ali'、'h5']
* @return {[type]} [description]
*/
function _useMapLocation (successFn, errorFn, posOptions, mapType) {
switch (mapType) {
case MAP_TYPES.AMAP.type:
_AMapLocation(successFn, errorFn, posOptions)
break
case MAP_TYPES.BMAP.type:
_BMapLocation(successFn, errorFn, posOptions)
break
case MAP_TYPES.QQMAP.type:
_QQMapLocation(successFn, errorFn, posOptions)
break
}
}
/**
* [_H5Location description]
* @param {[Function]} successFn [description]
* @param {[Function]} errorFn [description]
* @param {[Object]} posOptions [description]
* @return {[type]} [description]
*/
function _H5Location (successFn, errorFn, posOptions) {
window.navigator.geolocation.getCurrentPosition(successFn, errorFn, posOptions)
}
/**
* [_AMapLocation description]
* @param {[Function]} successFn [description]
* @param {[Function]} errorFn [description]
* @param {[Object]} posOptions [description]
* @return {[type]} [description]
*/
function _AMapLocation (successFn, errorFn, posOptions) {
// http://lbs.amap.com/api/javascript-api/reference/location/
_getScript('//webapi.amap.com/maps?v=1.3&key=' + MAP_TYPES.AMAP.app_key)
.then(() => {
const aMapWrapId = 'geo-everywhere-amap'
let map, geolocation
createAMap(() => {
// instantiate a AMap instance
map = new window.AMap.Map(aMapWrapId)
map.plugin('AMap.Geolocation', () => {
geolocation = new window.AMap.Geolocation({})
geolocation.getCurrentPosition(onComplete)
})
// callback of getCurrentPosition
function onComplete (status, result) {
if (status === 'complete') {
successFn(result)
} else {
errorFn(status)
}
}
})
// Amap need a real map DOM to use AMap.Geolocation plugin
function createAMap (next) {
let container = document.createElement('div')
container.id = aMapWrapId
container.style.display = 'none'
document.body.appendChild(container)
util.isFunction(next) && next()
}
})
}
/**
* [_BMapLocation description]
* @param {[Function]} successFn [description]
* @param {[Function]} errorFn [description]
* @param {[Object]} posOptions [description]
* @return {[type]} [description]
*/
function _BMapLocation (successFn, errorFn, posOptions) {
// http://developer.baidu.com/map/reference/index.php?title=Class:%E6%9C%8D%E5%8A%A1%E7%B1%BB/Geolocation
_getScript('//api.map.baidu.com/getscript?v=2.0&ak=' + MAP_TYPES.BMAP.app_key + '&services=&t=' + (+new Date()))
.then(() => {
let geolocation = new window.BMap.Geolocation()
geolocation.getCurrentPosition(function (pos) {
if (this.getStatus() === window.BMAP_STATUS_SUCCESS) {
successFn(pos)
} else {
errorFn(this.getStatus())
}
}, posOptions)
})
}
/**
* [_QQMapLocation description]
* @param {[Function]} successFn [description]
* @param {[Function]} errorFn [description]
* @param {[Object]} posOptions [description]
* @return {[type]} [description]
*/
function _QQMapLocation (successFn, errorFn, posOptions) {
// http://lbs.qq.com/tool/component-geolocation.html
_getScript(`//apis.map.qq.com/tools/geolocation/min?key=${MAP_TYPES.QQMAP.app_key}&referer=${MAP_TYPES.QQMAP.app_name}`)
.then(() => {
let geolocation = new window.qq.maps.Geolocation(MAP_TYPES.QQMAP.app_key, MAP_TYPES.QQMAP.app_name)
geolocation.getLocation(successFn, errorFn, posOptions)
})
}
/**
* [_getScript description]
* @param {[String]} mapJsUrl [map js url]
* @return {[type]} [description]
*/
function _getScript (mapJsUrl) {
return new Promise((resolve, reject) => {
for (let url of cacheURL) { // if has cache url, resolve directly
if (url === mapJsUrl) {
resolve()
return false
}
}
let sc = document.createElement('script')
sc.type = 'text/javascript'
sc.src = mapJsUrl
sc.onload = sc.onreadystatechange = function () {
if (!this.readyState || /^(loaded|complete)$/.test(this.readyState)) {
resolve()
sc.onload = sc.onreadystatechange = null
cacheURL.push(mapJsUrl)
}
}
sc.onerror = function (err) {
reject(err)
sc.onerror = null
}
document.body.appendChild(sc)
})
}
export default geo
module.exports = geo