整合看这篇: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>