/**
|
* 网格绘制
|
*/
|
import { map } from './index_old';
|
import calculate from './calculate';
|
import { Legend } from '@/model/Legend';
|
import { getHexColor, getColorBetweenTwoColors } from '../color';
|
|
/**
|
* 角度增减,确保角度处于0 - 360度之间
|
* @param {number} angle 原角度
|
* @param {number} offset 偏移量
|
*/
|
function plusAngle(angle, offset) {
|
const result = angle + offset;
|
if (result > 360) {
|
return result - 360;
|
} else if (result < 0) {
|
return result + 360;
|
} else {
|
return result;
|
}
|
}
|
|
/**
|
* 根据网格中心点,生成正方形网格4个顶点的坐标
|
* @param {Array} points 网格中心点经纬度数组
|
*/
|
function parseGridPoint(points) {
|
if (points.length < 2) throw new Error('坐标点数量小于2');
|
const p1 = points[0];
|
const p2 = points[1];
|
// 两中心点间的角度
|
const angle = calculate.getAngle(p1[0], p1[1], p2[0], p2[1]);
|
// const angle = calculate.bearing(
|
// { latitude: p1[0], longitude: p1[1] },
|
// { latitude: p2[0], longitude: p2[1] }
|
// );
|
// 两中心点间的距离
|
const dis = calculate.getDistance(p1[0], p1[1], p2[0], p2[1]);
|
// 网格正方形对角线的一半长度
|
const halfDiagonal = Math.sqrt((dis / 2) * (dis / 2) * 2);
|
// 计算首个正方形各顶点相对于中心点的角度,得到正方形各顶点的坐标
|
const angle1 = plusAngle(angle, 45);
|
const gp1 = calculate.getLatLon(p1, halfDiagonal, angle1);
|
const angle2 = plusAngle(angle1, 90);
|
const gp2 = calculate.getLatLon(p1, halfDiagonal, angle2);
|
const angle3 = plusAngle(angle2, 90);
|
const gp3 = calculate.getLatLon(p1, halfDiagonal, angle3);
|
const angle4 = plusAngle(angle3, 90);
|
const gp4 = calculate.getLatLon(p1, halfDiagonal, angle4);
|
// 计算4个顶点分别与中心点的经纬度差值
|
const diff = {
|
diff1: {
|
dx: gp1[0] - p1[0],
|
dy: gp1[1] - p1[1]
|
},
|
diff2: {
|
dx: gp2[0] - p1[0],
|
dy: gp2[1] - p1[1]
|
},
|
diff3: {
|
dx: gp3[0] - p1[0],
|
dy: gp3[1] - p1[1]
|
},
|
diff4: {
|
dx: gp4[0] - p1[0],
|
dy: gp4[1] - p1[1]
|
}
|
};
|
|
// 得到所有正方形网格的4个顶点信息
|
return points.map((p) => {
|
return [
|
[p[0] + diff.diff1.dx, p[1] + diff.diff1.dy],
|
[p[0] + diff.diff2.dx, p[1] + diff.diff2.dy],
|
[p[0] + diff.diff3.dx, p[1] + diff.diff3.dy],
|
[p[0] + diff.diff4.dx, p[1] + diff.diff4.dy]
|
];
|
});
|
}
|
|
/**
|
* 文本标记
|
* 可修改position
|
*/
|
function textMaker(position, text, anchor, type) {
|
let style = {};
|
if (type == 'data') {
|
style = {
|
'font-size': '12px',
|
'text-align': 'center',
|
color: 'white',
|
background: '#122b54a9',
|
'text-shadow': 'black 2px 2px 2px',
|
border: '0px',
|
'margin-top': '4px'
|
};
|
} else if (type == 'rank') {
|
style = {
|
'font-size': '14px',
|
'text-align': 'center',
|
color: 'white',
|
background: 'transparent',
|
'text-shadow': 'black 2px 2px 2px',
|
'border-radius': '2px',
|
border: '1px solid #122b54a9',
|
'margin-bottom': '4px'
|
};
|
}
|
// eslint-disable-next-line no-undef
|
return new AMap.Text({
|
text: text,
|
anchor,
|
position: position,
|
style: style
|
});
|
}
|
|
/**
|
* 海量文本标注
|
*/
|
function textLabelMarker(position, text, direction, style) {
|
// eslint-disable-next-line no-undef
|
return new AMap.LabelMarker({
|
position: position,
|
zooms: [10, 20],
|
opacity: 1,
|
zIndex: 2,
|
// icon: {
|
// image: 'https://a.amap.com/jsapi_demos/static/images/poi-marker.png',
|
// anchor: 'bottom-center',
|
// size: [25, 34],
|
// clipOrigin: [459, 92],
|
// clipSize: [50, 68]
|
// },
|
text: {
|
// 注意内容格式必须是string
|
content: text ? text + '' : '',
|
direction: direction ? direction : 'center',
|
style: {
|
'border-radius': '.25rem',
|
fontSize: 12,
|
fillColor: '#fff',
|
strokeColor: 'rgba(0, 0, 0, 1)',
|
strokeWidth: 4,
|
// backgroundColor: '#122b54a9',
|
padding: [3, 10],
|
// backgroundColor: 'yellow',
|
borderColor: '#ccc',
|
borderWidth: 30
|
}
|
}
|
});
|
}
|
|
export default {
|
parseGridPoint,
|
|
/**
|
* 绘制网格风险图
|
* @param {*} points
|
*/
|
drawRectangle(points) {
|
const gridViews = [];
|
points.forEach((p) => {
|
const { lb, rt, c } = p;
|
|
let pList = [lb, rt].map((v) => {
|
// eslint-disable-next-line no-undef
|
return new AMap.LngLat(v[0], v[1]);
|
});
|
// eslint-disable-next-line no-undef
|
var bounds = new AMap.Bounds(...pList);
|
// eslint-disable-next-line no-undef
|
var rectangle = new AMap.Rectangle({
|
bounds: bounds,
|
strokeColor: '#ffffffff',
|
strokeWeight: 1,
|
strokeOpacity: 1,
|
// strokeStyle还支持 solid
|
strokeStyle: 'solid',
|
fillColor: '#990D0D',
|
fillOpacity: 0.8,
|
cursor: 'pointer',
|
zIndex: 50
|
});
|
gridViews.push(rectangle);
|
});
|
map.add(gridViews);
|
map.setFitView(gridViews);
|
},
|
|
/**
|
* 绘制一组多边形
|
* @param {*} points
|
*/
|
drawPolylines(points) {
|
const gridViews = [];
|
points.forEach((p) => {
|
let path = p.map((v) => {
|
// eslint-disable-next-line no-undef
|
return new AMap.LngLat(v[0], v[1]);
|
});
|
//创建多边形 Polygon 实例
|
// eslint-disable-next-line no-undef
|
var polygon = new AMap.Polygon({
|
path: path, //路径
|
fillColor: '#fff', //多边形填充颜色
|
strokeWeight: 1, //线条宽度,默认为 2
|
strokeColor: 'white', //线条颜色
|
fillOpacity: 0
|
});
|
gridViews.push(polygon);
|
});
|
map.add(gridViews);
|
map.setFitView(gridViews);
|
return gridViews;
|
},
|
|
drawGridText(points, textViews, anchor, type) {
|
if (textViews) {
|
points.forEach((p, i) => {
|
textViews[i].setPosition(p.lnglat_GD);
|
textViews[i].setText(p.data);
|
});
|
return { textViews };
|
} else {
|
const _textViews = [];
|
points.forEach((p) => {
|
const m = textMaker(p.lnglat_GD, p.data, anchor, type);
|
_textViews.push(m);
|
});
|
map.add(_textViews);
|
return { textViews: _textViews };
|
}
|
},
|
|
drawGridTextLabel(points, textViews, labelsLayer, direction) {
|
if (textViews) {
|
points.forEach((p, i) => {
|
textViews[i].setPosition(p.lnglat_GD);
|
textViews[i].setText({
|
content: p.data ? p.data + '' : ''
|
});
|
});
|
return { textViews, labelsLayer };
|
} else {
|
// 创建一个 LabelsLayer 实例来承载 LabelMarker,[LabelsLayer 文档](https://lbs.amap.com/api/jsapi-v2/documentation#labelslayer)
|
// eslint-disable-next-line no-undef
|
const labelsLayer = new AMap.LabelsLayer({
|
zooms: [12, 20],
|
zIndex: 1000,
|
// 开启标注避让,默认为开启,v1.4.15 新增属性
|
collision: false,
|
// 开启标注淡入动画,默认为开启,v1.4.15 新增属性
|
animation: false
|
});
|
const _textViews = [];
|
points.forEach((p) => {
|
const m = textLabelMarker(p.lnglat_GD, p.data, direction);
|
_textViews.push(m);
|
// 将 LabelMarker 实例添加到 LabelsLayer 上
|
labelsLayer.add(m);
|
});
|
map.add(labelsLayer);
|
// map.on('zoomend', () => {
|
// console.log(map.getZoom());
|
// });
|
return { textViews: _textViews, labelsLayer };
|
}
|
},
|
|
drawGridColor(gridViews, texts, factorName) {
|
gridViews.forEach((g, i) => {
|
const data = parseFloat(texts[i]);
|
const { color, nextColor, range, nextRange } =
|
Legend.getStandardColorAndNext(factorName, data);
|
const ratio = (data - range) / (nextRange - range);
|
const _color = getColorBetweenTwoColors(
|
color.map((v) => v * 255),
|
nextColor.map((v) => v * 255),
|
ratio
|
);
|
g.setOptions({
|
fillColor: _color,
|
fillOpacity: color[3] == 0 ? 0 : 0.7
|
});
|
});
|
},
|
|
drawGridColorCustom(gridViews, texts) {
|
var max, min;
|
texts.forEach((t) => {
|
if (!t) return;
|
if (!max || t > max) {
|
max = t;
|
}
|
if (!min || t < min) {
|
min = t;
|
}
|
});
|
gridViews.forEach((g, i) => {
|
const data = parseFloat(texts[i]);
|
const { color, nextColor, range, nextRange } =
|
Legend.getCustomColorAndNext(data, min, max);
|
const ratio = (data - range) / (nextRange - range);
|
|
const _color = getColorBetweenTwoColors(
|
color.map((v) => v * 255),
|
nextColor.map((v) => v * 255),
|
ratio
|
);
|
g.setOptions({
|
fillColor: _color,
|
// fillOpacity: color[3]
|
fillOpacity: color[3] == 0 ? 0 : 0.7
|
});
|
});
|
}
|
};
|