var MapUtil = {
_map: '',
_satellite: '',
_object3Dlayer: '',
_canvas: '',
_customLayer: '',
_dpi: Util.dpi(),
_isDragging: false,
init: function (elementId) {
this._map = new AMap.Map(elementId, {
resizeEnable: true,
center: [121.6039283, 31.25295567],
zoom: 12,
});
},
setCenter: function (lnglat) {
if (this._isDragging) {
return;
}
var now = new Date();
if (
this.lasttime == undefined ||
now.getTime() - this.lasttime.getTime() >= 1000
) {
this._map.setCenter(lnglat);
this.lasttime = now;
}
},
clearMap: function () {
this._map.clearMap();
this._car = undefined;
},
clear3D: function () {
this._object3Dlayer.remove(this._cylinder);
this._cylinder = undefined;
},
addViews: function (views, fit) {
this._map.add(views);
if (fit != false) {
this._map.setFitView(views);
}
},
removeViews: function (views) {
this._map.remove(views);
},
addElasticMarkers(markers) {
const zoomStyleMapping = {
14: 0,
15: 0,
16: 0,
17: 0,
18: 0,
19: 0,
20: 0,
};
const mList = [];
markers.forEach((m) => {
let name = m.name;
if (m.name.length > 9) {
const i = m.name.length / 2;
const str1 = m.name.slice(0, i + 1);
const str2 = m.name.slice(i + 1, m.name.length);
name = `${str1}
${str2}`;
}
var marker = new AMap.ElasticMarker({
title: m.name,
zoom: [14, 20],
position: new AMap.LngLat(m.lng, m.lat),
styles: [
{
icon: {
img: './asset/mipmap/scene.png',
size: [16, 16], //可见区域的大小
ancher: [8, 16], //锚点
fitZoom: 14, //最合适的级别
scaleFactor: 1.4, //地图放大一级的缩放比例系数
maxScale: 2, //最大放大比例
minScale: 1, //最小放大比例
},
label: {
content: `
${name}
`,
offset: [-35, 0],
position: 'BM',
minZoom: 15,
},
},
],
zoomStyleMapping: zoomStyleMapping,
});
mList.push(marker);
});
this.addViews(mList, false);
return mList;
},
_markers: [],
/**
*
* @param {*} fDatas 所有走航监测因子数据
* @param {*} _factor 当前选中的监测因子数据
* @param {*} lineChart 需要联动的折线图
* @param {*} onClick 标记点击事件回调
* @param {boolean} merge 是否和之前的标记合并绘制
*/
drawMarker: function (fDatas, _factor, lineChart, onClick, merge) {
if (!this._showDataMarker) {
return;
}
const interval = this._getMarkerInterval();
if (fDatas) {
if (merge != true && this._markers.length > 0) {
this.removeViews(this._markers);
this._markers = [];
}
const lnglats = fDatas.lnglats_GD;
const factor = fDatas.factor;
for (let i = 0; i < lnglats.length; i++) {
// 创建一个 Marker 实例:
var marker = new AMap.Marker({
position: new AMap.LngLat(lnglats[i][0], lnglats[i][1]), // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
title: `${fDatas.times[i]}\r\n${_factor.factorName}: ${_factor.datas[i].factorData} mg/m³`,
offset: new AMap.Pixel(-13, -12),
// anchor: 'center',
icon: new AMap.Icon({
image: './asset/mipmap/ic_up_white.png',
// imageSize: [12, 12],
}),
});
marker.on('click', (event) => {
// console.log(event);
// console.log(i);
// 绘制溯源扇形区域
var windDir = 0;
const d = factor[17].datas[i];
if (d != undefined) {
windDir = d.factorData;
}
var windSpeed = 1;
const s = factor[16].datas[i];
if (s != undefined) {
windSpeed = s.factorData;
}
// 1. 绘制扇形区域
this.drawSector3(lnglats[i], windDir, windSpeed);
// 2. 绘制对话框
const window = DialogUtil.createInfoWindow(fDatas, i, () => {
// 移除扇形区域
this.clearSector3();
});
window.open(MapUtil._map, lnglats[i]);
// 3. 趋势图跳转定位
const progress = FChart.locate(
lineChart.chart,
lineChart.option,
i,
_factor.factorName
);
// 4. 表格数据跳转定位
Table.locate(i);
// 5. 自定义点击事件
onClick(progress);
});
// this._map.add(marker);
this._markers.push(marker);
}
}
const _markers = [];
for (let i = 0; i < this._markers.length; i += interval) {
_markers.push(this._markers[i]);
}
this.removeViews(this._markers);
this.addViews(_markers, false);
},
_massMarks: undefined,
/**
* 绘制海量点标记
* @param {*} fDatas 所有走航监测因子数据
* @param {*} _factor 当前选中的监测因子数据
* @param {*} lineChart 需要联动的折线图
* @param {*} onClick 标记点击事件回调
*/
drawMassMarks(fDatas, _factor, lineChart, onClick) {
if (!this._showDataMarker) {
return;
}
if (this._massMarks) {
this.removeViews(this._massMarks);
this._massMarks = undefined;
}
const lnglats = fDatas.lnglats_GD;
const factor = fDatas.factor;
var data = [];
for (let i = 0; i < lnglats.length; i++) {
data.push({
lnglat: lnglats[i], //点标记位置
name: `${fDatas.times[i]}
${_factor.factorName}: ${_factor.datas[i].factorData} mg/m³`,
id: i,
});
}
// 创建样式对象
var styleObject = {
url: 'https://a.amap.com/jsapi_demos/static/images/mass1.png',
// url: './asset/mipmap/ic_up_white.png', // 图标地址
size: new AMap.Size(11, 11), // 图标大小
anchor: new AMap.Pixel(5, 5), // 图标显示位置偏移量,基准点为图标左上角
};
var massMarks = new AMap.MassMarks(data, {
zIndex: 5, // 海量点图层叠加的顺序
zooms: [15, 18], // 在指定地图缩放级别范围内展示海量点图层
style: styleObject, // 设置样式对象
});
massMarks.on('click', (event) => {
const i = event.data.id;
// 绘制溯源扇形区域
var windDir = 0;
const d = factor[17].datas[i];
if (d != undefined) {
windDir = d.factorData;
}
var windSpeed = 1;
const s = factor[16].datas[i];
if (s != undefined) {
windSpeed = s.factorData;
}
// 1. 绘制扇形区域
this.drawSector3(lnglats[i], windDir, windSpeed);
// 2. 绘制对话框
DialogUtil.openNewWindow(fDatas, i, MapUtil._map, lnglats[i], () => {
// 移除扇形区域
// this.clearSector3();
});
// 3. 趋势图跳转定位
const progress = FChart.locate(
lineChart.chart,
lineChart.option,
i,
_factor.factorName
);
// 4. 表格数据跳转定位
Table.locate(i);
// 5. 自定义点击事件
onClick(progress);
});
var marker = new AMap.Marker({
content: ' ',
map: this._map,
offset: new AMap.Pixel(13, 12),
});
var timeout;
massMarks.on('mouseover', (e) => {
if (timeout) {
clearTimeout(timeout);
}
marker.setPosition(e.data.lnglat);
marker.setLabel({ content: e.data.name });
this.addViews(marker, false);
timeout = setTimeout(() => {
this.removeViews(marker);
}, 2000);
});
this._massMarks = massMarks;
this.addViews(massMarks, false);
},
_polyline: '',
drawLine: function (lnglats) {
this._map.remove(this._polyline);
var path = this.parse2LngLat(lnglats);
// 创建折线实例
this._polyline = new AMap.Polyline({
path: path,
strokeStyle: 'solid',
isOutline: true,
borderWeight: 2,
outlineColor: 'white',
strokeWeight: 4, // 线条宽度,默认为 1
strokeColor: '#CC0000', // 线条颜色
lineJoin: 'round', // 折线拐点连接处样式
showDir: true,
});
// 将折线添加至地图实例
this._map.add(this._polyline);
return this._polyline;
},
/**
* 根据坐标点、距离和角度,得到另一个坐标点
* @param {*} pos
* @param {*} distance 米
* @param {*} angle
*/
_getLatLon: function (pos, distance, angle) {
var Ea = 6378137; // 赤道半径
var Eb = 6356725; // 极半径
var dx = distance * Math.sin((angle * Math.PI) / 180);
var dy = distance * Math.cos((angle * Math.PI) / 180);
var ec = Eb + ((Ea - Eb) * (90.0 - pos[1])) / 90.0;
var ed = ec * Math.cos((pos[1] * Math.PI) / 180);
var lng = ((dx / ed + (pos[0] * Math.PI) / 180.0) * 180.0) / Math.PI;
var lat = ((dy / ec + (pos[1] * Math.PI) / 180.0) * 180.0) / Math.PI;
return [lng, lat];
},
_defaultDeg: 30,
_sector: undefined,
_sectorViews3: {},
drawSector3: function (lnglat, windDir, windSpeed) {
if (windSpeed > 10) {
return;
}
if (this._sector != undefined) {
this.clearSector3();
}
var sector = new AMap.Object3D.Mesh();
sector.transparent = true;
sector.backOrFront = 'both';
var unit = 5;
var sDeg = windDir - this._defaultDeg; //扇形起始角度(以上方作为0度)
// sDeg = sDeg < 0 ? sDeg + 360 : sDeg
var eDeg = windDir + this._defaultDeg; //扇形结束角度
// eDeg = eDeg < 0 ? eDeg + 360 : eDeg
var distance = windSpeed * 10 * 60; //半径(风速*时间)
var lnglat2 = this._getLatLon(lnglat, distance, sDeg);
var lnglat3 = this._getLatLon(lnglat, distance, windDir);
var lnglat4 = this._getLatLon(lnglat, distance, eDeg);
var list = this.parse2LngLat([lnglat, lnglat2, lnglat3, lnglat4]);
var distance2 = windSpeed * 5 * 60; //半径(风速*时间)
var lnglat2_2 = this._getLatLon(lnglat, distance2, sDeg);
var lnglat2_3 = this._getLatLon(lnglat, distance2, windDir);
var lnglat2_4 = this._getLatLon(lnglat, distance2, eDeg);
var list2 = this.parse2LngLat([lnglat2_2, lnglat2_3, lnglat2_4]);
var p0 = this.lngLatToGeodeticCoord([lnglat])[0];
var geometry = sector.geometry;
var count = distance / unit;
var unitDeg = (eDeg - sDeg) / count;
for (let i = 0; i < count; i++) {
var angle1 = sDeg + unitDeg * i;
var angle2 = sDeg + unitDeg * (i + 1);
var l1 = this._getLatLon(lnglat, distance, angle1);
var l2 = this._getLatLon(lnglat, distance, angle2);
var l3 = this._getLatLon(lnglat, distance2, angle1);
var l4 = this._getLatLon(lnglat, distance2, angle2);
var coors = this.lngLatToGeodeticCoord([l1, l2, l3, l4]);
l1 = coors[0];
l2 = coors[1];
l3 = coors[2];
l4 = coors[3];
// 内测扇形
geometry.vertices.push(p0.x, p0.y, 0);
geometry.vertices.push(l3.x, l3.y, 0);
geometry.vertices.push(l4.x, l4.y, 0);
// 外侧扇形
geometry.vertices.push(l3.x, l3.y, 0);
geometry.vertices.push(l4.x, l4.y, 0);
geometry.vertices.push(l1.x, l1.y, 0);
geometry.vertices.push(l2.x, l2.y, 0);
// console.log(l3.x + ',' + l3.y + ' | ' + l1.x + ',' + l1.y);
// 内测扇形颜色
geometry.vertexColors.push(1, 0.11, 0.25, 0.6);
geometry.vertexColors.push(1, 0.11, 0.25, 0.6);
geometry.vertexColors.push(1, 0.11, 0.25, 0.6);
//外侧扇形颜色
geometry.vertexColors.push(1, 0.37, 0.07, 0.5);
geometry.vertexColors.push(1, 0.37, 0.07, 0.5);
geometry.vertexColors.push(1, 0.37, 0.07, 0.5);
geometry.vertexColors.push(1, 0.37, 0.07, 0.5);
var index = i * 7;
geometry.faces.push(index, index + 1, index + 2);
geometry.faces.push(index + 3, index + 4, index + 5);
geometry.faces.push(index + 4, index + 5, index + 6);
}
this._object3Dlayer.add(sector);
this._sector = sector;
distance = distance.toFixed(0);
distance2 = distance2.toFixed(0);
const zoomStyleMapping = {
14: 0,
15: 0,
16: 0,
17: 0,
18: 0,
19: 0,
20: 0,
};
//10分钟扇形
var text15 = new AMap.ElasticMarker({
zoom: [14, 20],
position: list[2],
styles: [
{
icon: {
img: './asset/mipmap/location.png',
size: [16, 16], //可见区域的大小
ancher: [8, 16], //锚点
fitZoom: 18, //最合适的级别
scaleFactor: 1, //地图放大一级的缩放比例系数
maxScale: 2, //最大放大比例
minScale: 1, //最小放大比例
},
label: {
content: '10分钟
',
offset: [-35, 0],
position: 'BM',
minZoom: 15,
},
},
],
zoomStyleMapping: zoomStyleMapping,
});
MapUtil._sectorViews3['text10'] = text15;
var textM = new AMap.ElasticMarker({
zoom: [14, 20],
position: list[1],
styles: [
{
icon: {
img: './asset/mipmap/location.png',
size: [16, 16], //可见区域的大小
ancher: [8, 16], //锚点
fitZoom: 18, //最合适的级别
scaleFactor: 1, //地图放大一级的缩放比例系数
maxScale: 2, //最大放大比例
minScale: 1, //最小放大比例
},
label: {
content: `${distance}m
`,
offset: [-35, 0],
position: 'BM',
minZoom: 15,
},
},
],
zoomStyleMapping: zoomStyleMapping,
});
MapUtil._sectorViews3['textM'] = textM;
MapUtil._map.add(MapUtil._sectorViews3['text10']);
MapUtil._map.add(MapUtil._sectorViews3['textM']);
//5分钟扇形
pList = list2;
path = [
[pList[0].lng, pList[0].lat],
[pList[1].lng, pList[1].lat, pList[2].lng, pList[2].lat],
];
var text5 = new AMap.ElasticMarker({
position: pList[1],
styles: [
{
icon: {
img: './asset/mipmap/location.png',
size: [16, 16], //可见区域的大小
ancher: [8, 16], //锚点
fitZoom: 18, //最合适的级别
scaleFactor: 1, //地图放大一级的缩放比例系数
maxScale: 2, //最大放大比例
minScale: 1, //最小放大比例
},
label: {
content: `5分钟
`,
offset: [-35, 0],
position: 'BM',
minZoom: 15,
},
},
],
zoomStyleMapping: zoomStyleMapping,
});
MapUtil._sectorViews3['text5'] = text5;
var textM5 = new AMap.ElasticMarker({
position: pList[0],
styles: [
{
icon: {
img: './asset/mipmap/location.png',
size: [16, 16], //可见区域的大小
ancher: [8, 16], //锚点
fitZoom: 18, //最合适的级别
scaleFactor: 1, //地图放大一级的缩放比例系数
maxScale: 2, //最大放大比例
minScale: 1, //最小放大比例
},
label: {
content: `${distance2}m
`,
offset: [-35, 0],
position: 'BM',
minZoom: 15,
},
},
],
zoomStyleMapping: zoomStyleMapping,
});
MapUtil._sectorViews3['textM5'] = textM5;
MapUtil._map.add(MapUtil._sectorViews3['textM5']);
MapUtil._map.add(MapUtil._sectorViews3['text5']);
// 查询范围内的监测站点
SceneUtil.searchByCoordinate(lnglat[0], lnglat[1], distance);
},
drawSector4: function (lnglat, windDir, windSpeed) {
if (windSpeed > 10) {
return;
}
var sector = new AMap.Object3D.Mesh();
sector.transparent = true;
sector.backOrFront = 'both';
var unit = 5;
var sDeg = windDir - this._defaultDeg; //扇形起始角度(以上方作为0度)
var eDeg = windDir + this._defaultDeg; //扇形结束角度
var distance = windSpeed * 10 * 60; //半径(风速*时间)
var lnglat2 = this._getLatLon(lnglat, distance, sDeg);
var lnglat3 = this._getLatLon(lnglat, distance, windDir);
var lnglat4 = this._getLatLon(lnglat, distance, eDeg);
var list = this.parse2LngLat([lnglat, lnglat2, lnglat3, lnglat4]);
var distance2 = windSpeed * 5 * 60; //半径(风速*时间)
var lnglat2_2 = this._getLatLon(lnglat, distance2, sDeg);
var lnglat2_3 = this._getLatLon(lnglat, distance2, windDir);
var lnglat2_4 = this._getLatLon(lnglat, distance2, eDeg);
var list2 = this.parse2LngLat([lnglat2_2, lnglat2_3, lnglat2_4]);
var p0 = this.lngLatToGeodeticCoord([lnglat])[0];
var geometry = sector.geometry;
var count = distance / unit;
var unitDeg = (eDeg - sDeg) / count;
for (let i = 0; i < count; i++) {
var angle1 = sDeg + unitDeg * i;
var angle2 = sDeg + unitDeg * (i + 1);
var l1 = this._getLatLon(lnglat, distance, angle1);
var l2 = this._getLatLon(lnglat, distance, angle2);
var l3 = this._getLatLon(lnglat, distance2, angle1);
var l4 = this._getLatLon(lnglat, distance2, angle2);
var coors = this.lngLatToGeodeticCoord([l1, l2, l3, l4]);
l1 = coors[0];
l2 = coors[1];
l3 = coors[2];
l4 = coors[3];
// 内测扇形
geometry.vertices.push(p0.x, p0.y, 0);
geometry.vertices.push(l3.x, l3.y, 0);
geometry.vertices.push(l4.x, l4.y, 0);
// 外侧扇形
geometry.vertices.push(l3.x, l3.y, 0);
geometry.vertices.push(l4.x, l4.y, 0);
geometry.vertices.push(l1.x, l1.y, 0);
geometry.vertices.push(l2.x, l2.y, 0);
// 内测扇形颜色
geometry.vertexColors.push(1, 0.11, 0.25, 0.6);
geometry.vertexColors.push(1, 0.11, 0.25, 0.6);
geometry.vertexColors.push(1, 0.11, 0.25, 0.6);
//外侧扇形颜色
geometry.vertexColors.push(1, 0.37, 0.07, 0.5);
geometry.vertexColors.push(1, 0.37, 0.07, 0.5);
geometry.vertexColors.push(1, 0.37, 0.07, 0.5);
geometry.vertexColors.push(1, 0.37, 0.07, 0.5);
var index = i * 7;
geometry.faces.push(index, index + 1, index + 2);
geometry.faces.push(index + 3, index + 4, index + 5);
geometry.faces.push(index + 4, index + 5, index + 6);
}
if (this._sector != undefined) {
this._object3Dlayer.remove(this._sector);
}
this._object3Dlayer.add(sector);
this._sector = sector;
distance = distance.toFixed(0);
distance2 = distance2.toFixed(0);
//10分钟扇形
if (MapUtil._sectorViews3['text10-a'] == undefined) {
var text15 = new AMap.Text({
text: '10分钟',
position: list[2],
style: {
'font-size': '13px',
'text-align': 'center',
color: 'white',
'background-color': 'transparent',
'text-shadow': 'black 2px 2px 2px',
'border-radius': '2px',
border: '0px',
padding: '4px',
},
});
MapUtil._map.add(text15);
MapUtil._sectorViews3['text10-a'] = text15;
var textM = new AMap.Text({
text: distance + 'm',
position: list[1],
style: {
'font-size': '13px',
'text-align': 'center',
color: 'white',
'background-color': 'transparent',
'text-shadow': 'black 2px 2px 2px',
'border-radius': '2px',
border: '0px',
padding: '4px',
},
});
MapUtil._map.add(textM);
MapUtil._sectorViews3['text10M-a'] = textM;
} else {
MapUtil._sectorViews3['text10-a'].setPosition(list[2]);
MapUtil._sectorViews3['text10M-a'].setPosition(list[1]);
MapUtil._sectorViews3['text10M-a'].setText(distance + 'm');
}
//5分钟扇形
pList = list2;
path = [
[pList[0].lng, pList[0].lat],
[pList[1].lng, pList[1].lat, pList[2].lng, pList[2].lat],
];
if (MapUtil._sectorViews3['textM5-a'] == undefined) {
var bezierCurve = new AMap.BezierCurve({
path: path,
// isOutline: true,
// outlineColor: '#ffeeff',
borderWeight: 1,
strokeColor: '#ffeeff',
strokeOpacity: 1,
// strokeWeight: 6,
// 线样式还支持 'dashed'
strokeStyle: 'solid',
// strokeStyle是dashed时有效
strokeDasharray: [10, 10],
lineJoin: 'round',
lineCap: 'round',
zIndex: 50,
});
// bezierCurve.setMap(MapUtil._map)
// MapUtil._sectorViews3['bezierCurve'] = bezierCurve
var text5 = new AMap.Text({
text: '5分钟',
position: pList[1],
style: {
'font-size': '13px',
'text-align': 'center',
color: 'white',
'background-color': 'transparent',
'text-shadow': 'black 2px 2px 2px',
'border-radius': '2px',
border: '0px',
padding: '4px',
},
// animation: "AMAP_ANIMATION_DROP"
});
MapUtil._map.add(text5);
MapUtil._sectorViews3['text5-a'] = text5;
var textM5 = new AMap.Text({
text: distance2 + 'm',
position: pList[0],
style: {
'font-size': '13px',
'text-align': 'center',
color: 'white',
'background-color': 'transparent',
'text-shadow': 'black 2px 2px 2px',
'border-radius': '2px',
border: '0px',
padding: '4px',
},
// animation: "AMAP_ANIMATION_DROP"
});
MapUtil._map.add(textM5);
MapUtil._sectorViews3['textM5-a'] = textM5;
} else {
// MapUtil._sectorViews3['bezierCurve'].setPath(path)
MapUtil._sectorViews3['text5-a'].setPosition(pList[1]);
MapUtil._sectorViews3['textM5-a'].setPosition(pList[0]);
MapUtil._sectorViews3['textM5-a'].setText(distance2 + 'm');
}
},
clearSector3: function () {
var list = [];
for (const key in this._sectorViews3) {
list.push(this._sectorViews3[key]);
}
if (list.length > 0) {
this.removeViews(list);
this._sectorViews3 = {};
}
if (this._sector) {
this._object3Dlayer.remove(this._sector);
}
},
parse2LngLat: function (lnglats) {
// 创建包含4个节点的折线及文字标注
var path = [];
lnglats.forEach(function (value) {
path.push(new AMap.LngLat(value[0], value[1]));
});
return path;
},
//*****************3d相关*************************
_margin: 0.00025,
//监测数据
_factorDatas: {
lnglats: [],
heights: [],
type: '',
},
//当前选中的监测因子数据
_factor: {},
_zoomFirst: true,
_onMapZoom: function () {
// 首次地图缩放监听不执行(因为设定监听函数后会立即执行一次,可能官方函数有相关参数,后续待修改)
if (this._zoomFirst) {
this._zoomFirst = false;
return;
}
const fDatas = MapUtil._factorDatas;
const factor = MapUtil._factor;
// MapUtil._object3Dlayer.clear()
// MapUtil.drawMesh(f.lnglats, f.heights, f.type, false)
MapUtil.drawMesh2(fDatas, factor);
MapUtil.drawMarker();
},
init3D: function (elementId) {
//setFeatures(feature:Array)
var that = this;
this._map = new AMap.Map(elementId, {
rotateEnable: true,
pitchEnable: true,
alwaysRender: false,
showLabel: true,
showBuildingBlock: true,
mapStyle: 'amap://styles/e1e78509de64ddcd2efb4cb34c6fae2a',
features: ['bg', 'road'],
pitch: 45, // 地图俯仰角度,有效范围 0 度- 83 度
viewMode: '3D', // 地图模式
resizeEnable: true,
center: [121.6039283, 31.25295567],
zooms: [3, 18],
zoom: 14,
});
// 卫星图层
this._satellite = new AMap.TileLayer.Satellite();
this._satellite.show();
this._map.add([this._satellite]);
this._map.addControl(
new AMap.ControlBar({
position: {
right: '300px',
top: '260px',
},
})
);
// 默认把地图工具箱关闭
// var closeControlbar = setInterval(() => {
// $('.amap-controlbar').hide();
// }, 100);
// 地图图块加载完成后触发
// this._map.on('complete', function () {
// $('.amap-controlbar').hide();
// clearInterval(closeControlbar);
// });
// AMap.plugin(['AMap.ControlBar', 'AMap.MapType'], function() { //异步同时加载多个插件
// 在图面添加类别切换控件,实现默认图层与卫星图、实施交通图层之间切换的控制
// MapUtil._map.addControl(new AMap.MapType({
// position: {
// left: '10px',
// top: '300px'
// }
// }));
// });
this._object3Dlayer = new AMap.Object3DLayer();
this._map.add(this._object3Dlayer);
this._canvas = document.createElement('canvas');
this._customLayer = new AMap.CustomLayer(this._canvas, {
zooms: [3, 20],
alwaysRender: true, //缩放过程中是否重绘,复杂绘制建议设为false
zIndex: 1,
opacity: 0.6,
});
this._customLayer.setMap(this._map);
// 设置地图拖拽监听事件
this._map.on('dragstart', function () {
clearTimeout(that.dragEndEvent);
that._isDragging = true;
});
this._map.on('dragend', function () {
that.dragEndEvent = setTimeout(() => {
that._isDragging = false;
}, 8000);
});
},
_feature: false,
/**
* 设置地图显示的内容
* @param {*} type
*/
setFeatures: function () {
this._feature = !this._feature;
if (!this._feature) {
this._map.setFeatures(['bg', 'road']);
return '地物标注:关';
} else {
this._map.setFeatures(['bg', 'road', 'point', 'building']);
return '地物标注:开';
}
},
_showLayer: true,
/**
* 切换图层
*/
toggleLayer: function () {
this._showLayer = !this._showLayer;
if (this._showLayer) {
this._satellite.show();
return '卫星地图:开';
} else {
this._satellite.hide();
return '卫星地图:关';
}
},
_controlbar: true,
/**
* 地图工具箱
*/
toggleControlbar: function () {
this._controlbar = !this._controlbar;
if (this._controlbar) {
$('.amap-controlbar').show();
return '控制罗盘:开';
} else {
$('.amap-controlbar').hide();
return '控制罗盘:关';
}
},
_showDataMarker: true,
toggleDataMarker() {
this._showDataMarker = !this._showDataMarker;
if (this._showDataMarker) {
this.addViews(this._markers, false);
return '数据标记:开';
} else {
this.removeViews(this._markers);
return '数据标记:关';
}
},
/**
* 坐标拾取功能
*/
_locationMarker: undefined,
_locationText: undefined,
_onClickListener: function (e) {
var text = `经度: ${e.lnglat.getLng()}
纬度: ${e.lnglat.getLat()}`;
if (MapUtil._locationMarker == undefined) {
var textM = new AMap.Text({
style: {
'font-size': '12px',
},
text: text,
position: e.lnglat,
offset: new AMap.Pixel(0, 30),
});
// textM.setStyle()
var icon = new AMap.Icon({
size: new AMap.Size(60, 60),
imageSize: new AMap.Size(60, 60),
image: './asset/mipmap/pungent.png',
});
var marker = new AMap.Marker({
position: e.lnglat,
// icon: icon,
// anchor: 'top-center',
content:
'',
});
MapUtil._map.add(marker);
MapUtil._map.add(textM);
MapUtil._locationMarker = marker;
MapUtil._locationText = textM;
} else {
MapUtil._locationMarker.setPosition(e.lnglat);
MapUtil._locationText.setPosition(e.lnglat);
MapUtil._locationText.setText(text);
}
},
_isOpen: false,
locationMark: function (onClickListener) {
this._isOpen = !this._isOpen;
if (onClickListener == undefined) {
onClickListener = this._onClickListener;
}
if (this._isOpen) {
this._map.on('click', onClickListener);
return '坐标拾取:开';
} else {
this._map.off('click', onClickListener);
this._map.remove([this._locationMarker, this._locationText]);
this._locationMarker = undefined;
this._locationText = undefined;
return '坐标拾取:关';
}
},
_prepare4convert: function (lnglats) {
var coor = [];
var maxLength = 1000;
var start = 0;
var end = start + maxLength;
while (end <= lnglats.length) {
coor.push(lnglats.slice(start, end));
start += maxLength;
end += maxLength;
}
if (start < lnglats.length) {
coor.push(lnglats.slice(start));
}
return coor;
},
/**
* 将gps经纬度转换为高德地图经纬度
* @param {*} lnglats
* @param {*} callback
*/
_convertLatlng: function (index, coor, lnglats, callback) {
if (index < coor.length) {
var path = MapUtil.parse2LngLat(coor[index]);
AMap.convertFrom(path, 'gps', function (status, result) {
if (result.info === 'ok') {
lnglats.push.apply(lnglats, result.locations);
MapUtil._convertLatlng(index + 1, coor, lnglats, callback);
}
});
} else {
callback(lnglats);
}
},
convertFromGPS: function (gps, callback) {
var coor = MapUtil._prepare4convert(gps);
MapUtil._convertLatlng(0, coor, [], function (result) {
var gd = [];
result.forEach((r) => {
gd.push([r.lng, r.lat]);
});
callback(gd);
});
},
lngLatToGeodeticCoord: function (lnglats_GD) {
var coors_GD = [];
for (let i = 0; i < lnglats_GD.length; i++) {
var gd = lnglats_GD[i];
var r = new AMap.LngLat(...gd);
var p = MapUtil._map.lngLatToGeodeticCoord(r);
// **记录转换后的3D地图图形坐标
coors_GD.push(p);
}
return coors_GD;
},
_cylinder: undefined, // 3d图形
_minH: -1, // 当前绘制的图形中的最小高度
_maxH: -1, // 当前绘制的图形中的最大高度
drawMesh_Test: function (fDatas, factor, merge, setCenter) {
const lnglats_GD = fDatas.lnglats_GD;
const coors_GD = fDatas.coors_GD;
const heights = factor.heights;
const colors = factor.colors;
const bColor = factor.bottomColor;
// 1.关闭地图缩放监听
this._map.off('zoomend', this._onMapZoom);
// 2.计算绘图高度的边界值
if (merge != true) {
var minH = MapUtil._minH < 0 ? heights[0] : MapUtil._minH;
var maxH = MapUtil._maxH < 0 ? heights[0] : MapUtil._maxH;
for (let i = 0; i < heights.length; i++) {
const h = heights[i];
minH = Math.min(minH, h);
maxH = Math.max(maxH, h);
}
MapUtil._minH = minH;
MapUtil._maxH = maxH;
}
// 3.确定定位坐标点
var center;
if (setCenter && lnglats_GD.length > 0) {
var p = lnglats_GD[0];
for (let i = 0; i < lnglats_GD.length; i++) {
const e = lnglats_GD[i];
if (e[0] != 0) {
p = e;
break;
}
}
center = new AMap.LngLat(...p);
}
// 5.绘制3D图形
MapUtil.drawMesh2(fDatas, factor, center, merge);
// 缩放地图到合适的视野级别
// MapUtil._map.setFitView()
// 6.开启地图缩放监听
if (lnglats_GD.length > 0) {
this._map.on('zoomend', this._onMapZoom);
}
},
/**
* 绘图
* @param {*} lnglats_GD 高德地图坐标
* @param {*} coors 通过高德地图 Map.lngLatToGeodeticCoord() 转换后的3d地图坐标
* @param {*} heights 每个坐标对应的高度
* @param {*} center 定位的坐标点
*/
drawMesh2: function (fDatas, factor, center, merge) {
const lnglats_GD = fDatas.lnglats_GD;
const coors = fDatas.coors_GD;
const heights = factor.heights;
const colors = factor.colors;
const bColor = factor.bottomColor;
if (center) {
MapUtil._map.setZoomAndCenter(16, center);
}
var cylinder = new AMap.Object3D.Mesh();
cylinder.backOrFront = 'both';
cylinder.transparent = true;
var geometry = cylinder.geometry;
const scale = MapUtil._getScale(MapUtil._minH, MapUtil._maxH);
for (let i = 0; i < coors.length; i++) {
var r = lnglats_GD[i];
var lastP = lnglats_GD[i - 1];
// if (r[0] == 0) {
// continue
// }
// if (lastP[0] == 0) {
// continue
// }
var p = coors[i];
// var p = MapUtil._map.lngLatToGeodeticCoord(r)
var h = MapUtil._getHeight(
heights[i],
MapUtil._minH,
MapUtil._maxH,
scale
);
if (heights[i] == -1) {
h = -1;
}
geometry.vertices.push(p.x, p.y, 0); //底部顶点
geometry.vertices.push(p.x, p.y, 0 - h); //顶部顶点
if (i > 0) {
var distance = AMap.GeometryUtil.distance(r, lastP);
//两个数据点最小间隔时间为4s,假设车速按照120km/h计算,4s行驶最大距离作为132米,
//设定超过1分钟的数据绘制特殊的连线
if (distance <= 500 && h != -1) {
var bottomIndex = i * 2;
var topIndex = bottomIndex + 1;
var lastBottomIndex = bottomIndex - 2;
var lastTopIndex = bottomIndex - 1;
geometry.faces.push(bottomIndex, topIndex, lastTopIndex);
geometry.faces.push(bottomIndex, lastBottomIndex, lastTopIndex);
}
}
// var bColor = bColor
var tColor = colors[i];
geometry.vertexColors.push.apply(geometry.vertexColors, bColor); //底部顶点颜色
geometry.vertexColors.push.apply(geometry.vertexColors, tColor); //顶部顶点颜色
}
// 7.根据合并选项重置或新增当前缓存数据
if (merge != true) {
this._factorDatas = fDatas;
this._factor = factor;
if (MapUtil._cylinder != undefined) {
MapUtil._object3Dlayer.remove(MapUtil._cylinder);
}
} else {
// this._factorDatas.lnglats.push.apply(
// this._factorDatas.lnglats,
// lnglats_GD
// );
// this._factorDatas.coors.push.apply(this._factorDatas.coors, coors);
// this._factorDatas.heights.push.apply(this._factorDatas.heights, heights);
// this._factorDatas.colors.push.apply(this._factorDatas.colors, colors);
// this._factorDatas.bottomColor = bColor;
}
MapUtil._object3Dlayer.add(cylinder);
/**************test ****************/
MapUtil._object3Dlayer.on('mouseover', function (e) {
console.log(
`鼠标移入覆盖物! [${e.lnglat.getlng()}, ${e.lnglat.getLat()}]`
);
});
/**************test ****************/
MapUtil._cylinder = cylinder;
},
_maxHeight: 1000,
_minHeight: 100,
_lastZoom: -1,
/**
* 获取当前地图缩放等级下的绘制高度缩放比例
* @param {*} minH 当前监测数据的最小高度
* @param {*} maxH 当前监测数据的最大高度
*/
_getScale(minH, maxH) {
var zoom = MapUtil._map.getZoom();
// console.log(`zoom: ${zoom}`);
if (this._lastZoom == -1) {
this._lastZoom = zoom;
} else if (this._lastZoom <= 8) {
this._lastZoom = zoom;
return;
} else if (this._lastZoom >= 18) {
this._lastZoom = zoom;
return;
}
if (zoom <= 8) {
MapUtil._maxHeight = 10000;
MapUtil._minHeight = 1000;
} else if (zoom <= 9) {
MapUtil._maxHeight = 9000;
MapUtil._minHeight = 900;
} else if (zoom <= 10) {
MapUtil._maxHeight = 8000;
MapUtil._minHeight = 800;
} else if (zoom <= 11) {
MapUtil._maxHeight = 7000;
MapUtil._minHeight = 700;
} else if (zoom <= 12) {
MapUtil._maxHeight = 6000;
MapUtil._minHeight = 600;
} else if (zoom <= 14) {
MapUtil._maxHeight = 5000;
MapUtil._minHeight = 500;
} else if (zoom <= 15) {
MapUtil._maxHeight = 4500;
MapUtil._minHeight = 450;
} else if (zoom <= 16) {
MapUtil._maxHeight = 4000;
MapUtil._minHeight = 400;
} else if (zoom <= 17) {
MapUtil._maxHeight = 2500;
MapUtil._minHeight = 250;
} else if (zoom > 17) {
MapUtil._maxHeight = 1000;
MapUtil._minHeight = 100;
}
var scale = (MapUtil._maxHeight - MapUtil._minHeight) / (maxH - minH);
return scale;
},
/**
* 根据地图缩放等级获取监测因子图形的绘制高度范围
* @param {*} height 当前数据的原始高度
* @param {*} minH 当前监测数据的最小高度
* @param {*} maxH 当前监测数据的最大高度
* @param {*} scale 缩放比例
* @returns
*/
_getHeight: function (height, minH, maxH, scale) {
// var offset = minH - (maxH - minH) * (this._minHeight / this._maxHeight)
// height = ((height - offset) < 0 ? 0 : (height - offset)) * scale
// // console.log("scale: " + height);
// return height
height = (height - minH) * scale + MapUtil._minHeight;
return height;
},
/**
* 根据地图缩放等级,获取走航监测点标记的绘制间隔
*/
_getMarkerInterval() {
var zoom = MapUtil._map.getZoom();
if (this._lastZoom == -1) {
this._lastZoom = zoom;
} else if (this._lastZoom <= 8) {
this._lastZoom = zoom;
return;
} else if (this._lastZoom >= 18) {
this._lastZoom = zoom;
return;
}
var interval = 1;
if (zoom <= 8) {
interval = 1000;
} else if (zoom <= 9) {
interval = 800;
} else if (zoom <= 10) {
interval = 600;
} else if (zoom <= 11) {
interval = 400;
} else if (zoom <= 12) {
interval = 100;
} else if (zoom <= 13) {
interval = 20;
} else if (zoom <= 14) {
interval = 10;
} else if (zoom <= 15) {
interval = 5;
} else if (zoom <= 16) {
interval = 2;
} else if (zoom <= 17) {
interval = 1;
} else if (zoom > 17) {
interval = 1;
}
return interval;
},
};