当前位置: 首页 > news >正文

Uniapp中使用renderjs实现OpenLayers+天地图的展示与操作

Uniapp中自带的地图组件对支持的地图服务略有局限,同时,该组件在样式布局上层级过高且无法控制,无法满足部分高度自定义化的需求。故引入renderjs视图层工具搭配OpenLayers框架对地图功能进行实现,但由于renderjs的限制,只支持App端与H5端。

一、renderjs

renderjs是一个运行在视图层的js,可对DOM元素进行操作。它比WXS更加强大但只支持app-vueweb(H5)
renderjs的主要作用有:

  1. 大幅降低逻辑层和视图层的通讯损耗,提供高性能视图交互能力;
  2. 在视图层操作dom,运行 for web 的 js库。

renderjs相关的更多信息见Uniapp官网介绍。

二、OpenLayers

OpenLayers 是一个开源的 JavaScript 库,用于在 Web 浏览器中显示和交互地图数据。它支持多种地理数据源(如 WMS、WFS、GeoJSON 等),并提供丰富的功能,如地图渲染、图层控制、坐标转换和用户交互(缩放、平移、标记等)。
主要应用场景在:

  1. Web GIS 系统:构建地理信息展示与分析平台。
  2. 数据可视化:叠加业务数据(如热力图、轨迹)。
  3. 自定义地图:整合第三方地图服务或离线瓦片。

OpenLayers 官网:https://openlayers.org/

三、Uniapp展示天地图

1.依赖下载

npm install ol

2.引入OpenLayers相关方法

此时,需要借助renderjs对Openlayers进行处理,另起一个script 标签<script module="ol" lang="renderjs"> ... </script>包裹相关内容。

<script module="ol" lang="renderjs">
import {Map,View
} from 'ol';
import TileLayer from 'ol/layer/Tile';
import Tile from 'ol/layer/Tile';
import VectorSource from 'ol/source/Vector';
import {Vector as VectorLayer,
} from 'ol/layer';
import {defaults as defaultControls,
} from 'ol/control';
</script>

3.初始化天地图

页面中建立一个id为map的块级元素供后续操作,其中map_page类需要设置好宽度与高度。

<template><view><view id="map" class="map_page"></view></view>
</template>

使用renderjs操作OpenLayers对天地图进行展示。

