123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501 |
- // 引入uni-map-common公共模块
- const UniMap = require('uni-map-common');
- const configCenter = require("uni-config-center");
- // 读取配置中心地图配置
- var UniMapConfig = configCenter({ pluginId: 'uni-map' }).requireFile('config.js');
- // 本地地图配置
- var LocalMapConfig = {
- "default": "", // 默认使用的平台
- "key": {
- "qqmap": "", // 腾讯地图key
- "amap": "", // 高德地图key
- }
- }
- const db = uniCloud.database();
- const _ = db.command;
- const $ = _.aggregate;
- const opendbPoiDB = db.collection("opendb-poi");
- module.exports = {
- _before: function() {
- // 如果配置中心不存在地图配置,则使用本地地图配置
- if (!UniMapConfig) {
- UniMapConfig = LocalMapConfig;
- }
- let defaultProvider = UniMapConfig.default || "qqmap";
- let params = this.getParams();
- let {
- provider = defaultProvider
- } = params[0] || {};
- console.log('provider: ', provider)
- const key = UniMapConfig.key[provider] || LocalMapConfig.key[provider];
- if (!key) {
- throw { errCode: -1, errMsg: `请在uni-config-center/uni-map/config.js中或LocalMapConfig中配置地图供应商${provider}对应的key` };
- }
- // 初始化实例
- let uniMap = new UniMap({
- provider: provider, // 指定使用哪家地图供应商
- key: key,
- needOriginalResult: false
- });
- this.uniMap = uniMap;
- },
- _after: function(error, res) {
- if (error) {
- throw error; // 如果方法抛出错误,也直接抛出不处理
- }
- console.log("result", res.result);
- return res;
- },
- // 经纬度坐标转地址
- async location2address(data = {}) {
- let res = {};
- // 获取uniMap实例
- const uniMap = this.uniMap;
- // 调用API
- let result = await uniMap.location2address(data);
- res.result = result;
- return res;
- },
- // 地址转经纬度坐标
- async address2location(data = {}) {
- let res = {};
- // 获取uniMap实例
- const uniMap = this.uniMap;
- // 调用API
- let result = await uniMap.address2location(data);
- res.result = result;
- return res;
- },
- // 坐标系转换
- async translate(data = {}) {
- let res = {};
- // 获取uniMap实例
- const uniMap = this.uniMap;
- // 调用API
- let result = await uniMap.translate(data);
- res.result = result;
- return res;
- },
- // ip定位
- async ip2location(data = {}) {
- let res = {};
- // 获取uniMap实例
- const uniMap = this.uniMap;
- // 调用API
- let result = await uniMap.ip2location(data);
- res.result = result;
- return res;
- },
- // 输入提示
- async inputtips(data = {}) {
- let res = {};
- // 获取uniMap实例
- const uniMap = this.uniMap;
- // 调用API
- let result = await uniMap.inputtips(data);
- res.result = result;
- return res;
- },
- // 搜索
- async search(data = {}) {
- let res = {};
- // 获取uniMap实例
- const uniMap = this.uniMap;
- // 调用API
- let result = await uniMap.search(data);
- res.result = result;
- return res;
- },
- // 行政区划
- async districtSearch(data = {}) {
- let res = {};
- // 获取uniMap实例
- const uniMap = this.uniMap;
- // 调用API
- let result = await uniMap.districtSearch(data);
- res.result = result;
- return res;
- },
- // 路径规划
- async route(data = {}) {
- let res = {};
- // 获取uniMap实例
- const uniMap = this.uniMap;
- // 调用API
- let result = await uniMap.route(data);
- res.result = result;
- return res;
- },
- // 演示用 - 清空所有的测试POI
- async clearPoi(data = {}) {
- let res = { errCode: 0 };
- const db = uniCloud.database();
- await db.collection("opendb-poi").where({
- is_random: true
- }).remove();
- return res;
- },
- // 演示用 - 初始化静态001场景演示数据
- async initStatic001(data = {}) {
- let res = { errCode: 0 };
- const category = "static-001";
- // 先删除
- await opendbPoiDB.where({
- category: category
- }).remove();
- // 后添加随机数据
- // 以天安门为中心
- let tiananmen = {
- longitude: 116.39747,
- latitude: 39.908823,
- };
- let time = Date.now();
- // 随机生成6个门店地址
- let list = [];
- for (let i = 1; i <= 6; i++) {
- let randomCoordinate = getRandomCoordinateWithinRadius(tiananmen.longitude, tiananmen.latitude, 10); // 随机生成在天安门方圆X KM内的坐标
- list.push({
- category: category, // 场景值,用于区分这些POI所属哪张地图
- type: "门店",
- title: `随机门店-${i}`,
- location: new db.Geo.Point(randomCoordinate.longitude, randomCoordinate.latitude),
- create_date: time,
- visible: true,
- is_random: true, // 表示此为随机生成的点,方便删除
- level: i
- });
- }
- // 随机生成1个总部地址
- let randomCoordinate = getRandomCoordinateWithinRadius(tiananmen.longitude, tiananmen.latitude, 1); // 随机生成在天安门方圆X KM内的坐标
- list.push({
- category: category, // 场景值,用于区分这些POI所属哪张地图
- type: "总部",
- title: `随机总部`,
- location: new db.Geo.Point(randomCoordinate.longitude, randomCoordinate.latitude),
- create_date: time,
- visible: true,
- is_random: true, // 表示此为随机生成的点,方便删除
- level: 7
- });
- // 添加到数据库
- await opendbPoiDB.add(list);
- return res;
- },
- // 演示用 - 初始化动态001场景演示数据(模拟送外卖场景)
- async initDynamics001(data = {}) {
- let res = { errCode: 0 };
- const category = "dynamics-001";
- // 先删除
- await opendbPoiDB.where({
- category: category
- }).remove();
- // 后添加随机数据
- // 以天安门为中心
- let tiananmen = {
- longitude: 116.39747,
- latitude: 39.908823,
- };
- let time = Date.now();
- // 随机生成配送员坐标
- let randomCoordinate1 = getRandomCoordinateWithinRadius(tiananmen.longitude, tiananmen.latitude, 2); // 随机生成在天安门方圆X KM内的坐标
- let data1 = {
- category: category, // 场景值,用于区分这些POI所属哪张地图
- type: "配送员",
- title: "配送员",
- location: new db.Geo.Point(randomCoordinate1.longitude, randomCoordinate1.latitude),
- create_date: time,
- visible: true,
- is_random: true, // 表示此为随机生成的点,方便删除
- }
- // 随机生成目的地坐标
- let randomCoordinate2 = getRandomCoordinateWithinRadius(tiananmen.longitude, tiananmen.latitude, 2); // 随机生成在天安门方圆X KM内的坐标
- let data2 = {
- category: category, // 场景值,用于区分这些POI所属哪张地图
- type: "目的地",
- title: "配送目的地",
- location: new db.Geo.Point(randomCoordinate2.longitude, randomCoordinate2.latitude),
- create_date: time,
- visible: true,
- is_random: true, // 表示此为随机生成的点,方便删除
- }
- let list = [data1, data2];
- // 添加到数据库
- await opendbPoiDB.add(list);
- // 获取配送路线
- // 获取uniMap实例
- const uniMap = this.uniMap;
- // 调用电瓶车路径规划API
- let result = await uniMap.route({
- mode: "ebicycling",
- from: `${randomCoordinate1.latitude},${randomCoordinate1.longitude}`,
- to: `${randomCoordinate2.latitude},${randomCoordinate2.longitude}`,
- alternative_route: 1
- });
- let route = result.result.routes[0];
- let { steps = [] } = route;
- let points = [];
- steps.map((step) => {
- let {
- polyline = ""
- } = step;
- let arr = polyline.split(";");
- arr.map((item) => {
- let arr2 = item.split(",");
- points.push({
- latitude: arr2[0],
- longitude: arr2[1],
- });
- });
- });
- let polyline = {
- points,
- color: "#19b411",
- width: 6,
- dottedLine: false,
- arrowLine: true,
- borderWidth: 1,
- borderColor: "#000000",
- };
- res.polyline = [polyline];
- return res;
- },
- // 演示用 - 获取配送员配送路径
- async getPolyline(data = {}) {
- let res = { errCode: 0 };
- const category = "dynamics-001";
- let getRes1 = await opendbPoiDB.where({
- category: category,
- type: "配送员",
- visible: true
- }).get();
- let poi1 = getRes1.data[0];
- let getRes2 = await opendbPoiDB.where({
- category: category,
- type: "目的地",
- visible: true
- }).get();
- let poi2 = getRes2.data[0];
- if (!poi2) {
- return {
- errCode: 0,
- end: true
- }
- }
- let coordinate1 = {
- longitude: poi1.location.coordinates[0],
- latitude: poi1.location.coordinates[1]
- };
- let coordinate2 = {
- longitude: poi2.location.coordinates[0],
- latitude: poi2.location.coordinates[1]
- };
- // 获取uniMap实例
- const uniMap = this.uniMap;
- // 调用电瓶车路径规划API
- let result = await uniMap.route({
- mode: "ebicycling",
- from: `${coordinate1.latitude},${coordinate1.longitude}`,
- to: `${coordinate2.latitude},${coordinate2.longitude}`,
- alternative_route: 1
- });
- let route = result.result.routes[0];
- //console.log('route: ', route)
- let { steps = [], distance, duration } = route;
- let points = [];
- let dir_desc;
- steps.map((step) => {
- let {
- polyline = ""
- } = step;
- if (!dir_desc) dir_desc = step.dir_desc;
- if (polyline) {
- let arr = polyline.split(";");
- arr.map((item) => {
- let arr2 = item.split(",");
- if (!isNaN(arr2[0]) && !isNaN(arr2[1])) {
- points.push({
- latitude: Number(arr2[0]),
- longitude: Number(arr2[1]),
- });
- }
- });
- }
- });
- let polyline = {
- points,
- color: "#19b411",
- width: 6,
- dottedLine: false,
- arrowLine: true,
- borderWidth: 1,
- borderColor: "#000000",
- };
- res.polyline = [polyline];
- if (distance <= 30 || duration <= 0) {
- await opendbPoiDB.doc(poi1._id).update({
- title: `配送员已到达目的地`,
- location: new db.Geo.Point(Number(coordinate2.longitude), Number(coordinate2.latitude)),
- rotate: 0
- });
- // 隐藏目的地
- await opendbPoiDB.doc(poi2._id).update({
- visible: false,
- });
- return {
- errCode: 0,
- end: true
- }
- } else {
- // 从最近2个点计算出当前行驶方向
- let rotate = 0;
- if (points && points.length >= 2) {
- rotate = calculateDirectionAngle(points[0], points[1]);
- }
- await opendbPoiDB.doc(poi1._id).update({
- title: `配送员正在配送\r\n还有 ${distance} 米\r\n预计 ${duration} 分钟送达`,
- rotate: rotate, // 设置角度,0°的图片方向应朝左(西) 故90° 朝上(北) 180° 朝右(东) 270° 朝下(南)
- });
- }
- return res;
- },
- // 演示用 - 模拟上报配送员坐标
- async updateMyLocation(data = {}) {
- let res = {};
- const category = "dynamics-001";
- let {
- longitude,
- latitude
- } = data;
- let getRes1 = await opendbPoiDB.where({
- category: category,
- type: "配送员",
- visible: true
- }).get();
- let poi1 = getRes1.data[0];
- await opendbPoiDB.doc(poi1._id).update({
- location: new db.Geo.Point(Number(longitude), Number(latitude))
- });
- return res;
- },
- // 演示用 - xxxx
- async test(data = {}) {
- let res = {};
- // 获取uniMap实例
- const uniMap = this.uniMap;
- // 调用API
- let result = await uniMap.location2address({
- });
- res.result = result;
- return res;
- }
- }
- /**
- * 生成在指定经纬度圆内的随机坐标
-
- const latitude = 39.908823; // 指定纬度
- const longitude = 116.39747; // 指定经度
- const radiusInKm = 10; // 指定圆的半径(单位:千米)
- const randomCoordinate = getRandomCoordinateWithinRadius(latitude, longitude, radiusInKm);
- console.log(randomCoordinate);
- */
- function getRandomCoordinateWithinRadius(longitude, latitude, radiusInKm) {
- // 地球半径(单位:千米)
- const earthRadius = 6371;
- // 将圆的半径转换为弧度
- const radiusInRad = radiusInKm / earthRadius;
- // 生成随机的方位角(弧度,0到2π)
- const randomAngleRad = Math.random() * 2 * Math.PI;
- // 生成随机的距离(弧度,0到圆的半径)
- const randomDistanceRad = Math.acos(Math.random() * (Math.cos(radiusInRad) - 1) + 1);
- // 使用球面三角学计算随机点的纬度和经度
- const randomLatitudeRad = latitude * (Math.PI / 180) + randomDistanceRad * Math.cos(randomAngleRad);
- const randomLongitudeRad = longitude * (Math.PI / 180) + randomDistanceRad * Math.sin(randomAngleRad) / Math.cos(latitude * (Math.PI / 180));
- // 转换为度,并保留6位小数
- const randomLatitude = parseFloat((randomLatitudeRad * (180 / Math.PI)).toFixed(6));
- const randomLongitude = parseFloat((randomLongitudeRad * (180 / Math.PI)).toFixed(6));
- return { latitude: randomLatitude, longitude: randomLongitude };
- }
- /**
- * 计算坐标B在坐标A的方向,0代表正西方 90 代表正北方
-
- const latitude = 39.908823; // 指定纬度
- const longitude = 116.39747; // 指定经度
- const radiusInKm = 10; // 指定圆的半径(单位:千米)
- const randomCoordinate = getRandomCoordinateWithinRadius(latitude, longitude, radiusInKm);
- console.log(randomCoordinate);
- */
- function calculateDirectionAngle(coordA, coordB) {
- const toRadians = (angle) => angle * (Math.PI / 180);
- const toDegrees = (angle) => angle * (180 / Math.PI);
- const lat1 = toRadians(coordA.latitude);
- const lon1 = toRadians(coordA.longitude);
- const lat2 = toRadians(coordB.latitude);
- const lon2 = toRadians(coordB.longitude);
- const dLon = lon2 - lon1;
- const y = Math.sin(dLon) * Math.cos(lat2);
- const x =
- Math.cos(lat1) * Math.sin(lat2) -
- Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon);
- const angleRadians = Math.atan2(y, x);
- let angleDegrees = toDegrees(angleRadians);
- angleDegrees = (angleDegrees + 360) % 360;
- angleDegrees = (angleDegrees > 180) ? angleDegrees - 180 : angleDegrees + 180;
- angleDegrees -= 90; // 以正西方为0°表示,因此需要-90
- return angleDegrees;
- }
|