LinYeFangHuo/src/packages/components/Charts/Maps/MapLayer/index.vue

540 lines
16 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div ref="vChartRef" >
<div class="layer-container" @click="handlerMap"
:style="{'background-color':props.chartConfig.option.boxStyle?.backgroundColor,
'border-color':props.chartConfig.option.boxStyle?.borderColor}">
<div class="title">
{{ props.chartConfig.option.boxStyle?.title }}
</div>
<div class="layer-item-container">
<div v-for="(item,index) in handlerLayers" :key="index" style="color:#fff;">
<div class="layer-category">
<div class="arrow" @click="handnlerFoldGroupLayer(item)">
<CaretDownOutlined v-show="item.fold" />
<CaretRightOutlined v-show="!item.fold" />
</div>
<div class="layer-category-checkbox" :style="{'background':item.show ? '#00E832':'#fff'}" @click="handlerChangeAllLayer(item)">
</div>
<div class="layer-category-name">
{{ item.name }}{{item.children.length}}
</div>
</div>
<div class="layer-item" v-for="(it,idx) in item.children" :key="idx" v-show="item.fold">
<div class="layer-checkbox" :style="{'background':it.show ? '#00E832':'#fff'}" @click="handlerChangeLayer(it,item)">
<!-- <CheckOutlined v-show="it.show" /> -->
</div>
<div class="layer-name" @click="handlerChangeLayer(it,item)">
{{ it.name }}
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, PropType, toRefs, watch,onMounted,nextTick } from 'vue'
import AMapLoader from '@amap/amap-jsapi-loader'
import { CreateComponentType } from '@/packages/index.d'
import { useChartDataFetch } from '@/hooks'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { MarkerEnum, ThemeEnum } from './config'
import { isArray } from '@/utils';
import axios from 'axios';
import { CaretDownOutlined, StarFilled, StarTwoTone,CheckOutlined,CaretRightOutlined } from '@ant-design/icons-vue';
import * as mars3d from "mars3d";
import { option } from '@/views/chart/ContentConfigurations/components/CanvasPage/components/CreateColorRenderChart/barOptions'
import { EventBus } from '@/utils/eventBus';
let map: mars3d.Map; //
const props = defineProps({
chartConfig: {
type: Object as PropType<CreateComponentType>,
required: true
}
})
const layers = ref(null)
const handlerLayers:any = ref([]);
const handlerGetLayerTree = ()=>{
axios.get('http://221.2.83.254:9006/applicationMars/getApplicationInfo/feixian').then((res)=>{
layers.value = res.data.data
let configLayers = [];
let GEOSERVER_BASE_API = "http://221.2.83.254:9007/";
res.data.data.forEach((item, index) => {
let group:Object;
group = {
id: parseInt(Math.random() * 10000000),
name: item.serverName,
type: "group",
fold:true,
show:false,
};
let layerGroup = group;
layerGroup.children = [];
configLayers.unshift(group);
if (item.children && item.children.length > 0) {
item.children.forEach((it, idx) => {
let attribute = JSON.parse(it.attribute);
// 处理根据字段分类渲染样式的图层
if(attribute && attribute.symbol && attribute.symbol.styleField && attribute.symbol.styleFieldOptions && Object.keys(attribute.symbol.styleFieldOptions).length>0){
// console.log(attribute.layers,attribute)
attribute.type = 'geojson';
if(attribute.layers){
attribute.url = "geoserver/ksp/ows?service=WFS&version=1.0.0&request=GetFeature&typeName="+attribute.layers+"&maxFeatures=1000000&outputFormat=application%2Fjson";
}
// delete attribute.layers;
delete attribute.parameters;
delete attribute.highlight;
console.log("图层属性信息:",attribute.url,attribute);
if(!attribute.symbol.styleOptions){
attribute.symbol.styleOptions = {
"opacity": 0.8,
"color": "",
"width": 2,
"clampToGround": true
}
}
attribute.zIndex = 10000000000;
}
// 如果是动态线类型
if(attribute.dynamic){
attribute.type = 'geojson';
if(attribute.layers){
attribute.url = "geoserver/ksp/ows?service=WFS&version=1.0.0&request=GetFeature&typeName="+attribute.layers+"&maxFeatures=1000000&outputFormat=application%2Fjson";
attribute.symbol = {
type: "polyline",
styleOptions: {
clampToGround:true,
width: 5,
materialType: mars3d.MaterialType.LineFlow,
materialOptions: {
// color: Cesium.Color.CHARTREUSE,
image: "img/textures/line-color-yellow.png",
speed: 8
}
}
}
}
}
// 设置标签文字偏移量
if(attribute.symbol && attribute.symbol.styleOptions && attribute.symbol.styleOptions.label){
attribute.symbol.styleOptions.label.pixelOffsetY = -40
let oldText = attribute.symbol.styleOptions.label.text;
attribute.symbol.styleOptions.label = {
text: oldText,
font_size: 14,
// color: Cesium.Color.AZURE,
outline: true,
// outlineColor: Cesium.Color.BLACK,
outlineWidth: 2,
// horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
// verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
// pixelOffset: new Cesium.Cartesian2(10, -25) // 偏移量
pixelOffsetY:-40
}
}
// 设置PID
attribute.pid = group.id;
// 去掉所有图层点击选中样式
delete attribute.highlight;
// 如果不为空
if(attribute.symbol && attribute.symbol.styleOptions && attribute.symbol.styleOptions.label && attribute.symbol.styleOptions.label.text){
/**
* 图标标题显示情况:
key字段中文名称value字段英文名称
* 1. key:value
* 2. key:value@key:value
* 3. key:value@,@key:value
* 4. @value
* 5. @value1@value2
* 6. @value1@,@value2
* 7. key:value1@value2
* */
let text = "";
if(attribute.symbol.styleOptions.label.text.match("@")){
let arr = attribute.symbol.styleOptions.label.text.split("@");
if(arr.length>0){
arr.forEach((item,index)=>{
if(item.match(":")){
let garr = item.split(":")
text = text+garr[0]+":{"+garr[1]+"}"
}else if(item.length==1){
text = text+item
}else if(item.length>1){
text = text+"{"+item+"}"
}
})
}
}else if(attribute.symbol.styleOptions.label.text.length>1 && attribute.symbol.styleOptions.label.text.match(":") ){
let garr = attribute.symbol.styleOptions.label.text.split(":")
text = text+garr[0]+":{"+garr[1]+"}"
}else if(attribute.symbol.styleOptions.label.text.length>1 && !attribute.symbol.styleOptions.label.text.match(":")){
text = "{"+attribute.symbol.styleOptions.label.text+"}";
}
attribute.symbol.styleOptions.label.text = text;
}
let ipinfo = matchHttpIpPort(attribute.url);
if(ipinfo){ // 如果匹配得到则替换为配置文件中的
attribute.url = attribute.url.replace(ipinfo[0],GEOSERVER_BASE_API);
}else{ //如果没有匹配到则直接拼接
attribute.url = GEOSERVER_BASE_API+attribute.url
}
// 根据图层类型设置数据过滤条件 过滤掉被删除的数据
if(attribute.type == 'geojson'){
attribute.url = attribute.url + "&cql_filter=is_del%20=0"
}else if(attribute.type == 'wms'){
attribute.parameters.cql_filter="is_del=0"
attribute.zIndex = 1;
}
if(attribute.name == '防火驿站'){
attribute.show = true;
}
configLayers.unshift(attribute);
attribute.show = attribute.show ? true : false;
layerGroup.children.push(attribute);
});
}
handlerLayers.value.push(layerGroup);
});
console.log("configlayers",handlerLayers.value);
// window.globalMap.setLayersOptions(configLayers);
})
}
const matchHttpIpPort = (url) => { // 匹配“ http://ip:port ”
const ipRegex = /^http\:\/\/\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b\:\b[0-9]{1,5}\//;
const match = url.match(ipRegex)
if (match) {
return match;
}
return null;
}
const handlerChangeAllLayer = (group) =>{
if(group.show == false){
group.children?.forEach((item,index)=>{
item.show = true;
})
}else{
group.children?.forEach((item,index)=>{
item.show = false;
})
}
group.show = !group.show;
}
const handlerChangeLayer = (options,group)=>{
if(options.show == true){
group.show = false;
}
options.show = !options.show;
let layer = window.globalMap.getLayerById(options.id);
if(layer){
layer.show = !layer.show
}else{
if(options.type == "geojson"){
layer = new mars3d.layer.GeoJsonLayer(options);
layer.show = true;
}else if(options.type == "wms"){
layer = new mars3d.layer.WmsLayer(options);
layer.show = true;
}
window.globalMap.addLayer(layer);
}
}
const handnlerFoldGroupLayer = (item)=>{
item.fold = !item.fold;
}
const ch = ()=>{
}
const handlerMap = ()=>{
}
let {
amapKey,
amapStyleKey,
amapLon,
amapLat,
amapZindex,
mapMarkerType,
lang,
amapStyleKeyCustom,
features,
viewMode,
showLabel,
pitch,
skyColor,
marker,
satelliteTileLayer,
roadNetTileLayer,
trafficTileLayer
} = toRefs(props.chartConfig.option.mapOptions)
let mapIns: any = null
let markers: any = []
let AMapIns: any = null
const vChartRef = ref<HTMLElement>()
onMounted(()=>{
handlerGetLayerTree();
EventBus.on(props.chartConfig.id + 'GraphicClick', (data) => {
console.log('data', data);
});
})
const isFirstLoad = ref(true);
const initMap = (newData: any) => {
// 第一次加载
if(isFirstLoad.value){
map = new mars3d.Map(vChartRef.value, newData);
}else{ // 之后更新
// map.setOptions(newData);
map.setSceneOptions(newData.scene);
}
isFirstLoad.value = false;
window.globalMap = map;
return null;
// 初始化
AMapLoader.load({
key: amapKey.value, //api服务key--另外需要在public中使用安全密钥
version: '1.4.15', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15
plugins: ['AMap.PlaceSearch', 'AMap.AutoComplete'] // 需要使用的的插件列表
}).then(AMap => {
AMapIns = AMap
mapIns = new AMap.Map(vChartRef.value, {
resizeEnable: true,
zoom: amapZindex.value, // 地图显示的缩放级别
center: [amapLon.value, amapLat.value],
lang: lang.value,
features: features.value,
pitch: pitch.value, // 地图俯仰角度,有效范围 0 度- 83 度
skyColor: skyColor.value,
viewMode: viewMode.value, // 地图模式
showLabel: showLabel.value, // 是否显示地图文字标记
willReadFrequently: true
})
dataHandle(props.chartConfig.option.dataset)
let satelliteLayer = new AMap.TileLayer.Satellite({
zIndex: satelliteTileLayer.value.zIndex,
opacity: satelliteTileLayer.value.opacity,
zooms: satelliteTileLayer.value.zooms
})
let roadNetLayer = new AMap.TileLayer.RoadNet({
zIndex: roadNetTileLayer.value.zIndex,
opacity: roadNetTileLayer.value.opacity,
zooms: roadNetTileLayer.value.zooms
})
let trafficLayer = new AMap.TileLayer.Traffic({
zIndex: trafficTileLayer.value.zIndex,
opacity: trafficTileLayer.value.opacity,
zooms: trafficTileLayer.value.zooms
})
mapIns.remove([satelliteLayer, roadNetLayer, trafficLayer])
if (satelliteTileLayer.value.show) {
mapIns.add([satelliteLayer])
}
if (roadNetTileLayer.value.show) {
mapIns.add([roadNetLayer])
}
if (trafficTileLayer.value.show) {
mapIns.add([trafficLayer])
}
mapIns.setMapStyle(
`amap://styles/${amapStyleKeyCustom.value !== '' ? amapStyleKeyCustom.value : amapStyleKey.value}`
)
})
.catch(e => {})
}
const dataHandle = (newData: any) => {
if (!mapIns && !AMapIns) {
// initMap(props.chartConfig.option)
return
}
if (isArray(newData.markers)) {
// 先清除旧标记
mapIns.remove(markers)
markers = []
// 记录新标记
if (mapMarkerType.value === MarkerEnum.MARKER) {
newData.markers.forEach((markerItem: any) => {
const markerInstance = new AMapIns.Marker({
position: [markerItem.position[0], markerItem.position[1]],
offset: new AMapIns.Pixel(-13, -30)
})
markers.push(markerInstance)
markerInstance.setMap(mapIns)
})
} else if (mapMarkerType.value === MarkerEnum.CIRCLE_MARKER) {
newData.markers.forEach((markerItem: any) => {
const markerInstance = new AMapIns.CircleMarker({
center: [markerItem.position[0], markerItem.position[1]],
radius: markerItem.value,
...marker.value
})
markers.push(markerInstance)
markerInstance.setMap(mapIns)
})
}
}
}
const stopWatch = watch(
() => props.chartConfig.option.mapOptions,
async option => {
let options = JSON.parse(JSON.stringify(props.chartConfig.option.mapOptions))
console.log("props.chartConfig.option.mapOptions",);
await nextTick();
},
{
immediate: true,
deep: true
}
)
watch(
() => props.chartConfig.option.dataset,
newData => {
try {
dataHandle(newData)
} catch (error) {
console.log(error)
}
},
{
deep: false
}
)
// 预览
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
stopWatch()
dataHandle(newData)
})
</script>
<style scoped>
.layer-container{
width:100%;
height:100%;
padding:15px;
padding-top:0px;
padding-right:5px;
background:rgba(7,38,30,0.85);
border:1px solid #088538;
}
.layer-item-container{
width:100%;
height: calc( 100% - 50px);
overflow-y:auto;
}
.layer-container .title{
width:100%;
height:50px;
line-height:50px;
color:#CBE6CD;
font-size:16px;
}
.layer-category{
width:100%;
height:36px;
color:#CBE6CD;
font-size:16px;
line-height:36px;
display: flex;
}
.arrow{
font-size:22px;
cursor:pointer;
}
.layer-category-checkbox{
width:14px;
height:14px;
background:#fff;
margin-top:11px;
cursor:pointer;
border-radius:2px;
}
.layer-category-name{
flex:auto;
text-indent: 12px;
cursor:pointer;
}
.layer-item{
width:100%;
height:24px;
line-height:24px;
font-size:14px;
color: #CBE6CD;
display:flex;
padding-left:40px;
}
.layer-checkbox{
width:14px;
height:14px;
background:#fff;
margin-top:5px;
cursor:pointer;
border-radius:2px;
font-weight:bold;
}
.layer-name{
flex:auto;
text-indent: 12px;
cursor:pointer;
}
</style>