410 lines
14 KiB
Vue
410 lines
14 KiB
Vue
|
|
<template>
|
||
|
|
<view class="app-content">
|
||
|
|
<view id="map" style="width: 100%;height: 100%;"></view>
|
||
|
|
</view>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
import 'ol/ol.css';
|
||
|
|
import Map from 'ol/Map';
|
||
|
|
import View from 'ol/View';
|
||
|
|
import TileLayer from 'ol/layer/Tile';
|
||
|
|
import SourceVector from 'ol/source/Vector';
|
||
|
|
import LayerVector from 'ol/layer/Vector';
|
||
|
|
import * as control from 'ol/control';
|
||
|
|
import {
|
||
|
|
toLonLat
|
||
|
|
} from 'ol/proj';
|
||
|
|
import Overlay from 'ol/Overlay';
|
||
|
|
import {
|
||
|
|
toStringHDMS
|
||
|
|
} from 'ol/coordinate';
|
||
|
|
import {
|
||
|
|
Select
|
||
|
|
} from 'ol/interaction'
|
||
|
|
import {
|
||
|
|
GeoJSON
|
||
|
|
} from 'ol/format';
|
||
|
|
import {
|
||
|
|
Style,
|
||
|
|
Circle,
|
||
|
|
Fill,
|
||
|
|
Stroke,
|
||
|
|
Icon,
|
||
|
|
Text
|
||
|
|
} from 'ol/style';
|
||
|
|
import Feature from 'ol/Feature';
|
||
|
|
import {
|
||
|
|
Point,
|
||
|
|
Polygon
|
||
|
|
} from 'ol/geom';
|
||
|
|
import {
|
||
|
|
Logo,
|
||
|
|
TileSuperMapRest,
|
||
|
|
FeatureService,
|
||
|
|
GetFeaturesByGeometryParameters
|
||
|
|
} from '@supermap/iclient-ol';
|
||
|
|
const geoJSONParser = new GeoJSON();
|
||
|
|
let mypoint = require('@/static/img/mypoint.png');
|
||
|
|
export default {
|
||
|
|
name: "uMapView",
|
||
|
|
props: {
|
||
|
|
latitude: {
|
||
|
|
required: true,
|
||
|
|
},
|
||
|
|
longitude: {
|
||
|
|
required: true,
|
||
|
|
},
|
||
|
|
zoom: {
|
||
|
|
type: Number,
|
||
|
|
required: false,
|
||
|
|
default: 10,
|
||
|
|
},
|
||
|
|
maxZoom: {
|
||
|
|
type: Number,
|
||
|
|
required: false,
|
||
|
|
default: 20,
|
||
|
|
},
|
||
|
|
minZoom: {
|
||
|
|
type: Number,
|
||
|
|
required: false,
|
||
|
|
default: 0,
|
||
|
|
},
|
||
|
|
ScaleZoom: {
|
||
|
|
type: Boolean,
|
||
|
|
required: false,
|
||
|
|
default: false,
|
||
|
|
},
|
||
|
|
MapUrl: { // 瓦片地图URL
|
||
|
|
type: String,
|
||
|
|
required: true,
|
||
|
|
default: '',
|
||
|
|
},
|
||
|
|
flagTip: {
|
||
|
|
type: Boolean,
|
||
|
|
required: false,
|
||
|
|
default: false,
|
||
|
|
},
|
||
|
|
open: {
|
||
|
|
type: Boolean,
|
||
|
|
required: false,
|
||
|
|
default: false,
|
||
|
|
},
|
||
|
|
init: {
|
||
|
|
type: Boolean,
|
||
|
|
required: false,
|
||
|
|
default: true,
|
||
|
|
}
|
||
|
|
},
|
||
|
|
data() {
|
||
|
|
return {
|
||
|
|
// 实例化对象
|
||
|
|
map: null,
|
||
|
|
addPointsSource: null,
|
||
|
|
vectorSource: null,
|
||
|
|
vectorSourceIcon: null,
|
||
|
|
vectorLayerIcon: null,
|
||
|
|
selectInteraction: null,
|
||
|
|
helpTooltipElement: null,
|
||
|
|
helpTooltip: null,
|
||
|
|
isclearPoint: null,
|
||
|
|
overlay: null,
|
||
|
|
// 控制参数
|
||
|
|
isShowToolTip: false,
|
||
|
|
};
|
||
|
|
},
|
||
|
|
mounted() {
|
||
|
|
if (this.init) {
|
||
|
|
this.initMap()
|
||
|
|
}
|
||
|
|
},
|
||
|
|
methods: {
|
||
|
|
initMap(options) {
|
||
|
|
let lat, lon;
|
||
|
|
if (options) {
|
||
|
|
lat = options.lat
|
||
|
|
lon = options.lon
|
||
|
|
} else {
|
||
|
|
lat = this.latitude
|
||
|
|
lon = this.longitude
|
||
|
|
}
|
||
|
|
this.map = new Map({
|
||
|
|
target: 'map',
|
||
|
|
controls: control.defaults({
|
||
|
|
attribution: false,
|
||
|
|
zoom: this.ScaleZoom,
|
||
|
|
}),
|
||
|
|
layers: [
|
||
|
|
new TileLayer({ // 使用瓦片
|
||
|
|
source: new TileSuperMapRest({
|
||
|
|
url: this.MapUrl,
|
||
|
|
wrapX: true,
|
||
|
|
}),
|
||
|
|
projection: 'EPSG:4326',
|
||
|
|
}),
|
||
|
|
],
|
||
|
|
view: new View({
|
||
|
|
center: [lon, lat],
|
||
|
|
maxZoom: this.maxZoom,
|
||
|
|
minZoom: this.minZoom,
|
||
|
|
zoom: this.zoom,
|
||
|
|
projection: 'EPSG:4326',
|
||
|
|
})
|
||
|
|
});
|
||
|
|
//添加查询结果图层
|
||
|
|
this.vectorSource = new SourceVector({
|
||
|
|
wrapX: false
|
||
|
|
});
|
||
|
|
const resultLayer = new LayerVector({
|
||
|
|
source: this.vectorSource,
|
||
|
|
});
|
||
|
|
|
||
|
|
//添加点图层
|
||
|
|
this.addPointsSource = new SourceVector({
|
||
|
|
wrapX: false
|
||
|
|
});
|
||
|
|
const addPointsLayer = new LayerVector({
|
||
|
|
source: this.addPointsSource,
|
||
|
|
});
|
||
|
|
this.map.addLayer(addPointsLayer);
|
||
|
|
this.map.addLayer(resultLayer);
|
||
|
|
this.map.on('pointermove', (e) => {
|
||
|
|
if (this.isShowToolTip) {
|
||
|
|
this.helpTooltip.setPosition(undefined);
|
||
|
|
this.helpTooltipElement.classList.add('hidden');
|
||
|
|
}
|
||
|
|
this.$emit('regionchange', e.pixel)
|
||
|
|
});
|
||
|
|
this.map.on('singleclick', (e) => {
|
||
|
|
this.$emit('clickMap', e.coordinate)
|
||
|
|
});
|
||
|
|
|
||
|
|
if (this.open) {
|
||
|
|
this.addFeature([{
|
||
|
|
id: 1,
|
||
|
|
latitude: lat,
|
||
|
|
longitude: lon,
|
||
|
|
iconPath: mypoint,
|
||
|
|
title: '',
|
||
|
|
width: 20,
|
||
|
|
height: 20
|
||
|
|
}])
|
||
|
|
}
|
||
|
|
|
||
|
|
if (this.flagTip) {
|
||
|
|
this.createHelpTooltip()
|
||
|
|
}
|
||
|
|
|
||
|
|
},
|
||
|
|
addMarker(point) {
|
||
|
|
console.log('point', point)
|
||
|
|
// this.ceateMarker([104.404419, 31.133980])
|
||
|
|
},
|
||
|
|
addFeature(covers) {
|
||
|
|
console.log(covers)
|
||
|
|
const features = covers.map((item) => ({
|
||
|
|
type: 'Feature',
|
||
|
|
geometry: {
|
||
|
|
type: 'Point',
|
||
|
|
coordinates: [item.longitude, item.latitude],
|
||
|
|
},
|
||
|
|
properties: {
|
||
|
|
iconPath: item.iconPath,
|
||
|
|
text: item.title,
|
||
|
|
value: JSON.stringify(item),
|
||
|
|
scale: item.id === 1 ? [0.15, 0.15] : [0.1, 0.1]
|
||
|
|
}
|
||
|
|
}))
|
||
|
|
this.careateFeature(features)
|
||
|
|
|
||
|
|
},
|
||
|
|
ceateMarker(point) {
|
||
|
|
// 创建一个坐标点
|
||
|
|
const pointed = new Point(point); // 这里的[0, 0]应该替换为您的经度和纬度
|
||
|
|
|
||
|
|
// 创建一个特征
|
||
|
|
const pointFeature = new Feature({
|
||
|
|
geometry: pointed,
|
||
|
|
name: 'My Point'
|
||
|
|
});
|
||
|
|
|
||
|
|
pointFeature.setStyle(new Style({
|
||
|
|
image: new Circle({
|
||
|
|
fill: new Fill({
|
||
|
|
color: [255, 0, 0, 0.5]
|
||
|
|
}),
|
||
|
|
stroke: new Stroke({
|
||
|
|
color: 'red',
|
||
|
|
width: 2
|
||
|
|
}),
|
||
|
|
radius: 8
|
||
|
|
})
|
||
|
|
}));
|
||
|
|
|
||
|
|
pointFeature.setProperties({
|
||
|
|
POP: 1,
|
||
|
|
CAPITAL: 'test'
|
||
|
|
});
|
||
|
|
this.addPointsSource.clear()
|
||
|
|
// 将特征添加到矢量图层
|
||
|
|
this.addPointsSource.addFeature(pointFeature);
|
||
|
|
// 确保更新地图视图以显示新的标点
|
||
|
|
this.map.getView().fit(this.addPointsSource.getExtent());
|
||
|
|
// // 或者移动视图
|
||
|
|
// _this.map.getView().animate({
|
||
|
|
// duration: 850,
|
||
|
|
// zoom: 5,
|
||
|
|
// center: point,
|
||
|
|
// });
|
||
|
|
|
||
|
|
},
|
||
|
|
careateFeature(result) {
|
||
|
|
if (this.vectorSourceIcon) {
|
||
|
|
this.vectorSourceIcon.clear()
|
||
|
|
const geojsonObject = {
|
||
|
|
type: 'FeatureCollection',
|
||
|
|
features: result,
|
||
|
|
};
|
||
|
|
this.vectorSourceIcon.addFeatures(geoJSONParser.readFeatures(geojsonObject))
|
||
|
|
this.vectorSourceIcon.changed()
|
||
|
|
return
|
||
|
|
}
|
||
|
|
|
||
|
|
const geojsonObject = {
|
||
|
|
type: 'FeatureCollection',
|
||
|
|
features: result,
|
||
|
|
};
|
||
|
|
// 创建一个图层作为点位
|
||
|
|
this.vectorSourceIcon = new SourceVector({
|
||
|
|
features: geoJSONParser.readFeatures(geojsonObject)
|
||
|
|
});
|
||
|
|
this.vectorLayerIcon = new LayerVector({
|
||
|
|
source: this.vectorSourceIcon,
|
||
|
|
style: feature => {
|
||
|
|
return new Style({
|
||
|
|
image: new Icon({
|
||
|
|
anchor: [0.5, 0.9],
|
||
|
|
scale: feature.get('scale'),
|
||
|
|
src: feature.get('iconPath'),
|
||
|
|
}),
|
||
|
|
text: new Text({
|
||
|
|
text: feature.get('text'),
|
||
|
|
fill: new Fill({
|
||
|
|
color: '#000'
|
||
|
|
}),
|
||
|
|
stroke: new Stroke({
|
||
|
|
color: '#fff',
|
||
|
|
width: 3
|
||
|
|
}),
|
||
|
|
font: 'normal 12px Calibri, sans-serif',
|
||
|
|
textAlign: 'center', // 文本对齐
|
||
|
|
offsetX: 0,
|
||
|
|
offsetY: 15,
|
||
|
|
rotation: 0, // 文本旋转
|
||
|
|
}),
|
||
|
|
});
|
||
|
|
}
|
||
|
|
});
|
||
|
|
this.map.addLayer(this.vectorLayerIcon);
|
||
|
|
// 添加事件
|
||
|
|
this.selectInteraction = new Select({
|
||
|
|
layers: [this.vectorLayerIcon]
|
||
|
|
});
|
||
|
|
this.selectInteraction.on('select', (event) => {
|
||
|
|
const selectedFeatures = event.selected;
|
||
|
|
if (selectedFeatures.length) {
|
||
|
|
const select = selectedFeatures[0].values_
|
||
|
|
this.$emit('markertap', JSON.parse(select.value))
|
||
|
|
// tooltip
|
||
|
|
if (this.flagTip) {
|
||
|
|
const coordinate = selectedFeatures[0].values_.geometry.flatCoordinates;
|
||
|
|
this.helpTooltipElement.innerHTML = select.text;
|
||
|
|
console.log(this.helpTooltip)
|
||
|
|
this.helpTooltip.setPosition(coordinate);
|
||
|
|
this.helpTooltipElement.classList.remove('hidden');
|
||
|
|
this.map.addOverlay(this.helpTooltip);
|
||
|
|
this.isShowToolTip = true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
});
|
||
|
|
this.map.addInteraction(this.selectInteraction);
|
||
|
|
},
|
||
|
|
createHelpTooltip() {
|
||
|
|
this.helpTooltipElement
|
||
|
|
if (this.helpTooltipElement) {
|
||
|
|
this.helpTooltipElement.parentNode.removeChild(this.helpTooltipElement);
|
||
|
|
}
|
||
|
|
this.helpTooltipElement = document.createElement('div');
|
||
|
|
this.helpTooltipElement.className = 'tooltip hidden';
|
||
|
|
this.helpTooltip = new Overlay({
|
||
|
|
element: this.helpTooltipElement,
|
||
|
|
offset: [-30, 20],
|
||
|
|
positioning: 'center-left'
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style scoped>
|
||
|
|
.app-content {}
|
||
|
|
|
||
|
|
.editPane {
|
||
|
|
position: absolute;
|
||
|
|
right: 65px;
|
||
|
|
top: 8px;
|
||
|
|
text-align: center;
|
||
|
|
background: #FFF;
|
||
|
|
z-index: 1000;
|
||
|
|
border-radius: 4px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.ol-popup {
|
||
|
|
position: absolute;
|
||
|
|
background-color: white;
|
||
|
|
-webkit-filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
|
||
|
|
filter: drop-shadow(0 1px 4px rgba(0, 0, 0, 0.2));
|
||
|
|
padding: 15px;
|
||
|
|
border-radius: 10px;
|
||
|
|
border: 1px solid #cccccc;
|
||
|
|
bottom: 12px;
|
||
|
|
left: -50px;
|
||
|
|
min-width: 120px;
|
||
|
|
white-space: nowrap;
|
||
|
|
}
|
||
|
|
|
||
|
|
.ol-popup:after,
|
||
|
|
.ol-popup:before {
|
||
|
|
top: 100%;
|
||
|
|
border: solid transparent;
|
||
|
|
content: " ";
|
||
|
|
height: 0;
|
||
|
|
width: 0;
|
||
|
|
position: absolute;
|
||
|
|
pointer-events: none;
|
||
|
|
}
|
||
|
|
|
||
|
|
.ol-popup:after {
|
||
|
|
border-top-color: white;
|
||
|
|
border-width: 10px;
|
||
|
|
left: 48px;
|
||
|
|
margin-left: -10px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.ol-popup:before {
|
||
|
|
border-top-color: #cccccc;
|
||
|
|
border-width: 11px;
|
||
|
|
left: 48px;
|
||
|
|
margin-left: -11px;
|
||
|
|
}
|
||
|
|
|
||
|
|
.tooltip {
|
||
|
|
position: relative;
|
||
|
|
background: rgba(0, 0, 0, 0.5);
|
||
|
|
border-radius: 4px;
|
||
|
|
color: white;
|
||
|
|
padding: 4px 8px;
|
||
|
|
opacity: 0.7;
|
||
|
|
white-space: nowrap;
|
||
|
|
}
|
||
|
|
</style>
|