Skip to content

Commit

Permalink
【feature】 图层列表新增缩放至与设置透明度
Browse files Browse the repository at this point in the history
  • Loading branch information
xilanhuaweidapao committed Sep 27, 2024
1 parent 8aa5062 commit 30a29a8
Show file tree
Hide file tree
Showing 7 changed files with 408 additions and 21 deletions.
111 changes: 99 additions & 12 deletions src/mapboxgl/web-map/LayerGroup.vue
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@
>
<div v-if="zoomToMap.enabled" class="sm-component-layer-list__zoom">
<i
:class="attributesIconClass"
class="sm-components-icon-locate"
:style="!item.visible && { cursor: 'not-allowed' }"
:title="$t('layerList.zoomToMap')"
@click.stop="item.visible && toggleAttributesVisibility($event, item)"
@click.stop="zoomToBounds(item)"
/>
</div>
<div v-if="(item && item.type) !== 'group' && attributesEnabled(item)" class="sm-component-layer-list__attributes">
Expand All @@ -38,7 +38,7 @@
@click.stop="item.visible && toggleAttributesVisibility($event, item)"
/>
</div>
<div v-if="(item && item.type) !== 'group' && layerStyle.enabled" class="sm-component-layer-list__style">
<div v-if="layerStyle.enabled && (item && item.type) !== 'group'" class="sm-component-layer-list__style">
<i
:class="[
'sm-components-icon-attribute',
Expand All @@ -47,7 +47,7 @@
]"
:style="!item.visible && { cursor: 'not-allowed' }"
:title="$t('layerList.layerStyle')"
@click.stop="item.visible && toggleLayerStyleVisibility($event, item)"
@click.stop="item.visible && changeItemOpacity(item)"
/>
</div>
</div>
Expand All @@ -56,14 +56,14 @@
<div v-show="item.id === showOpacityItem" class="opacity-style">
<div>{{ $t('layerList.opacity') }}</div>
<sm-slider
:value="10"
:value="formatOpacity"
:min="0"
:max="100"
:step="1"
:style="{ ...getColorStyle(0), width: '70%' }"
@change="sliderChange"
@change="changeOpacity"
/>
<div>{{ 10 + '%' }}</div>
<div>{{ formatOpacity + '%' }}</div>
</div>
</template>
</sm-tree>
Expand All @@ -85,6 +85,10 @@ export default {
SmTree
},
props: {
currentOpacity: {
type: Number,
default: 0
},
layerCatalog: {
type: Array,
default() {
Expand Down Expand Up @@ -117,14 +121,17 @@ export default {
dropHandler: Function
},
computed: {
formatOpacity() {
return +(this.currentOpacity * 100).toFixed(0);
},
attributesIconClass() {
return (this.attributes && this.attributes.iconClass) || 'sm-components-icon-attribute';
},
attributesEnabled() {
return item => {
const isGeojson = item.renderSource.type === 'geojson';
const isStructureData = item.dataSource.type === 'STRUCTURE_DATA';
return this.attributes.enabled && (isGeojson || isStructureData);
const isGeojson = item.renderSource && item.renderSource.type === 'geojson';
const isStructureData = item.dataSource && item.dataSource.type === 'STRUCTURE_DATA';
return this.attributes.enabled && (isGeojson || isStructureData) && (item && item.type) !== 'group';
};
}
},
Expand Down Expand Up @@ -157,22 +164,102 @@ export default {
});
return treeData;
},
sliderChange(val) {},
changeOpacity(val) {
if (this.showOpacityItem) {
val = val / 100;
this.$emit('changeOpacity', this.showOpacityItem, val);
this.$emit('getLayerOpacityById', this.showOpacityItem);
}
},
toggleItemVisibility(item) {
this.$emit('toggleItemVisibility', item, !item.visible);
},
toggleAttributesVisibility(e, item) {
this.$emit('toggleAttributesVisibility', e, item);
},
toggleLayerStyleVisibility(e, item) {
changeItemOpacity(item) {
if (this.showOpacityItem === item.id) {
this.showOpacityItem = '';
} else {
this.showOpacityItem = item.id;
this.$emit('getLayerOpacityById', this.showOpacityItem);
}
},
changeIconsStatus(val) {
this.showIconsItem = val;
},
zoomToBounds(item) {
this.$emit('zoomToBounds', item);
},
onDrop(info) {
const dropKey = info.node.eventKey;
const dragKey = info.dragNode.eventKey;
const dropPos = info.node.pos.split('-');
const dropPosition = info.dropPosition - Number(dropPos[dropPos.length - 1]);
if (!info.dropToGap && this.getCatalogTypeById(this.layerCatalog, dropKey) !== 'group') {
return;
}
const loop = (data, id, callback) => {
data.forEach((item, index, arr) => {
if (item.id === id) {
return callback(item, index, arr);
}
if (item.children) {
return loop(item.children, id, callback);
}
});
};
const data = [...this.treeData];
// Find dragObject
let dragObj;
loop(data, dragKey, (item, index, arr) => {
arr.splice(index, 1);
dragObj = item;
});
if (!info.dropToGap) {
// Drop on the content
loop(data, dropKey, item => {
item.children = item.children || [];
// where to insert 示例添加到尾部,可以是随意位置
item.children.push(dragObj);
});
} else if (
(info.node.children || []).length > 0 && // Has children
info.node.expanded && // Is expanded
dropPosition === 1 // On the bottom gap
) {
loop(data, dropKey, item => {
item.children = item.children || [];
// where to insert 示例添加到尾部,可以是随意位置
item.children.unshift(dragObj);
});
} else {
let ar;
let i;
loop(data, dropKey, (item, index, arr) => {
ar = arr;
i = index;
});
if (dropPosition === -1) {
ar.splice(i, 0, dragObj);
} else {
ar.splice(i + 1, 0, dragObj);
}
}
this.treeData = data;
},
getCatalogTypeById(layerCatalog, id) {
for (let layer of layerCatalog) {
if (layer.id === id) {
return layer.type;
} else if (layer.type === 'group') {
const foundType = this.getTypeById(layer.children, id);
if (foundType) {
return foundType;
}
}
}
}
}
};
Expand Down
166 changes: 165 additions & 1 deletion src/mapboxgl/web-map/WebMapViewModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,32 @@ import echarts from 'echarts';
import EchartsLayer from 'vue-iclient/static/libs/echarts-layer/EchartsLayer';
import iPortalDataService from 'vue-iclient/src/common/_utils/iPortalDataService';
import proj4 from 'proj4';
import { getLayerCatalogIds } from 'vue-iclient/src/mapboxgl/web-map/GroupUtil';
import { getLayerCatalogIds, getGroupChildrenLayers, findLayerCatalog } from 'vue-iclient/src/mapboxgl/web-map/GroupUtil';
import bbox from '@turf/bbox';
import { points } from '@turf/helpers';

