WholeProcessPlatform/frontend/src/components/gis/gisUtils.ts

544 lines
15 KiB
TypeScript

// import { Session } from '@zebras/qgc-share/service/Session'
import domtoimage from 'dom-to-image';
import {
offset2,
drawDotImg2,
drawDotImg1,
offset1,
drawDotImg3,
offset3,
drawDotImg5,
offset5
} from '@/utils/GisUrlList';
declare global {
interface Window {
__lyConfigs?: {
theme?: string;
[key: string]: any; // 根据实际配置结构补充具体字段,或使用索引签名兼容其他属性
};
__mapMode?: string; // 建议同时声明代码中用到的其他全局变量
}
}
console.log(import.meta.env.VITE_APP_ATTACHMENT_URL);
/**
* 根据镜头高度获取地图级别
* @param {Number} height
*/
const A = 40487.57;
const B = 0.00007096758;
const C = 91610.74;
const D = -40467.74;
/**
* 图例数据转对象
* @param data 图例数据
* @returns 以nameEn为下标的图例数据
*/
export const legendData2Obj = (data: any[]) => {
const _tempData: any = {};
const f = (_data: any[]) => {
_data.forEach(item => {
// childrenList有值表示这是一个分组
if (item?.childrenList && item.childrenList?.length > 0) {
f(item.childrenList);
} else {
if (item.nameEn.includes('_测试')) {
item.nameEn = item.nameEn.split('_测试')[0];
}
_tempData[item.nameEn] = item;
}
});
};
f(data);
return _tempData;
};
/**
* 添加标签偏移量等属性到item中
* @param item - 待添加属性的item
* @param index - item的索引
* @param labelType - 标签类型
*/
export const appendOffsetPropties = (item: any, index: any, labelType = 2) => {
let drawDotImg = null;
let offset = null;
if (labelType == 2) {
drawDotImg = drawDotImg1;
offset = offset1;
addItemProperty(item, index, drawDotImg, offset);
} else if (labelType == 3) {
drawDotImg = drawDotImg2;
offset = offset2;
addItemProperty(item, index, drawDotImg, offset);
} else if (labelType == 4) {
drawDotImg = drawDotImg3;
offset = offset3;
addItemProperty2(item, index, drawDotImg, offset);
} else if (labelType == 5) {
drawDotImg = drawDotImg5;
offset = offset5;
addItemProperty2(item, index, drawDotImg, offset);
}
};
const addItemProperty2 = (
item: any,
index: any,
drawDotImg: any,
offset: any
) => {
if (!drawDotImg || !offset) return;
item.icon_image =
index % 2 !== 0
? drawDotImg[item.anchoPointState]?.left || ''
: drawDotImg[item.anchoPointState]?.right || '';
item.text_anchor = index % 2 !== 0 ? 'right' : 'left';
item.text_offset = offset[item.icon_image]?.text_offset ?? [-10, -1.8];
item.text_offset2 = offset[item.icon_image]?.text_offset2 ?? [-10, -1.8];
item.icon_offset = [
offset[item.icon_image]?.icon_x ?? -200,
offset[item.icon_image]?.icon_y ?? -50
];
item.icon_offset2 = offset[item.icon_image]?.icon_offset2 ?? [-200, -50];
item.billboard_offset = [
offset[item.icon_image]?.billboard_x ?? -80,
offset[item.icon_image]?.billboard_y ?? -15
];
item.label_offset = offset[item.icon_image]?.labelOffset ?? [100, 41];
};
export const addItemProperty = (
item: any,
index: any,
drawDotImg: any,
offset: any
) => {
if (!drawDotImg || !offset) return;
item.icon_image =
index % 2 !== 0
? drawDotImg[item.anchoPointState]?.left || ''
: drawDotImg[item.anchoPointState]?.right || '';
item.text_offset = [
offset[item.icon_image]?.text_x ?? -10,
offset[item.icon_image]?.text_y ?? -1.8
];
item.icon_offset = [
offset[item.icon_image]?.icon_x ?? -200,
offset[item.icon_image]?.icon_y ?? -50
];
item.billboard_offset = [
offset[item.icon_image]?.billboard_x ?? -80,
offset[item.icon_image]?.billboard_y ?? -15
];
item.label_offset = offset[item.icon_image]?.labelOffset ?? [100, 41];
};
/**
* 设置popName属性
* @param item - 待设置popName的item
*/
export const setPopName = (item: any) => {
if (item.sttp === 'ENG') {
item.popName = item.ennm || item.titleName;
} else if (item.sttp === 'ylfb') {
if (item?.ftp?.length > 20) {
item.popName = item.ftp.slice(0, 20) + '...';
} else {
item.popName = item?.ftp;
}
} else if (item.sttp === 'WE_FISH') {
item.popName =
item.fishList?.[0]?.fishName + `(${item.fishList?.[0]?.ptypeName})`;
item.popName1 = item.total + '尾';
} else {
item.popName = item.stnm || item.titleName;
}
};
/**
* 获取图例配置中选中项的key
* @param data - 图例配置数据
* @returns 选中项的key数组
*/
export const getCheckedLayerConfigs = (data: any[]): any[] => {
const rs: any[] = [];
const f = (arr: any[] = []) => {
let count = 0;
arr.forEach((item: any) => {
if (item?.children && item.children.length > 0) {
const childrenCount = f(item.children);
if (childrenCount) {
rs.push(item.key);
}
} else if (item.checked) {
count++;
rs.push(item.key); // 对应图例的layerCode
}
});
return count;
};
f(data);
return rs;
};
// type mapType = "" | "pointMap" | "gisLayer"
/**
* 将图层配置数据转换为一维数组
* @param data - 图层配置数据
* @returns 一维数组
*/
export const layerConfig2Flat = (data: any): any[] => {
const rs: any[] = [];
const f = (arr: any[] = []) => {
arr.forEach((item: any) => {
const { type } = item;
if (type) {
if (type == 'GISMap') {
if (item?.children && item.children.length > 0) {
f(item.children);
} else {
rs.push(item);
}
} else if (type == 'pointMap') {
if (
item.url ||
item.title === '国家水文站' ||
item.title === '自建水文站'
) {
rs.push(item);
} else if (item.children.length > 0) {
f(item.children);
}
}
} else if (item.children.length > 0) {
f(item.children);
}
});
};
f(data);
return rs;
};
/**
* 替换图层配置中的 URL
* @param layerConfigsArr - 图层配置数组
* @param urlList - URL 配置列表
* @returns 更新后的图层配置数组
*/
export const replaceUrl = (layerConfigsArr: any[], urlList: any[]): any[] => {
const bDict: Record<string, any[]> = {};
// 构建 URL 映射字典
for (let i = 0; i < urlList.length; i++) {
const key = urlList[i].url;
const title = urlList[i].title;
const keyType = urlList[i].keyType;
if (!bDict[key]) bDict[key] = [];
if (!bDict[title]) bDict[title] = [];
if (!bDict[keyType]) bDict[keyType] = [];
bDict[key].push(urlList[i]);
bDict[title].push(urlList[i]);
if (bDict[keyType]) {
bDict[keyType].push(urlList[i]);
}
}
// 替换图层配置中的 URL
for (let i = 0; i < layerConfigsArr.length; i++) {
const obj = layerConfigsArr[i];
const key = obj.url;
const title = obj.title;
const keyType = obj.key;
const bObjList = bDict[keyType] || bDict[title] || bDict[key];
if (bObjList && bObjList.length > 0) {
const bObj = bObjList[0];
obj.url = bObj.url;
obj.urlThd = bObj.url;
obj.params = bObj.params;
obj.orders = bObj.orders;
} else {
obj.url = '';
}
}
return layerConfigsArr;
};
/**
* 获取基础图层配置
* @param config - 接口获取的配置数据
* @returns 基础图层配置
*/
export const getMapConfig = (config: any) => {
const r = { ...config };
const baseUrlObj = import.meta.env.VITE_APP_MAP_URL;
if (baseUrlObj) {
r.url = baseUrlObj + r.url; // 'http://localhost:8088'
r.url_3d = baseUrlObj + r.url_3d;
// r.url = baseUrlObj.url + r.url //baseUrlObj.url
// r.url_3d = baseUrlObj.url + r.url_3d
if (r.geojson_url) {
r.geojson_url = baseUrlObj + r.geojson_url;
}
}
return r;
};
/**
* 重置地图元素位置
*/
export const resetMapElPos = () => {
const legend = document.querySelector('#qgc-legendtl') as HTMLElement; // 图例
// const filter = document.querySelector('#map-filter-container') as HTMLElement // 全局表单
const controller = document.querySelector('#map-controller') as HTMLElement; // 地图工具栏
const baselayer = document.querySelector('#map-baselayer') as HTMLElement; // 底图模式切换
if (legend) {
legend.style.left = '0';
legend.style.bottom = '0';
}
if (controller) {
controller.style.right = '480px';
controller.style.bottom = '114px';
}
if (baselayer) {
baselayer.style.right = '480px';
baselayer.style.bottom = '20px';
}
};
/**
* 根据位置获取布局数据列表
* @param data - 布局数据
* @param position - 位置
* @returns 布局数据列表
*/
const getListByPosition = (data: any, position: string) =>
data?.data?.filter((el: any) => el.position === position && el.code);
/**
* 设置地图组件位置
* @param layoutType - 布局类型
* @param data - 布局数据
* @param offset - 偏移量
*/
export const setMapLegendPos = (
layoutType: string,
data: any,
offset = 456
) => {
const menuStateString = localStorage.getItem('menuState'); //处理澜沧江左侧菜单状态
const menuState =
menuStateString !== null ? JSON.parse(menuStateString) : true;
const _theme = localStorage.getItem('ly-theme') || window.__lyConfigs?.theme;
const leftEle = document.querySelector('#page-layout-left') as HTMLElement;
const rightEle = document.querySelector('#page-layout-right') as HTMLElement;
const bottomEle = document.querySelector(
'#page-layout-bottom'
) as HTMLElement;
const legend = document.querySelector('#qgc-legendtl') as HTMLElement; // 图例
const filter = document.querySelector('#map-filter-container') as HTMLElement; // 全局表单
const compassControl = document.querySelector(
'#map-compassControl'
) as HTMLElement; // 全局表单
const controller = document.querySelector('#map-controller') as HTMLElement; // 地图工具栏
const monitor = document.querySelector('#map-monitor') as HTMLElement; // 地图工具栏
const baselayer = document.querySelector('#map-baselayer') as HTMLElement; // 底图模式切换
// const vd = document.querySelector('#vd_operate') as HTMLElement // 底部视频
const left = [
'layout1',
'layout2',
'layout3',
'layout4',
'layout6',
'layout7',
'layout8',
'layout9',
'layout10',
'layout11',
'layout14',
'layout15',
'layout16',
'layout17'
]; // 左侧布局
const right = [
'layout1',
'layout2',
'layout3',
'layout4',
'layout5',
'layout6',
'layout8',
'layout10',
'layout11',
'layout15',
'layout16',
'layout17'
]; // 右侧布局
const bottom1 = [
'layout1',
'layout6',
'layout8',
'layout9',
'layout10',
'layout16'
]; // 三行底部布局
const bottom2 = ['layout2', 'layout15']; // 四行底部布局
const w = `${offset}px`;
const l = `${_theme === 'ly-8' ? (menuState ? 643 : 510) : offset}px`;
let b = `0px`;
const le = ['layout17', 'layout10'].includes(layoutType) ? 0 : 1;
const leftList = getListByPosition(data, 'left');
const rightList = getListByPosition(data, 'right');
const bottomList = getListByPosition(data, 'bottom');
let bottom = '0';
if (_theme === 'ly-8') {
if (window.__mapMode === '3D') {
b = `200px`;
} else {
b = `${menuState ? 200 : 50}px`;
}
}
if (bottomList?.length > 0) {
if (bottom1.includes(layoutType)) {
bottom = 'calc((100% - 16px) / 3 + 8px)';
}
if (bottom2.includes(layoutType)) {
bottom = 'calc((100% - 24px) / 4 + 8px)';
}
} else {
// 没有底部布局时,底部高度为
bottom = '28px';
}
const rle = ['layout6'].includes(layoutType) || bottom != '28px' ? 0 : 1;
const leftHide = leftEle?.classList?.contains('hide');
const rightHide = rightEle?.classList?.contains('hide');
const bottomHide = bottomEle?.classList?.contains('hide');
if (legend) {
legend.style.left =
!leftHide && left.includes(layoutType) && leftList?.length > le ? l : b;
legend.style.bottom = bottomHide
? '0'
: bottomList?.length > 0
? bottom
: '12px';
}
if (filter) {
if (layoutType === 'layout10') {
filter.style.left =
!leftHide && left.includes(layoutType) && leftList?.length > 1 ? l : b;
} else {
filter.style.left =
!leftHide &&
left.includes(layoutType) &&
leftList?.length > 0 &&
layoutType !== 'layout17'
? l
: b;
}
}
if (compassControl) {
if (layoutType === 'layout10') {
compassControl.style.left =
!leftHide && left.includes(layoutType) && leftList?.length > 1 ? l : b;
} else {
compassControl.style.left =
!leftHide &&
left.includes(layoutType) &&
leftList?.length > 0 &&
layoutType !== 'layout17'
? l
: b;
}
}
if (controller) {
controller.style.right =
!rightHide && right.includes(layoutType) && rightList?.length > rle
? w
: '0';
controller.style.bottom = bottomHide ? '0' : bottom;
}
if (monitor) {
monitor.style.right =
!rightHide && right.includes(layoutType) && rightList?.length > rle
? w
: '0';
// monitor.style.bottom = bottomHide ? '0' : bottom
}
if (baselayer) {
baselayer.style.right =
!rightHide && right.includes(layoutType) && rightList?.length > rle
? `calc(${w} + 60px)`
: '60px';
baselayer.style.bottom = bottomHide ? '0' : bottom;
}
};
export const altitudeToZoom = (height: number) => {
const lv =
Math.round(D + (A - D) / (1 + Math.pow(Number(height) / C, B))) + 1;
return lv > -1 ? lv : 0;
};
/**
* 根据地图级别获取镜头高度
* @param {Number} zoom
*/
export const zoomToAltitude = (zoom: number) => {
return Math.round(C * Math.pow((A - D) / (zoom - D) - 1, 1 / B));
};
export const mapOutPut = (imageUrl: string) => {
const canvas = document.createElement('canvas');
const downloadElement = document.createElement('a');
const mapElem = document.getElementById('mapContainer');
if (mapElem == null) {
return;
}
const context = canvas.getContext('2d')!;
canvas.width = mapElem.offsetWidth;
canvas.height = mapElem.offsetHeight;
const image = new Image();
image.src = imageUrl;
image.onload = () => {
context.drawImage(image, 0, 0);
const elem: any = document.getElementById('qgc-legendtl');
const l = elem?.style?.left === '' ? 0 : parseInt(elem?.style?.left);
if (elem) {
domtoimage
.toPng(elem, {
quality: 1.0,
width: elem.offsetWidth + (l + 24),
height: mapElem.offsetHeight - 20
})
.then((legendUrl: string) => {
const image = new Image();
image.src = legendUrl;
image.width = elem.offsetWidth;
image.onload = () => {
context.drawImage(image, 0, 0);
downloadElement.href = canvas.toDataURL('image/png');
downloadElement.download = '地图截图';
downloadElement.click();
};
})
.catch((e: any) => {
console.log('e', e);
});
} else {
downloadElement.href = canvas.toDataURL('image/png');
downloadElement.download = 'download';
downloadElement.click();
}
};
};