<script module="ol" lang="renderjs">
import {Map,View
} from 'ol';
import TileLayer from 'ol/layer/Tile';
import Tile from 'ol/layer/Tile';
import VectorSource from 'ol/source/Vector';
import {Vector as VectorLayer,
} from 'ol/layer';
import XYZ from 'ol/source/XYZ'
import {defaults as defaultControls,
} from 'ol/control';export default {name: 'gis-map',data() {return {//地图对象map: null, // 地图渲染控件vectorSource: null,vectorLayer: null,}},mounted() {this.initMap()},methods: {/*** 初始化地图*/initMap() {this.vectorSource = new VectorSource();this.vectorLayer = new VectorLayer({source: this.vectorSource,});// 引入天地图瓦片资源let source = new XYZ({url: 'http://t0.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=**这里用你申请的密钥**',})let tileLayer = new Tile({title: '天地图',source: source,})// 标注图层(行政区名称,道路)瓦片资源let sourceMark = new XYZ({url: "http://t0.tianditu.com/DataServer?T=cta_w&tk=**这里用你申请的密钥**&x={x}&y={y}&l={z}",})let tileMark = new Tile({title: '标注图层',source: sourceMark,})// 地铁路线图层// let sourceSubway = new XYZ({// 	url: '******'// })// let tileSubway = new Tile({// 	title: '地铁路线图层',// 	source: sourceSubway,// })// 地图实例this.map = new Map({controls: defaultControls({attribution: false,zoom: false,rotate: false,}),target: 'map', // 对应页面里 id 为 map 的元素layers: [tileLayer, tileMark], //若有其他图层如tileSubway,则可放进数组中进行初始化处理view: new View({// 地图视图projection: 'EPSG:4326', // 坐标系,有EPSG:4326和EPSG:3857center: [116.39, 39.92], // 中心坐标zoom: 12, // 地图缩放级别(打开页面时默认级别)minZoom: 1, // 地图缩放最小级别maxZoom: 18,enableRotation: false, //禁用旋转}),})},}	
}
</script>

实现效果如下:
在这里插入图片描述

4.在地图中添加标记点与多边形

预览效果:
在这里插入图片描述

4.1 renderjs方法调用
4.1.1 点击调用

页面中点击按钮调用renderjs中的方法,使用ol.方法名的方式进行调用,其中ol取标签<script module="ol" lang="renderjs">中module定义的名称,可调用的方法则需在methods: {...}内。
以示例中的按钮为例,点击按钮调用定位中心标记点: @click="ol.handleCenterIcon"

<view class="btn-area_item" @click="ol.handleCenterIcon">中心标记
</view>

此处需要特别注意在APP端可能出现点击后调用无效的问题,主要原因可能有:

  1. 写法不符合“仅支持内联事件”的限制;
  2. 节点被其它组件(slot、v-if、自定义组件、三方组件)重新包裹,导致编译期找不到模块前缀。

其根本原因是:事件指令被编译器识别失败时,框架不会把点击消息派发到 renderjs 层。
App 端 renderjs “无法点击” 99% 都是写法或节点被转包导致编译器没有生成视图层事件绑定,只要严格遵循:行内绑定、模块前缀、裸节点,三条规则,点击事件即可在 Android、iOS 真机正常调用renderjs 里的方法。

4.1.2 监听值变化时调用

在相关块级元素的节点上绑定监听数据与监听变化的目标方法。以示例中的gps值获取为例,监听设备gps值变化并调用renderjs中的getGps()方法:

<view id="map" class="map_x" :style="{height:mapHeightStr}" :gps="deviceGps" :change:gps="ol.getGps">
</view>

其中:gps=绑定需要监听的目标值,:change:gps=绑定监听后调用的方法。getGps()方法中则可接收新旧值,如getGps(newValue, oldValue)

4.2 绘制标记点与多边形范围
4.2.1 绘制标记点图标

目前在renderjs中需要使用图标等图片资源时,无法直接使用图标的路径进行处理,需要将图标资源转化为base64后再引入使用,以当前处理的方式为例:在地图组件文件夹内创建一个resource.js文件,在文件中定义好图标资源的名称,如const localtion = ""data:image/png;base64,iVBORw0KG...";,最后再统一export供renderjs进行使用。

绘制图标的主要方法如下:

// 定位中心点
handleCenterIcon() {let vectorSource = new VectorSource();// 全局定义,方便后续进行其他操作,如清除等this.iconLayer = new VectorLayer({source: vectorSource,})// 添加图层this.map.addLayer(this.iconLayer)// 设置图片位置this.iconFeature = new Feature({geometry: new Point([this.gps.lng, this.gps.lat]),});// 设置图标的资源与放大倍率this.iconFeature.setStyle(new Style({image: new Icon({src: imgs.navUp,scale: 0.5,}),}));// 将图片Feature添加到Sourcethis.iconLayer.getSource().addFeature(this.iconFeature)
}

此时,图标即可添加到地图上,但此时的图标不会随着地图的缩放而变化比例,针对实际的使用场景,需监听地图缩放,从而改变图标的显示比例。

监听地图缩放并改变图标显示比例的方法如下:

// 监听地图缩放,处理中心图标的相对大小
zoomChange() {let that = this// 监听缩放this.map.getView().on("change:resolution", function(res) {// 缩放大小let autoZoom = res.target.values_.zoom;that.realZoom = autoZoom;// 存在图标时,获取图标的显示倍率并按比例调整if (that.iconFeature) {let style = that.iconFeature.getStyle()style.getImage().setScale(autoZoom / 20);that.iconFeature.setStyle(style)}})
}

以上监听方法可以在地图初始化完成后进行调用。

4.2.2 绘制多边形范围

在绘制多边形时需要使用坐标数组,需根据业务实际提供的坐标,使用fromLonLat进行统一处理,并设置坐标系为EPSG:4326EPSG:3857等其他坐标系。

// 循环转换坐标点
for (let i = 0; i < len; i++) {let point = fromLonLat([path[i].lng, path[i].lat], 'EPSG:4326')finalPath.push(point)
}

4326 是“经纬度(度)”,3857 是“Web 墨卡托(米)”;

坐标系 EPSG 编码 单位 用途特点 天地图服务中的标识
WGS84 经纬度 EPSG:4326 全球通用,适合存储与计算,适合 GPS 原始坐标、OGC WFS/WMS 查询 TILEMATRIXSET=c
Web 墨卡托投影 EPSG:3857 网络地图通用,适合瓦片拼接、前端展示 TILEMATRIXSET=w

两坐标系在 OpenLayers 中的互转:

import {fromLonLat, toLonLat} from 'ol/proj';
// EPSG:4326 → EPSG:3857
const webMercator = fromLonLat([116.391, 39.907]);
// EPSG:3857 → EPSG:4326
const lonLat = toLonStr(webMercator);

绘制多边形范围的方法如下:

// 绘制任务路径范围
handlePolygon() {// 测试用路径let path = [{lng: 118.050,lat: 24.621},{lng: 118.083,lat: 24.624},{lng: 118.084,lat: 24.685},{lng: 118.055,lat: 24.686},];let finalPath = [];let len = path.length;// 无路径时直接返回,不渲染if (len == 0) {return false}// 循环转换坐标系for (let i = 0; i < len; i++) {let point = fromLonLat([path[i].lng, path[i].lat], 'EPSG:4326');finalPath.push(point);}// 配置多边形let polygon = new Polygon([finalPath]);let polygonFeature = new Feature({

文章转载自:

http://Bw6ixWGv.jfwrf.cn
http://rxEhAlPu.jfwrf.cn
http://fKxyfx9j.jfwrf.cn
http://hxGHbo1a.jfwrf.cn
http://mGdA7Wh3.jfwrf.cn
http://plnxX5A0.jfwrf.cn
http://eF6ot0tL.jfwrf.cn
http://MtlbSWFr.jfwrf.cn
http://8626tVDy.jfwrf.cn
http://8ZHgGFCH.jfwrf.cn
http://jO8amcI1.jfwrf.cn
http://J3mpGG83.jfwrf.cn
http://WdlWEDMf.jfwrf.cn
http://If8Pfa6c.jfwrf.cn
http://G1dVTt7F.jfwrf.cn
http://c1VR8aN5.jfwrf.cn
http://LHNot7vZ.jfwrf.cn
http://rzZoRxuq.jfwrf.cn
http://HtpJbt7f.jfwrf.cn
http://6eSs6VWY.jfwrf.cn
http://TNRTbDK7.jfwrf.cn
http://oXOJp0Zv.jfwrf.cn
http://LKwmhj93.jfwrf.cn
http://qKhvUm3c.jfwrf.cn
http://hBK22NSF.jfwrf.cn
http://5FNiMkLj.jfwrf.cn
http://Gtew0cyd.jfwrf.cn
http://hjOKCp47.jfwrf.cn
http://sxOR3Mgd.jfwrf.cn
http://0XdEkc9b.jfwrf.cn
http://www.dtcms.com/a/376503.html

相关文章:

  • 鸿蒙HAP包解包、打包、签名及加固全流程解析
  • [Leetcode 算法题单] 1456. 定长子串中元音的最大数目
  • 基于Springboot + vue实现的高校大学生竞赛项目管理系统
  • 为什么 socket.io 客户端在浏览器能连上,但在 Node.js 中报错 transport close?
  • Windows 命令行:切换盘符
  • 论文阅读记录之《VelocityGPT 》
  • 微服务通信实战篇:基于 Feign 的远程调用与性能优化
  • “双轮”驱动见成效 中和农信深耕乡村“最后一百米”
  • 高防IP怎样抵御CC攻击的频繁侵扰?
  • LeetCode 面试经典 150_矩阵_生命游戏(38_289_C++_中等)(额外状态)
  • Kotlin 2.2.20 现已发布!下个版本的特性抢先看!
  • Shell编程:计算鸡兔同笼问题
  • 如何解决pip安装报错ModuleNotFoundError: No module named ‘python-dateutil’问题
  • WenetSpeech-Yue数据集及其诞生之路
  • 用粒子群算法PSO优化BP神经网络改善预测精度
  • 百度文心X1.1发布!实测深度思考能力!
  • 第六篇:终极压力测试——故障注入测试(FIT)
  • 文心大模型 X1.1:百度交出的“新深度思考”答卷
  • 物联网平台中的MongoDB(二)性能优化与生产监控
  • 性能测试-jmeter9-逻辑控制器、定时器压力并发
  • 网络编程;TCP控制机械臂;UDP文件传输;0910;ps今天没写出来
  • Firefox Window 开发详解(一)
  • 无公网 IP 也能轻松访问家中群晖 NAS:神卓 NAT 盒子使用记
  • 01数据结构-B树
  • 2025年最强XPath定位工具:SelectorsHub在Chrome与Firefox中的全方位使用指南
  • 如何将音乐从Redmi手机转移到Redmi手机
  • 大数据与云计算知识点
  • 第5篇、 Kafka 数据可靠性与容错机制
  • EasyExcel部署Docker缺少字体报错
  • CentOS Steam 9安装 Redis