mapbox在缓冲范围内随机生成点位

<template>
	<div class="relation">
		<div id="mapContainer" class="relation-container"></div>
		<div class="relation-search">
			<Select
				ref="select"
				style="width: 150px; margin-right: 20px"
				v-model:value="timeVal"
				:options="timeOption"
				@focus="focus"
				@change="handleChange"
			></Select>
			<InputSearch
				id="numericInput"
				style="width: 200px"
				v-model:value="inputVal"
				suffix="km"
				placeholder="请输入"
				@search="onSearch"
			/>
		</div>
	</div>
</template>

<script lang="ts" setup>
import { onMounted, Ref, ref } from 'vue';
import { Select, InputSearch } from 'ant-design-vue';
import mapboxgl from 'mapbox-gl';
import imgPoint from '../../../../assets/images/map/point12.png';
import * as turf from '@turf/turf';
import { bbox } from '@turf/turf';
let map: any;
const publick = `${import.meta.env.BASE_URL}`;
const selectValue = ref(1);
const timeVal = ref('一小时');
const inputVal: Ref<number> = ref(1);
const secrchVal: Ref<number> = ref(1);
let point = turf.point([104.0668, 30.5728]);
// 生成若干随机点
let randomPoints: AnyObject = [];

const timeOption = [
	{
		value: 1,
		label: '一小时',
	},
	{
		value: 2,
		label: '二小时',
	},
	{
		value: 3,
		label: '三小时',
	},
];

const init = () => {
	mapboxgl.accessToken = null;
	class Cjmapbox extends mapboxgl.Map {}
	// eslint-disable-next-line @typescript-eslint/no-empty-function
	Cjmapbox.prototype.__proto__._authenticate = function () {};
	map = new mapboxgl.Map({
		container: 'mapContainer',
		style: {
			version: 8,
			name: 'BlankMap',
			glyphs: `${publick}lib/glyphs/{fontstack}/{range}.pbf`,
			sources: {},
			layers: [
				{
					id: 'background',
					type: 'background',
					paint: {
						'background-color': '#08294A',
					} /* 背景颜色 */,
				},
			],
		},
		center: [104.0668, 30.5728], // Set the initial center of the map
		zoom: 14,
	});
	map.on('load', () => {
		map.addSource('DZDT_Vector_BZB', {
			type: 'raster',
			tiles: [
				'http://t3.tianditu.com/DataServer?T=vec_w&tk=915de993ea6873664830bf5d8217723c&x={x}&y={y}&l={z}',
			],
			tileSize: 256,
		});
		map.addLayer({
			id: 'DZDT_Vector_BZB',
			type: 'raster',
			source: 'DZDT_Vector_BZB',
			paint: {},
		});
		map.loadImage(
			imgPoint,
			function (error: AnyObject, imgPoint: AnyObject) {
				if (error) throw error;
				map.addImage('imgPoint', imgPoint);
			},
		);
		bufferEvt(point, 1);
		randomPointsEvt(1);
	});
};
onMounted(() => {
	init();
});
// 缓冲
const bufferEvt = (point: any, distant: number) => {
	let buffered = turf.buffer(point, distant, { units: 'kilometers' });
	if (map.getLayer('circlePOI')) {
		map.removeLayer('circlePOI');
		map.removeSource('circlePOI');
	}
	map.addLayer({
		id: 'circlePOI',
		type: 'fill',
		source: {
			type: 'geojson',
			data: buffered,
		},
		layout: {},
		paint: {
			'fill-color': '#5388e1',
			'fill-opacity': 0.5,
		},
	});
	let listArrBounds = bbox(buffered);
	map.fitBounds(listArrBounds, { padding: 100 });
};
// 缓冲距离
const onSearch = (e: string) => {
	let t = e.replace(/[^0-9.]/g, '');
	if (t.length <= 0) return;
	bufferEvt(point, Number(e));
	if (Number(e) < secrchVal.value) randomPoints = [];
	secrchVal.value = Number(e);
	randomPointsEvt(Number(e));
};
// 随机点
const randomPointsEvt = (dist: number) => {
	let pointsGeoJSON = {};
	for (let i = 0; i < 10; i++) {
		// 生成10个随机点
		randomPoints.push(getRandomPointInCircle([104.0668, 30.5728], dist));
		pointsGeoJSON = {
			type: 'FeatureCollection',
			features: randomPoints.map((coord: AnyObject) => ({
				type: 'Feature',
				geometry: {
					type: 'Point',
					coordinates: coord,
				},
				properties: {}, // 可以在此处添加任何需要的属性
			})),
		};
	}
	addPointEvt(pointsGeoJSON);
};
// 时间
const handleChange = (e: number) => {
	if (e < selectValue.value) {
		randomPoints = [];
	}
	selectValue.value = e;
	randomPointsEvt(secrchVal.value);
};
// 加载点位
const addPointEvt = (geojson: AnyObject) => {
	if (map.getLayer('pointLayer')) {
		map.removeLayer('pointLayer');
		map.removeSource('pointLayer');
	}
	// 添加点图层
	map.addLayer({
		id: 'pointLayer',
		type: 'symbol',
		source: {
			type: 'geojson',
			data: geojson,
		},
		layout: {
			'icon-image': 'imgPoint',
			'icon-size': 0.15,
		},
	});
};
// 随机生成点位
function getRandomPointInCircle(poi: any, radius: number) {
	const [longitude, latitude] = poi;
	// 随机生成距离和角度
	const distance = Math.sqrt(Math.random()) * radius * 800; // 距离,确保在圈内
	const angle = Math.random() * 2 * Math.PI; // 角度
	// 根据距离和角度计算点的偏移
	const offsetLongitude =
		(distance * Math.cos(angle)) /
		(111320 * Math.cos((latitude * Math.PI) / 180));
	const offsetLatitude = (distance * Math.sin(angle)) / 110540;
	return [longitude + offsetLongitude, latitude + offsetLatitude];
}
</script>
<style lang="scss" scoped>
.relation {
	width: 100%;
	height: 100%;
	position: relative;
	&-container {
		width: 100%;
		height: 100%;
	}
	&-search {
		position: absolute;
		right: 50px;
		top: 15px;
		display: flex;
		align-items: center;
	}
}
:deep(.ant-input-search-button) {
	border: 1px solid #d9d9d9 !important;
}
</style>

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小满blue

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值