2026-04-20 16:57:54 +08:00
|
|
|
// 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'
|
2026-04-22 17:53:20 +08:00
|
|
|
declare global {
|
|
|
|
|
interface Window {
|
|
|
|
|
__lyConfigs?: {
|
|
|
|
|
theme?: string;
|
|
|
|
|
[key: string]: any; // 根据实际配置结构补充具体字段,或使用索引签名兼容其他属性
|
|
|
|
|
};
|
|
|
|
|
__mapMode?: string; // 建议同时声明代码中用到的其他全局变量
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-04-20 16:57:54 +08:00
|
|
|
/**
|
|
|
|
|
* 根据镜头高度获取地图级别
|
|
|
|
|
* @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[]) => {
|
2026-04-22 17:53:20 +08:00
|
|
|
const _tempData: any = {}
|
|
|
|
|
const f = (_data: any[]) => {
|
2026-04-20 16:57:54 +08:00
|
|
|
_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: number = 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
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取基础图层配置
|
|
|
|
|
* @param config - 接口获取的配置数据
|
|
|
|
|
* @returns 基础图层配置
|
|
|
|
|
*/
|
2026-04-22 17:53:20 +08:00
|
|
|
export const getMapConfig = () => {
|
2026-04-20 16:57:54 +08:00
|
|
|
// const mapBaseUrls = MemoryCache.get('mapBaseUrls') || {}
|
|
|
|
|
// const r = { ...config }
|
|
|
|
|
// const { urlType } = r
|
|
|
|
|
// const baseUrlObj = mapBaseUrls[urlType as string]
|
|
|
|
|
// if (baseUrlObj) {
|
|
|
|
|
// r.url = baseUrlObj.url + r.url // 'http://localhost:8088'
|
|
|
|
|
// r.url_3d = baseUrlObj.url + 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.url + r.geojson_url + `&token=${Session.getToken()?.accessToken}`
|
|
|
|
|
// }
|
|
|
|
|
// }
|
|
|
|
|
// return r
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 重置地图元素位置
|
|
|
|
|
*/
|
|
|
|
|
export const resetMapElPos = () => {
|
|
|
|
|
const legend = document.querySelector('#qgc-legendtl') as HTMLElement // 图例
|
2026-04-22 17:53:20 +08:00
|
|
|
// const filter = document.querySelector('#map-filter-container') as HTMLElement // 全局表单
|
2026-04-20 16:57:54 +08:00
|
|
|
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 布局数据列表
|
|
|
|
|
*/
|
2026-04-22 17:53:20 +08:00
|
|
|
const getListByPosition = (data: any, position: string) => data?.data?.filter((el: any) => el.position === position && el.code)
|
2026-04-20 16:57:54 +08:00
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 设置地图组件位置
|
|
|
|
|
* @param layoutType - 布局类型
|
|
|
|
|
* @param data - 布局数据
|
|
|
|
|
* @param offset - 偏移量
|
|
|
|
|
*/
|
2026-04-22 17:53:20 +08:00
|
|
|
export const setMapLegendPos = (layoutType: string, data: any, offset: number = 456) => {
|
2026-04-20 16:57:54 +08:00
|
|
|
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 // 底图模式切换
|
2026-04-22 17:53:20 +08:00
|
|
|
// const vd = document.querySelector('#vd_operate') as HTMLElement // 底部视频
|
2026-04-20 16:57:54 +08:00
|
|
|
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()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|