uniapp 整合 OpenLayers - 添加点、线、面、图片、文字、popup、热力图、聚合和清除

整合看这篇:uniapp 整合 OpenLayer3-CSDN博客

添加点线面直接上代码:

<template>
	<!-- 监听变量 operation 的变化,operation 发生改变时,调用 openlayers 模块的 loadOperation 方法 -->
	<view :operation="valueChangeSign" :change:operation="ol.valueChange" type="default"></view>
	<view class="map" id="map">
		<view class="vertical-button">
			<button @click="goTo()" class="btn" type="primary">全图</button>
			<button @click="drawPoint()" class="btn" type="primary">点</button>
			<button @click="drawLine()" class="btn" type="primary">线</button>
			<button @click="drawPolygon()" class="btn" type="primary">面</button>
			<button @click="drawIcon()" class="btn" type="primary">图片</button>
			<button @click="drawText()" class="btn" type="primary">文字</button>
			<button @click="drawPopup()" class="btn" type="primary">popup</button>
			<button @click="drawHeatMap()" class="btn" type="primary">热力图</button>
			<button @click="cluster()" class="btn" type="primary">聚合</button>
			<button @click="clearDraw()" class="btn" type="primary">清除</button>
		</view>
		
	</view>
</template>

<!-- 逻辑层 -->
<script>

	export default {
		data(){
			return {
				valueChangeSign:{
					flag:false,
					type:""
				},
				map:null,
				total:0
			}
		},
		methods:{
			/**
			 * 接受renderjs传过来的数据
			 */
			reciveMessage(data){
			   this.total = data;
			   console.log("total",this.total);
			},
			receiveMethod(){
			   console.log("获取方法");
			},
			/**
			 * 点击事件-全图
			 */
			goTo(){
				this.valueChangeSign.flag = !this.valueChangeSign.flag;
				this.valueChangeSign.type = "allMap";
				
			},
			/**
			 * 点击事件-绘制点
			 */
			drawPoint(){
				this.valueChangeSign.flag = !this.valueChangeSign.flag;
				this.valueChangeSign.type = "drawPoint";
				//console.log("绘制点");
			},
			/**
			 * 点击事件-绘制线
			 */
			drawLine(){
				this.valueChangeSign.flag = !this.valueChangeSign.flag;
				this.valueChangeSign.type = "drawLine";
				//console.log("绘制线");
			},
			/**
			 * 点击事件-绘制面
			 */
			drawPolygon(){
				this.valueChangeSign.flag = !this.valueChangeSign.flag;
				this.valueChangeSign.type = "drawPolygon";
				//console.log("绘制面");
			},
			/**
			 * 点击事件-绘制图片
			 */
			drawIcon(){
				this.valueChangeSign.flag = !this.valueChangeSign.flag;
				this.valueChangeSign.type = "drawIcon";
				//console.log("绘制图片");
			},
			/**
			 * 点击事件-绘制文字
			 */
			drawText(){
				this.valueChangeSign.flag = !this.valueChangeSign.flag;
				this.valueChangeSign.type = "drawText";
				//console.log("绘制文字");
			},
			/**
			 * 点击事件-绘制popup
			 */
			drawPopup(){
				this.valueChangeSign.flag = !this.valueChangeSign.flag;
				this.valueChangeSign.type = "drawPopup";
				//console.log("绘制popup");
			},
			/**
			 * 点击事件-绘制热力图
			 */
			drawHeatMap(){
				this.valueChangeSign.flag = !this.valueChangeSign.flag;
				this.valueChangeSign.type = "drawHeatMap";
				//console.log("绘制热力图");
			},
			/**
			 * 聚合 
			*/	
			cluster(){
				this.valueChangeSign.flag = !this.valueChangeSign.flag;
				this.valueChangeSign.type = "cluster";
				//console.log("聚合");
			},
			/**
			 * 清除绘制 
			*/
		   clearDraw(){
			   this.valueChangeSign.flag = !this.valueChangeSign.flag;
			   this.valueChangeSign.type = "clearDraw";
		   }
		}
	}
</script>