// @ts-ignore
window.echarts = echarts;
// @ts-ignore
window.EchartsLayer = EchartsLayer;

const OPACITY_MAP = {
circle: ['circle-opacity', 'circle-stroke-opacity'],
line: 'line-opacity',
fill: 'fill-opacity',
background: 'background-opacity',
symbol: ['icon-opacity', 'text-opacity'],
raster: 'raster-opacity',
heatmap: 'heatmap-opacity',
'line-extrusion': 'line-extrusion-opacity',
'fill-extrusion': 'fill-extrusion-opacity',
'point-extrusion': 'point-extrusion-opacity',
'line-curve-extrusion': 'line-curve-extrusion-opacity',
'line-curve': 'line-curve-opacity',
'heatmap-extrusion': 'heatmap-extrusion-opacity',
radar: 'radar-opacity'
};

// 迁徙图最大支持要素数量
/**
* @class WebMapViewModel
Expand Down Expand Up @@ -308,6 +327,143 @@ export default class WebMapViewModel extends Events {
this._handler.toggleLayerVisible(layer, visible);
}

zoomToBounds(id: string) {
const item = findLayerCatalog(this._handler.getLayerCatalog(), id);
if (!item) {
return;
}
const itemList = [];
if (item.type === 'group') {
const targetLayers = getGroupChildrenLayers(item.children);
itemList.push(...targetLayers);
} else {
itemList.push(item);
}
const sourceBoundsMap = {};
itemList.forEach(item => {
const sourceId = item.renderSource.id || item.id;
if (sourceBoundsMap[sourceId]) {
return;
}
const source = this.map.getSource(sourceId);
if (!source) {
if (item['CLASS_INSTANCE']) {
const instance = item['CLASS_INSTANCE'];
if (instance?.markers.length) {
const coordList = [];
instance?.markers.forEach(marker => {
coordList.push([marker.lngLat.lng, marker.lngLat.lat]);
});
const pointFeatures = points(coordList);
const bounds = bbox(pointFeatures);
sourceBoundsMap[sourceId] = bounds;
}
} else {
return;
}
}
// @ts-ignore
const bounds = source && source.bounds;
if (bounds) {
sourceBoundsMap[sourceId] = bounds;
} else if (source && source.type === 'geojson') {
// @ts-ignore
const datas = source.getData();
if (datas) {
const bounds = bbox(datas);
sourceBoundsMap[sourceId] = bounds;
}
}
});
const boundsList = [];
Object.keys(sourceBoundsMap).forEach(sourceId => {
const bounds = sourceBoundsMap[sourceId];
boundsList.push(bounds);
});
const maxBounds = this._getMaxBounds(boundsList);
if (maxBounds && !maxBounds.isEmpty()) {
this.map.fitBounds(maxBounds);
}
}

changeItemOpacity(id, opacity) {
const item = findLayerCatalog(this._handler.getLayerCatalog(), id);
if (!item) {
return;
}

if (item['CLASS_INSTANCE']) {
const instance = item['CLASS_INSTANCE'];
if (instance?.markers.length) {
instance?.markers.forEach(marker => {
marker.markerOption.element.style.opacity = opacity;
});
}
return;
}

if (item['CLASS_NAME'] && item['CLASS_NAME'] === 'L7Layer') {
const layer = this.map.getLayer(item.id);
// @ts-ignore
layer?.l7layer?.style({
opacity
});
// @ts-ignore
layer.reRender();
return;
}
item.renderLayers.forEach((layerId: string) => {
const layer = this.map.getLayer(layerId);
if (layer) {
let opacityName = OPACITY_MAP[layer.type];
opacityName = Array.isArray(opacityName) ? opacityName : [opacityName];
opacityName.forEach(fieldName => {
this.map.setPaintProperty(layerId, fieldName, opacity);
});
}
});
}

getLayerOpacityById(id) {
const item = findLayerCatalog(this._handler.getLayerCatalog(), id);
if (!item) {
return;
}

if (item['CLASS_INSTANCE']) {
const instance = item['CLASS_INSTANCE'];
const element = instance?.markers[0]?.markerOption?.element;
if (element) {
const opacity = element?.style?.opacity;
return opacity === '' ? 1 : +opacity;
}
return;
}

if (item['CLASS_NAME'] && item['CLASS_NAME'] === 'L7Layer') {
const layer = this.map.getLayer(item.id);
// @ts-ignore
let config = layer?.l7layer?.getLayerConfig();
return config?.opacity;
}
let opacity;
for (let i = 0; i < item.renderLayers.length; i++) {
const layerId = item.renderLayers[i];
const layer = this.map.getLayer(layerId);
if (layer) {
let opacityName = OPACITY_MAP[layer.type];
if (Array.isArray(opacityName)) {
opacityName = opacityName[0];
}
opacity = this.map.getPaintProperty(layerId, opacityName);
if (opacity !== undefined) {
break;
}
}
}
return opacity === undefined ? 1 : opacity;
}

setLayersVisible(isShow: boolean, ignoreIds: string[] = []) {
const visibility = isShow ? 'visible' : 'none';
const layers = this._cacheCleanLayers.filter(item => !ignoreIds.some(sub => sub === item.id));
Expand Down Expand Up @@ -344,6 +500,14 @@ export default class WebMapViewModel extends Events {
this._createMap();
}

private _getMaxBounds(bounds) {
let maxBounds = new mapboxgl.LngLatBounds();
bounds.forEach(bound => {
maxBounds.extend(bound);
});
return maxBounds;
}

private _mapInitializedHandler({ map }) {
this.map = map;
this.triggerEvent('mapinitialized', { map: this.map });
Expand Down
Loading

0 comments on commit 30a29a8

Please sign in to comment.