/** * 网格绘制 */ 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, color }) { let style = {}; if (type == 'data') { style = { 'font-size': '12px', 'text-align': 'center', 'font-weight': 600, color: color ? color : 'white', background: '#122b54a9', // background: 'white', 'text-shadow': 'black 1px 1px 1px', border: '0px', 'margin-top': '4px' }; } else if (type == 'rank') { style = { 'font-size': '14px', 'text-align': 'center', color: color ? color : 'white', background: 'transparent', 'text-shadow': 'black 2px 2px 2px', 'border-radius': '2px', border: '1px solid #122b54a9', // border: '1px solid rgba(255, 255, 255, 0.62)', '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 } } }); } /** * 计算每个网格颜色 */ function calGridColor({ factorName, data, isCustomColor }) { let _colorList = []; if (isCustomColor) { var max, min; data.forEach((t) => { if (!t) return; if (!max || t > max) { max = t; } if (!min || t < min) { min = t; } }); data.forEach((d) => { if (d) { // 根据遥测数据计算网格颜色 const { color, nextColor, range, nextRange } = Legend.getCustomColorAndNext(d, min, max); const ratio = (d - range) / (nextRange - range); const _color = getColorBetweenTwoColors( color.map((v) => v * 255), nextColor.map((v) => v * 255), ratio ); _colorList.push(_color); } else { _colorList.push(undefined); } }); } else { data.forEach((d) => { if (d) { // 根据遥测数据计算网格颜色 const { color, nextColor, range, nextRange } = Legend.getStandardColorAndNext(factorName, d); const ratio = (d - range) / (nextRange - range); const _color = getColorBetweenTwoColors( color.map((v) => v * 255), nextColor.map((v) => v * 255), ratio ); _colorList.push(_color); } else { _colorList.push(undefined); } }); } return _colorList; } 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 {Array} points 网格坐标点数组 * @param {Boolean} draw 是否创建完成后同时绘制 */ drawPolylines({ points, draw, event }) { const gridViews = []; points.forEach((p) => { //创建多边形 Polygon 实例 // eslint-disable-next-line no-undef var polygon = new AMap.Polygon({ path: p.path, //路径 fillColor: '#fff', //多边形填充颜色 strokeWeight: 1, //线条宽度,默认为 2 strokeColor: 'white', //线条颜色 fillOpacity: 0, extData: p.extData }); if (typeof event === 'function') { event(polygon); } gridViews.push(polygon); }); if (draw) { map.add(gridViews); map.setFitView(gridViews); } return gridViews; }, drawGridText({ points, textViews, anchor, type, isCustomColor, useColor }) { let colorList = []; if (useColor) { colorList = calGridColor({ factorName: 'PM25', data: points.map((p) => p.data), isCustomColor: isCustomColor }); } if (textViews) { map.remove(textViews); } const _textViews = []; points.forEach((p, i) => { const m = textMaker({ position: p.lnglat_GD, text: p.data, anchor, type, color: useColor ? colorList[i] : 'white' }); _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 }; } }, /** * 根据遥测数据,设置对应网格的标准色,返回有数据的网格 * @param {Array} gridViews 网格多边形对象数组 * @param {Array} gridDataDetail 卫星遥测数据数组 * @param {string} factorName 监测因子名称 * @param {number} opacity 透明度 */ drawGridColor(gridViews, gridDataDetail, factorName, opacity, zIndex) { const res = []; // 遍历卫星遥测数据数组 gridDataDetail.forEach((d, i) => { if (d.pm25) { const grid = gridViews[i]; // 根据遥测数据计算网格颜色 const data = d.pm25; 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 ); grid.setOptions({ zIndex: zIndex ? zIndex : 10, fillColor: _color, fillOpacity: opacity ? opacity : color[3] == 0 ? 0 : 0.7 }); res.push(grid); } }); return res; }, drawGridColorCustom(gridViews, gridDataDetail, opacity) { var max, min; gridDataDetail.forEach((t) => { if (!t.pm25) return; if (!max || t.pm25 > max) { max = t.pm25; } if (!min || t.pm25 < min) { min = t.pm25; } }); const res = []; // 遍历卫星遥测数据数组 gridDataDetail.forEach((d, i) => { if (d.pm25) { const grid = gridViews[i]; // 根据遥测数据计算网格颜色 const data = d.pm25; 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 ); grid.setOptions({ fillColor: _color, fillOpacity: opacity ? opacity : color[3] == 0 ? 0 : 0.7 }); res.push(grid); } }); return res; } };