<!-- 视图层 -->
<script module="ol" lang="renderjs" type="module">
//import 'ol/ol.css'// 真机-样式需要放在App.vue下面的style标签中,全局引用
import Map from 'ol/Map.js'  // OpenLayers的主要类,用于创建和管理地图  
import View from 'ol/View.js'  // OpenLayers的视图类,定义地图的视图属性 
import TileLayer from 'ol/layer/Tile.js'// OpenLayers的瓦片图层类   
import olsourceOSM from 'ol/source/OSM.js'
import Cluster from 'ol/source/Cluster.js';// 聚合类
import {get as getProjection} from 'ol/proj.js';
import XYZ from 'ol/source/XYZ.js'
import Feature from 'ol/Feature.js'  // OpenLayers的要素类,表示地图上的一个对象或实体          
import Point from 'ol/geom/Point.js'  // OpenLayers的点几何类,用于表示点状的地理数据        
import { Vector as VectorLayer } from 'ol/layer.js'  // OpenLayers的矢量图层类,用于显示矢量数据        
import { Vector as VectorSource } from 'ol/source.js'  // OpenLayers的矢量数据源类,用于管理和提供矢量数据       
import { Circle as CircleStyle, Style, Text, Stroke, Fill, Icon } from "ol/style.js"  // OpenLayers的样式类,用于定义图层的样式,包括圆形样式、基本样式、边框、填充和图标      
import { ScaleLine, defaults as defaultControls, MousePosition } from 'ol/control.js'// OpenLayers的控件类,包括默认的控件集合和特定的全屏、鼠标位置、比例尺控件
import { transform } from 'ol/proj.js'// OpenLayers的投影转换函数,用于经纬度坐标和投影坐标之间的转换
import Overlay from 'ol/Overlay.js';
import HeatmapLayer from 'ol/layer/Heatmap.js';
import LineString from 'ol/geom/LineString.js'  // OpenLayers的线几何类,用于表示线状的地理数据            
import Polygon from "ol/geom/Polygon.js"  // OpenLayers的多边形几何类,用于表示面状的地理数据
import ZoomSlider from 'ol/control/ZoomSlider.js';// 滑动放大缩小按钮
import FullScreen from 'ol/control/FullScreen.js';// 全屏按钮
import ZoomToExtent from 'ol/control/ZoomToExtent.js';// 范围
 

	export default {
	    data () {
	        return {
	            map:null,
	            view:null,
				pointLayer:null,// 点图层
				lineLayer:null,// 线图层
				polygonLayer:null,//面图层
				count:0
	        }
	    },
	    mounted(){
		   this.initMap();
	       console.log("mounted方法");
	    },
		methods:{
			/**
			 * @param {*} newValue 新的值或状态
			 * @param {*} oldValue 旧的值或状态
			 * @param {*} ownerInstance 拥有该数据或组件的实例
			 * @param {*} instance 当前操作的具体实例
			 */
			valueChange(newValue, oldValue, ownerInstance, instance){
				console.log(newValue, oldValue, ownerInstance, instance);
				console.log(newValue.flag);
				// 下面的方法也好使
				/* // 传递数值
				this.$ownerInstance.callMethod('reciveMessage',this.count++);
				// 传递map
				this.$ownerInstance.callMethod('receiveMethod'); */
				
				// 传递数值
				ownerInstance.callMethod('reciveMessage',this.count++);
				// 传递map
				ownerInstance.callMethod('receiveMethod');
				
				switch (newValue.type){
					case "allMap":
						// 定位
						this.goToExtent();
						break;
					case "drawPoint":
						// 绘制点
						this.drawPoint();
						break;
					case "drawLine":
						// 绘制线 
						this.drawLine();
						break;
					case "drawPolygon":
						// 绘制面
						this.drawPolygon();
						break
					case "drawIcon":
						// 绘制图片
						this.drawIcon();
						break;
					case "drawText":
						//绘制文字标注 
						this.drawText();
						break;
					case "drawPopup":
						// 绘制popup
						this.drawPopup();
						break;
					case "drawHeatMap":
						//绘制热力图
						this.drawHeatMap();
						break;
					case "cluster":
						// 聚合
						this.cluster();
						break;
					case "clearDraw":
						// 清除绘制
						this.clearDraw();
						break;
					default:
						console.log("default");
						break;
				}
				
				
			},
			// 初始化天地图
			initMap(){
				//天地图影像
				var tdtYX = new TileLayer({
				  source: new XYZ({
				    url: 'http://t2.tianditu.gov.cn/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=cef191b507ff5cb698811cd8a9b11ca0',
				    projection: 'EPSG:3857',
				    crossOrigin: '*',
				  }),
				})
				//天地图标注
				var tdtBZ = new TileLayer({
				  source: new XYZ({
				    url: 'http://t2.tianditu.gov.cn/DataServer?T=cia_w&x={x}&y={y}&l={z}&tk=cef191b507ff5cb698811cd8a9b11ca0',
				    projection: 'EPSG:3857',
				  }),
				})
				
				//天地图电子地图
				var tdtDZ = new TileLayer({
				  source: new XYZ({
				    url: 'http://t2.tianditu.gov.cn/DataServer?T=vec_w &x={x}&y={y}&l={z}&tk=cef191b507ff5cb698811cd8a9b11ca0',
				    projection: 'EPSG:3857',
				  }),
				})
				
				this.map = new Map({
				  target: 'map',
				  layers: [tdtDZ,tdtBZ],//[tdtYX, tdtBZ],
				  view: new View({
				    projection: 'EPSG:3857',
				    center: transform([125.33,43.90], 'EPSG:4326', 'EPSG:3857'),
				    // center: [125.33,43.90],
				    zoom: 10,
					minZoom: 0,// 最小缩放级别
				    maxZoom: 18, //最大缩放级别
					constrainResolution: true,// 因为存在非整数的缩放级别,所以设置该参数为true来让每次缩放结束后自动缩放到距离最近的一个整数级别,这个必须要设置,当缩放在非整数级别时地图会糊
					enableRotation: false,// 禁止地图旋转
				  }),
				  controls:defaultControls({
					  zoom:false,//不显示放大放小按钮
					  rotate:false,// 不显示指北针控件
					  attribution:false//不显示右下角的地图信息控件
				  }).extend([
					// 比例尺
					new ScaleLine({
						//设置比例尺单位,degrees、imperial、us、nautical、metric(度量单位)
						units: "metric"
					})
				  ])
				})
				
			},
			async goToExtent(){
				// 获取当前可见视图范围
				console.log(this.map.getView().calculateExtent());
				// 设置中心点
				this.map.getView().setCenter(transform([125.33,43.90], 'EPSG:4326', 'EPSG:3857'));
				this.map.getView().setZoom(10);
			},
			async drawPoint(){// 绘制点
				// 清除绘制点
				this.map.removeLayer(this.pointLayer); 
				// 设置点特征(Feature)
				const pointFeature = new Feature({
					title:"point",
					geometry:new Point(transform([125.34,43.91],'EPSG:4326', 'EPSG:3857'))// 转换坐标
				});
				
				// 设置特征样式(style)
				pointFeature.setStyle(
					new Style({
						 // 使用 CircleStyle 创建一个圆形的点
						 image:new CircleStyle({
							 // 点样式
							 fill:new Fill({
								 //color:"red",// 颜色
								 color: 'rgba(255,0,0,0.4)',
							 }),
							 // 点周边样式
							 stroke:new Stroke({
								color: '#3399CC',
								width: 1.25, 
							 }),
							 radius:7,// 半径
						 }),
					})
				);
				// 创建和添加特征到源(Source)
				// VectorSource表示一个矢量要素源,它用于存储和显示地理数据。
				const source = new VectorSource();
				source.addFeature(pointFeature);
				// 创建图层并设置源(Layer)
				// VectorLayer表示一个矢量图层,它由一系列矢量要素(Feature)组成,用于在地图上显示地理数据。
				this.pointLayer = new VectorLayer();
				this.pointLayer.setSource(source);
				this.map.addLayer(this.pointLayer);
			},
			async drawLine(){// 绘制线
				// 清除绘制线
				this.map.removeLayer(this.lineLayer); 
			    // 创建线特征(Feature)
				const lineFeature = new Feature({
					geometry:new LineString([
						transform([125.34,43.91],'EPSG:4326', 'EPSG:3857'),//起点经纬度坐标
						transform([125.36,43.93],'EPSG:4326', 'EPSG:3857'),//终点经纬度坐标
						// 可以添加更多点坐标,绘制复杂的线
					])
				});
				
				// 设置线特征样式(Style)
				lineFeature.setStyle(
					new Style({
						stroke:new Stroke({
							color:"green",// 线的颜色
							width:2// 线宽带
						})
					})
				);
				
				// 创建和添加特征道源(Source)
				const source = new VectorSource();
				source.addFeature(lineFeature);
				
				// 创建图层并设置源(Layer)
				this.lineLayer = new VectorLayer();
				this.lineLayer.setSource(source);
				
				// 将图层添加到地图上
				this.map.addLayer(this.lineLayer);
				
			},
			async drawPolygon(){// 绘制面
				// 清除绘制面
				this.map.removeLayer(this.polygonLayer); 
				// 定义多边形坐标数组
				const coordinates = [
					[
						transform([125.34,43.91],'EPSG:4326', 'EPSG:3857'),
						transform([125.36,43.93],'EPSG:4326', 'EPSG:3857'),
						transform([125.31,43.95],'EPSG:4326', 'EPSG:3857'),
						transform([125.37,43.99],'EPSG:4326', 'EPSG:3857')
					]
				];
				
				// 创建多边形几何对象
				const polygon = new Polygon(coordinates);
				
				//创建特征(Feature)
				const polygonFeature = new Feature({
					geometry: polygon
				});
				
				// 设置多边形样式(Style)
				polygonFeature.setStyle(
					new Style({
						stroke:new Stroke({
							color:"yellow",// 多边形边界颜色
							width:2// 多边形边界宽度
						}),
						fill:new Fill({
							color:'rgba(0,0,255,0.5)'// 多边形填充颜色,这里设置为半透明颜色
						})
					})
				);
				
				// 创建和添加特征到源(Source)
				const source = new VectorSource();
				source.addFeature(polygonFeature);
				
				// 创建图层并设置源(Layer)
				this.polygonLayer = new VectorLayer();
				this.polygonLayer.setSource(source);
	 
				// 将图层添加到地图上
				this.map.addLayer(this.polygonLayer);
			    	
			},
			async drawIcon(){// 绘制图片
				// 创建点特征(Feature)
				const iconFeature = new Feature({
					title:"icon",
					geometry:new Point(transform([125.42,43.99],'EPSG:4326', 'EPSG:3857'))// 坐标转换
				});
				
				// 设置特征样式(Style)
				iconFeature.setStyle(
					new Style({
						// 自定义图片
						image:new Icon({
							anchor:[0.5,0.5],// 显示位置
							scale:0.5,// 图标缩放比例
							opacity:0.75,// 透明度
							color: 'rgba(255, 0, 0,0.5)',//给图片着色
							rotation: 0,//旋转弧度
							// 网络图片资源
							//src:"https://openlayers.org/en/v10.2.1/examples/data/icon.png",// 图片地址
							// 本地图片资源(需借用nginx)
							src:"http://192.168.1.167:81/images/demo_1.jpg"
						})
					})
				);
				
				// 创建和添加特征到源(Source)
				//VectorSource表示一个矢量要素源,它用于存储和显示地理数据。
				const source = new VectorSource();
				source.addFeature(iconFeature);
				// 创建图层并设置源(Layer)
				// VectorLayer表示一个矢量图层,它由一系列矢量要素(Feature)组成,用于在地图上显示地理数据。
				const layer = new VectorLayer()
				layer.setSource(source)
				this.map.addLayer(layer)
				
			},
			async drawText(){// 绘制文字标注
				// 创建一个点特征(Feature)作为文本标注得位置
				const textFeature = new Feature({
					geometry:new Point(transform([125.38,43.94],'EPSG:4326', 'EPSG:3857'))// 设置文字点坐标
				});
				
				// 创建一个带有文本得样式(Style)
				const textStyle = new Style({
					text:new Text({
						text:'还有谁',// 文本内容
						font:"28px Arial,sans-serif",// 字体样式
						fill:new Fill({color:'red'}),// 文本填充颜色
						stroke:new Stroke({color:"white",width:5}),//文本边框样式
						offsetX:0,//文本水平偏移量
						offsetY:-10,//文本垂直偏移量
						textAlign:'center'// 文本水平对齐方式
					})
				});
		
				// 设置添加
				textFeature.setStyle(textStyle);
				
				//创建一个特征源(Source)并添加点特征
				const source = new VectorSource();
				source.addFeature(textFeature);
				
				//创建一个矢量图层(Layer)并设置特征源
				const textLayer = new VectorLayer({
					source:source
				});
				// 将图层添加到地图上
				this.map.addLayer(textLayer);
			},
			async drawPopup(){// 绘制popup
				// 创建一个弹出窗口容器元素
				            const popupContainer = document.createElement('div');
				            popupContainer.setAttribute('id', 'popup');
				            popupContainer.innerHTML = '<p>Popup弹窗</p>';
				            popupContainer.style.height = '50px';
				            popupContainer.style.backgroundColor = 'rgba(255, 255, 255, 0.8)'; // 设置背景颜色,这里使用了半透明白色
				            popupContainer.style.textAlign = 'center';
				            popupContainer.style.padding = '10px';
				            popupContainer.style.border = '1px solid #ccc';
				            popupContainer.style.color = 'red';
				            // 创建一个 Overlay 实例,将弹出窗口容器元素添加到 Overlay 中
				            const popupOverlay = new Overlay({
				                element: popupContainer,
				                autoPan: {
				                    animation: {
				                        duration: 250 // 设置自动平移动画的持续时间,单位为毫秒
				                    }
				                }
				            });
				 
				            // 将 Overlay 添加到地图上
				            this.map.addOverlay(popupOverlay);
				 
				            // 设置弹出窗口的位置(示例位置)
				            const popupPosition = transform([125.35,43.93],'EPSG:4326', 'EPSG:3857'); // 替换 longitude 和 latitude 为实际的经纬度值
				            popupOverlay.setPosition(popupPosition);
				 
				            // 显示弹出窗口
				            popupContainer.style.display = 'block';
			},
			async drawHeatMap(){// 热力图
				const heatFeatures = [];
				
				// 添随机点数据
				const heatmapData = [];
				for (let i = 0; i < 100; i++) {
					const randomLon = 125.40 + (Math.random() - 0.5) * 0.2; // 在中心经度附近随机生成经度
					const randomLat = 43.90 + (Math.random() - 0.5) * 0.2; // 在中心纬度附近随机生成纬度
					
					const param = {"longitude":randomLon,"latitude":randomLat};
					heatmapData.push(param);
				}
				
				// 遍历点数据,添加到feature中
				heatmapData.forEach(item=>{
					const heatFeature = new Feature({
						geometry:new Point(transform([item.longitude,item.latitude],'EPSG:4326', 'EPSG:3857')),
					});
					// 添加数据
					heatFeatures.push(heatFeature);
				});
				
				// 创建一个矢量数据源,添加数据
				const heatSource = new VectorSource({
					features:heatFeatures
				});
				
				// 创建一个热力图层
				const heatmapLayer = new HeatmapLayer({
					title: 'heatmap',
					source: heatSource,
					blur: 30, // 设置模糊半径
					radius: 20, // 设置热力点半径
					//gradient: ["#2200FF", "#E8D225", "#EF1616"],
				    //zIndex: 4,
				    //opacity: 0.5
				});
	 
				// 将热力图层添加到地图中
				this.map.addLayer(heatmapLayer);
			},
			async cluster(){//聚合
				const _this = this;
				const clusFeatures = [];
			
				// 添加随机点数据  
				const clusterData = [];  
				for (let i = 0; i < 1000; i++) { // 假设有1000个随机点  
					const randomLon = 125.32 + (Math.random() - 0.5) * 0.2; // 在中心经度附近随机生成经度
					const randomLat = 43.82 + (Math.random() - 0.5) * 0.2; // 在中心纬度附近随机生成纬度
					
					const param = {"longitude":randomLon,"latitude":randomLat};
					clusterData.push(param);  
				}  
			
			// 遍历点数据,添加到feature中
			clusterData.forEach(item=>{
				const clusFeature = new Feature({
					geometry:new Point(transform([item.longitude,item.latitude],'EPSG:4326', 'EPSG:3857')),
				});
				// 添加数据
				clusFeatures.push(clusFeature);
			});
			
				// 创建一个矢量数据源,并添加随机点数据  
				const vectorSource = new VectorSource({  
					features: clusFeatures
				});  
				
			
				// 创建一个聚合图层  
				const clusterLayer = new VectorLayer({  
					source: new Cluster({  
						distance: 40, // 设置聚合的距离阈值  
						source: vectorSource  
					}),  
					style: function(feature) {  
						// 根据聚合点的数量设置不同的样式  
						const size = feature.get('features').length;  
						return new Style({  
							image: new CircleStyle({  
								radius: 10 + size / 10, // 半径根据聚合点数量进行调整  
								stroke: new Stroke({ color: 'white', width: 2 }),  
								fill: new Fill({ color: '#994433' }) // 通过数量获取颜色  
							}),  
							text: new Text({  
								text: size.toString(),  
								fill: new Fill({ color: '#fff' }),  
								stroke: new Stroke({ color: '#125522', width: 3 })  
							})  
						});  
					}  
				});  
			
				// 将聚合图层添加到地图中  
				_this.map.addLayer(clusterLayer);
			},
			async clearDraw(){// 清空绘制图层
				//移除点图层
				this.map.removeLayer(this.pointLayer);
				//移除线图层
				this.map.removeLayer(this.lineLayer);
				//移除线图层
				this.map.removeLayer(this.polygonLayer);
			}
		}
	}
