|
@@ -0,0 +1,154 @@
|
|
|
+<template>
|
|
|
+ <div class="main">
|
|
|
+ <EasyMapComponent
|
|
|
+ class="map"
|
|
|
+ layout="info"
|
|
|
+ @easyMapLoad="mapLoad"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script lang="ts">
|
|
|
+import {
|
|
|
+ defineComponent,
|
|
|
+ computed,
|
|
|
+ onMounted,
|
|
|
+ ref,
|
|
|
+ reactive,
|
|
|
+ watch,
|
|
|
+ getCurrentInstance,
|
|
|
+ ComponentInternalInstance,
|
|
|
+ toRefs,
|
|
|
+ nextTick
|
|
|
+} from 'vue'
|
|
|
+import {useStore} from 'vuex'
|
|
|
+import {useRouter, useRoute} from 'vue-router'
|
|
|
+import {ElMessage, ElMessageBox} from "element-plus";
|
|
|
+import * as layer from "ol/layer";
|
|
|
+import * as format from "ol/format";
|
|
|
+import * as source from "ol/source";
|
|
|
+import * as ol from "ol"
|
|
|
+import * as geom from "ol/geom";
|
|
|
+import * as turf from '@turf/turf'
|
|
|
+import * as style from "ol/style";
|
|
|
+
|
|
|
+export default defineComponent({
|
|
|
+ name: '',
|
|
|
+ components: {
|
|
|
+ },
|
|
|
+ props: {},
|
|
|
+ setup(props, {emit}) {
|
|
|
+ const store = useStore();
|
|
|
+ const router = useRouter();
|
|
|
+ const route = useRoute();
|
|
|
+ const that = (getCurrentInstance() as ComponentInternalInstance).appContext.config.globalProperties
|
|
|
+ const state = reactive({
|
|
|
+ map: <any>null,
|
|
|
+ mapFunc: <any>null,
|
|
|
+ })
|
|
|
+ const mapLoad = (map, func) => {
|
|
|
+ state.map = map
|
|
|
+ state.mapFunc = func
|
|
|
+ initMap()
|
|
|
+ }
|
|
|
+ const initMap = () => {
|
|
|
+ const feats = new format.GeoJSON().readFeatures(turf.randomPoint(1000, {bbox: state.mapFunc.getBBOX()}))
|
|
|
+ const l = new layer.Vector({
|
|
|
+ zIndex: 2,
|
|
|
+ source: new source.Vector({
|
|
|
+ features: feats
|
|
|
+ }),
|
|
|
+ style: new style.Style({
|
|
|
+ image: new style.Circle({
|
|
|
+ radius: 10,
|
|
|
+ fill: new style.Fill({
|
|
|
+ color: 'red',
|
|
|
+ }),
|
|
|
+ })
|
|
|
+ }),
|
|
|
+ // declutter: true
|
|
|
+ })
|
|
|
+ state.map.addLayer(l)
|
|
|
+ const tagL = new layer.Vector({
|
|
|
+ zIndex: 3,
|
|
|
+ source: new source.Vector({
|
|
|
+ features: feats
|
|
|
+ }),
|
|
|
+ style: capturePointStyle('这是标签'),
|
|
|
+ declutter: true
|
|
|
+ })
|
|
|
+ state.map.addLayer(tagL)
|
|
|
+ }
|
|
|
+ const capturePointStyle = (name = null) => {
|
|
|
+ const _style = []
|
|
|
+ const displacementY = 10
|
|
|
+ if (name) {
|
|
|
+ const canvas = document.createElement("canvas");
|
|
|
+ const context = canvas.getContext("2d");
|
|
|
+ const length = String(name).length;
|
|
|
+ canvas.width = length * 20;
|
|
|
+ canvas.height = 40;
|
|
|
+ const x = 0 // 起点x
|
|
|
+ const y = 0 // 起点y
|
|
|
+ let r = 4 // 圆角
|
|
|
+ const arrowW = 10 // 提示框箭头宽度
|
|
|
+ const arrowY = 6 // 提示框箭头高度
|
|
|
+ const w = canvas.width
|
|
|
+ const h = canvas.height - arrowY
|
|
|
+ if (w < 2 * r) r = w / 2;
|
|
|
+ if (h < 2 * r) r = h / 2;
|
|
|
+ context.beginPath();
|
|
|
+ context.moveTo(x + r, y);
|
|
|
+ context.arcTo(x + w, y, x + w, y + h, r);
|
|
|
+ context.arcTo(x + w, y + h, x, y + h, r);
|
|
|
+ context.lineTo(x + w, y + h);
|
|
|
+ context.lineTo(x + w / 2 + arrowW / 2, y + h);
|
|
|
+ context.lineTo(x + w / 2, y + h + arrowY);
|
|
|
+ context.lineTo(x + w / 2 - arrowW / 2, y + h );
|
|
|
+ context.arcTo(x, y + h, x, y, r);
|
|
|
+ context.arcTo(x, y, x + w, y, r);
|
|
|
+ context.closePath();
|
|
|
+ context.fillStyle = "rgba(0,0,0,0.7)";
|
|
|
+ context.fill();
|
|
|
+ _style.push(new style.Style({
|
|
|
+ image: new style.Icon({
|
|
|
+ img: canvas,
|
|
|
+ imgSize: [w, canvas.height],
|
|
|
+ displacement: [0, displacementY + 34]
|
|
|
+ }),
|
|
|
+ text: new style.Text({
|
|
|
+ // 位置
|
|
|
+ textAlign: "center",
|
|
|
+ // 基准线
|
|
|
+ // 文字样式
|
|
|
+ font: "12px 微软雅黑",
|
|
|
+ // 文本内容
|
|
|
+ text: `${name}`,
|
|
|
+ // 文字颜色
|
|
|
+ fill: new style.Fill({ color: "#FFFFFF" }),
|
|
|
+ offsetY: -(displacementY + 36),
|
|
|
+ offsetX: 0
|
|
|
+ }),
|
|
|
+ }))
|
|
|
+ }
|
|
|
+ return _style
|
|
|
+ }
|
|
|
+ onMounted(() => {
|
|
|
+ })
|
|
|
+ return {
|
|
|
+ ...toRefs(state),
|
|
|
+ mapLoad,
|
|
|
+ }
|
|
|
+ },
|
|
|
+})
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped lang="scss">
|
|
|
+.main {
|
|
|
+ width: 100%;
|
|
|
+ height: 100vh;
|
|
|
+ display: flex;
|
|
|
+ position: relative;
|
|
|
+ justify-content: center;
|
|
|
+}
|
|
|
+</style>
|