123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311 |
- <template>
- <div id="map-container"></div>
- </template>
- <script setup>
- import { ref, onMounted, onUnmounted } from "vue";
- import AMapLoader from "@amap/amap-jsapi-loader";
- import eventBus from "@/api/eventBus";
- import { convertPointToArray } from "@/utils/index";
- import { deepClone } from "@/common/commonFun";
- import wellknown from 'wellknown';
- import {base_img_url,base_img_url3} from "@/api/config";
- const map = ref(null);
- const mouseTool = ref(null);
- const selectedArea = ref(null);
- const selectedPoints = ref([]);
- const allPoints = ref([]);
- const defalutAllPoints = ref([])
- const pointList = ref([])
- const mapEventType = ref('rectangle')
- // 自定义圆点样式
- const createMarkerContent = (color = 'rgba(0, 0, 0, 0.4)') => {
- return `
- <div style="
- width: 15px;
- height: 15px;
- background-color: ${color};
- border: 1px solid #fff;
- border-radius: 50%;
- ">
- </div>
- `;
- }
- //高亮样式
- const createMarkerImg = () => {
- return `
- <img style="width: 38px;height: 38px;" src="${require('@/assets/images/map/status/active-icon.png')}">
- `;
- }
- // 初始化地图
- const initMap = async () => {
- try {
- const AMap = await AMapLoader.load({
- key: "41769169f0f157e13a197e7eb0dd7b5b", // 替换为你的高德地图 Key
- version: "2.0", // SDK 版本
- plugins: ["AMap.MouseTool","AMap.MarkerCluster"], // 加载 MouseTool 插件
- }).then(async (AMap) => {
- // 创建地图实例
- map.value = new AMap.Map("map-container", {
- zoom: 18, // 初始缩放级别
- center: [111.01055729572, 21.7743543],
- layers: [
- // 天地图卫星
- new AMap.TileLayer({
- tileSize: 256, // 瓦片大小
- getTileUrl: function(x, y, z) {
- // 天地图影像 WMTS 地址
- const s = Math.floor(Math.random() * 8); // 随机选择服务器节点
- // return `https://t{0-7}.tianditu.gov.cn/img_c/w mts?tk=e95115c454a663cd052d96019fd83840`
- return `https://t${s}.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX=${z}&TILEROW=${y}&TILECOL=${x}&tk=e95115c454a663cd052d96019fd83840`;
- },
- }),
- //天地图路网
- new AMap.TileLayer({
- tileSize: 256, // 瓦片大小
- getTileUrl: function(x, y, z) {
- // 天地图影像 WMTS 地址
- const s = Math.floor(Math.random() * 8); // 随机选择服务器节点
- return `https://t${s}.tianditu.gov.cn/cva_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX=${z}&TILEROW=${y}&TILECOL=${x}&tk=e95115c454a663cd052d96019fd83840`;
- },
- }),
- //正射影像
- new AMap.TileLayer({
- tileUrl: base_img_url + 'map/lby/[z]/[x]/[y].png',
- zIndex:2
- }),
- new AMap.TileLayer({
- tileUrl: base_img_url3 + 'map/lby/[z]/[x]/[y].png',
- zIndex:2
- })
- ],
- });
- // // 初始化点聚合
- // const cluster = new AMap.MarkerCluster(map, markers, {
- // gridSize: 60, // 聚合网格像素大小
- // maxZoom: 15, // 最大聚合级别
- // renderClusterMarker: customizeCluster // 自定义聚合样式
- // });
- // 初始化 MouseTool
- mouseTool.value = new AMap.MouseTool(map.value);
-
- // startRectangleSelection()
- // 监听框选完成事件
- mouseTool.value.on("draw", (event) => {
- if(mapEventType.value==='click') return
- const { obj} = event;
- if (obj instanceof AMap.Rectangle) {
- selectedArea.value = obj;
- map.value.remove(selectedArea.value);
- checkPointsInArea(); // 检查框选区域内的点位
- }
- });
- });
- } catch (error) {
- console.error("地图加载失败:", error);
- }
- };
- //重置数据
- const resetData = () =>{
- allPoints.value = defalutAllPoints.value
- allPoints.value.forEach(item =>{
- item.icon.setContent(createMarkerContent(item.color))
- item.icon.setOffset(new window.AMap.Pixel(-7, -7))
- item.type = 'defalutIcon'
- })
- }
- //初始化数据
- const initData = (data) =>{
- allPoints.value = data
- defalutAllPoints.value = []
- totalList.value.forEach(item => map.value.remove(item.icon))
- totalList.value = []
- allPoints.value.forEach(item =>{
- item.icon = new window.AMap.Marker({
- position: item.lnglat,
- map: map.value,
- content: createMarkerContent(item.color),
- offset: new window.AMap.Pixel(-7, -7),
- extData: { id: item.id, priority: item.status > item.noImg > item.wys } // 标记优先级
- });
- item.type = 'defalutIcon'
- // 绑定点击事件
- item.icon.on('click', () => {
- mapEventType.value = 'click'
- if(item.type === 'defalutIcon'){
- if (startDraw.value) {
- item.icon.setContent(createMarkerImg());
- item.icon.setOffset(new window.AMap.Pixel(-18, -18))
- item.type = 'activeIcon'
- const arr = pointList.value.filter(ele => ele.id === item.id)
- if(arr.length===0){
- pointList.value.push(item)
- }
- }
- }else{
- item.icon.setContent(createMarkerContent(item.color));
- item.icon.setOffset(new window.AMap.Pixel(-7, -7))
- item.type = 'defalutIcon'
- }
- console.log('item', item);
- eventBus.emit("clickMapPoint", item)
- setTimeout(()=>{
- mapEventType.value = 'draw'
- },100)
- });
- defalutAllPoints.value.push(item)
- })
- // 初始化点聚合
- // console.log('data',data);
- // const cluster = new window.AMap.MarkerCluster(map.value, data, {
- // gridSize: 30, // 聚合网格像素大小
- // // maxZoom: 15, // 最大聚合级别
- // // renderClusterMarker: customizeCluster // 自定义聚合样式
- // });
- setTimeout(()=>{
- map.value.setFitView(null, false, [0, 0, 0, 0]);
- },100)
- // 范围
- // const p1 = [
- // [111.00745562137854, 21.77564355219471],
- // [111.00982318507914, 21.77557930674749],
- // [111.01133652227907, 21.776531091149934],
- // [111.0125762214629, 21.775945743742568],
- // [111.01290458708189, 21.775241423284797],
- // [111.01341617119812, 21.773759019078113],
- // [111.01320915809049, 21.77329502418189],
- // [111.01209794980082, 21.772538355582128],
- // [111.01117233946951, 21.772414623609905],
- // [111.00909744947245, 21.772878618505956],
- // [111.00744610353439, 21.774094523079953],
- // [111.00745562137854, 21.77564355219471]
- // ]
- // addPolygon(p1)
-
- }
- const startDraw = ref(false)
- // 开始框选
- const startRectangleSelection = () => {
- if (mouseTool.value) {
- startDraw.value = true
- mouseTool.value.rectangle({
- strokeColor: "#ffffff", // 框选区域边框颜色
- strokeOpacity: 1, // 边框透明度
- strokeWeight: 2, // 边框宽度
- fillColor: "#000000", // 填充颜色
- fillOpacity: 0.5, // 填充透明度
- }); // 启用矩形框选工具
- map.value.setDefaultCursor("crosshair");
- }
- };
- // 停止绘制矩形
- const stopDrawRectangle = () => {
- mouseTool.value.close(); // 关闭 mouseTool
- map.value.setDefaultCursor("default");
- };
- // 清除框选
- const clearSelection = () => {
- if (selectedArea.value) {
- map.value.remove(selectedArea.value); // 移除框选区域
- selectedArea.value = null;
- }
- resetData()
- selectedPoints.value = []; // 清空选中的点位
- };
- // 检查框选区域内的点位
- const checkPointsInArea = () => {
- if (!selectedArea.value) return;
- const bounds = selectedArea.value.getBounds(); // 获取框选区域的边界
- selectedPoints.value = allPoints.value.filter((point) => {
- return bounds.contains(point.lnglat); // 判断点位是否在框选区域内
- });
-
- selectedPoints.value.forEach(item =>{
- if(item.type==='defalutIcon'){
- item.icon.setContent(createMarkerImg())
- item.icon.setOffset(new window.AMap.Pixel(-18, -18))
- item.type = 'activeIcon'
- }else{
- item.icon.setContent(createMarkerContent(item.color))
- item.icon.setOffset(new window.AMap.Pixel(-7, -7))
- item.type = 'defalutIcon'
- }
- })
- };
- const totalList = ref([])
- function getSelectPoint(){
- totalList.value = selectedPoints.value.concat(pointList.value)
- const arr = totalList.value.filter(item =>item.type==='activeIcon')
- return arr
- }
- function getRegionList(farmId) {
- VE_API.region.list({farmId}).then(({data}) =>{
- data.map(item => {
- addPolygon(wktToAmapPolygon(item.wkt))
- })
- })
- }
- function addPolygon(data) {
- console.log('dddddd', data);
- let polygon = new window.AMap.Polygon({
- path: data,
- fillColor: '#FFE17E',
- strokeOpacity: 1,
- fillOpacity: 0.1,
- strokeColor: 'rgba(255, 255, 255, 0.3)',
- strokeWeight: 1,
- strokeStyle: 'solid',
- // strokeDasharray: [5, 5],
- });
- map.value.add(polygon)
- }
- defineExpose({getSelectPoint,initData,startRectangleSelection,stopDrawRectangle,clearSelection, getRegionList})
- // 组件挂载时初始化地图
- onMounted(() => {
- initMap()
- });
- onUnmounted(()=>{
- map.value.destroy()// 销毁地图实例以释放资源
- })
- function wktToAmapPolygon(wkt) {
- const geoJSON = wellknown.parse(wkt);
- if (!geoJSON || geoJSON.type !== 'MultiPolygon') {
- console.error('Invalid WKT or not a MULTIPOLYGON');
- return [];
- }
- // MULTIPOLYGON 的坐标结构:[[[ [环1], [环2], ... ]]],取第一个环
- return geoJSON.coordinates[0][0].map(coord => [coord[0], coord[1]]);
- }
- </script>
- <style scoped>
- #map-container {
- width: 100%;
- height: 100%;
- }
- </style>
|