</script>

<style scoped lang="scss">
	/*去除顶部导航栏*/
	*{margin:0;padding:0}
	.map{
	  width:100vw;
	  height: 100vh;
	  position: relative;
	  z-index: 1;
	  .vertical-button{
		  margin-top: 80px;
		  margin-left: 88%;
		  position: absolute;
		  z-index: 10;
		  .btn {
				width: auto;
				height: auto;
				margin: 5px; /* 按钮间距 */
				padding: 10px; /* 按钮内部填充 */
				width: 100%; /* 按钮宽度 */
				text-align: center; /* 按钮文字居中 */
			}
	  }
	   
	  .ol-zoomslider {
		top: 7.5em;
		left: .5em;
		height: 200px;
	  }
	  
	}

	
</style>

OpenLayers中,当你想要在用户击地图时动态地添加标记图片并显示相关信息的弹窗,可以按照以下步骤操作: 1. **初始化地图**: 首先,你需要加载OpenLayers库,并创建一个地图容器。例如: ```javascript var map = new ol.Map({ target: 'map', // 地图容器id layers: [your_layer], // 添加基础地图层 view: new ol.View({ center: [lon, lat], // 中心坐标 zoom: 8 // 初始缩放级别 }) }); ``` 2. **监听click事件**: 使用`map.on('click', function(event) { ... })`来监听地图的击事件。在这个回调函数里处理击动作: ```javascript map.on('click', function(event) { // event.coordinate 是鼠标击的位置 }); ``` 3. **添加标记和图片**: 在击事件的回调中,你可以创建一个新的标记(marker)实例,附上图片: ```javascript var marker = new ol.Feature({ geometry: new ol.geom.Point(event.coordinate), properties: { imgUrl: 'path/to/your/image.png', // 图片URL popupContent: '<div>这里是弹窗内容</div>' // 弹窗HTML } }); var source = new ol.source.Vector({features: [marker]}); var layer = new ol.layer.Vector({ source: source, style: your_style_function(marker) // 样式函数根据需求定制 }); map.addLayer(layer); ``` 4. **显示弹窗**: 当标记被添加到地图上时,可以利用OpenLayersPopup组件来显示弹窗信息: ```javascript var popup = new ol.control.Popup(); map.addControl(popup); popup.showAt(event.coordinate, marker.getPopup().content); ``` 5. **样式定制**: `style_function(marker)` 可能需要自定义,以便调整标记的外观,比如颜色、图标等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值