🚀 优质资源分享 🚀
学习路线指引(点击解锁) | 知识定位 | 人群定位 |
---|---|---|
🧡 Python实战微信订餐小程序 🧡 | 进阶级 | 本课程是python flask+微信小程序的完美结合,从项目搭建到腾讯云部署上线,打造一个全栈订餐系统。 |
💛Python量化交易实战💛 | 入门级 | 手把手带你打造一个易扩展、更安全、效率更高的量化交易系统 |
前言
在前面介绍了通过openlayers
加载dwg
格式的CAD
图并与互联网地图叠加,openlayers
功能很全面,但同时也很庞大,入门比较难,适合于大中型项目中。而在中小型项目中,一般用开源的leaflet比较多, leaflet
小而美,插件很多。本文介绍如何用Leaflet来加载DWG格式的CAD图,并在上面做应用开发,如与互联网地图叠加显示等。
Leaflet介绍
Leaflet
是领先的用于移动友好交互式地图的开源 JavaScript 库。仅仅重约 39KB 的 JS,它拥有大多数开发者所需要的所有地图功能。Leaflet
在设计时考虑到了简单性、性能和可用性。它可以在所有主要的桌面和移动平台上高效地工作,可以通过大量的插件进行扩展,拥有一个漂亮的、易于使用的、记录良好的 API,以及一个简单的、可读的源代码。。
Leaflet 官网地址 https://leafletjs.com/
Leaflet 源码地址 [https://github.com/Leaflet/
Leaflet中加载CAD栅格瓦片
在leaflet中加载CAD图,需要建立一个由cad建立的坐标系。可以由L.CRS.Simple
来进行扩展,设置好坐标系的范围、分辨率及转换参数即可。
| | // 地图服务对象,调用唯杰地图服务打开地图,获取地图的元数据 |
| | let svc = new vjmap.Service(env.serviceUrl, env.accessToken) |
| | // 打开地图 |
| | let mapId = "sys\_zp"; |
| | let res = await svc.openMap({ |
| | mapid: mapId, // 地图ID |
| | mapopenway: vjmap.MapOpenWay.GeomRender, // 以几何数据渲染方式打开 |
| | style: vjmap.openMapDarkStyle() // div为深色背景颜色时,这里也传深色背景样式 |
| | }) |
| | if (res.error) { |
| | // 如果打开出错 |
| | message.error(res.error) |
| | } |
| | // 获取地图范围 |
| | let mapBounds = vjmap.GeoBounds.fromString(res.bounds); |
| | |
| | // 建立一个基于CAD图范围的坐标系 |
| | let CadCRS = L.Class.extend({ |
| | includes: L.CRS.Simple, |
| | initialize: function (bounds) { |
| | // 当前CAD图的范围 |
| | this.bounds = bounds; |
| | // 投影 |
| | this.projection = L.Projection.LonLat; |
| | // 计算分辨率 |
| | let r = (256 / Math.abs(this.bounds.getEast() - this.bounds.getWest())); |
| | // 设置转换参数 一个仿射变换:一组系数a, b, c, d,用于将一个形式为(x, y)的点变换为 (ax + b, cy + d)并做相反的变换 |
| | this.transformation = new L.Transformation(r, -r * this.bounds.getWest(), - r, r * this.bounds.getNorth()); |
| | } |
| | }); |
| | |
| | // leaflet中坐标是反的,如果要用L.latLng传入坐标的时候要传[y,x],如果要传[x,y],官网建议如下方案 |
| | // https://leafletjs.com/examples/crs-simple/crs-simple.html |
| | L.XY = function(x, y) { |
| | if (L.Util.isArray(x)) { // When doing XY([x, y]); |
| | return L.latLng(x[1], x[0]); |
| | } |
| | return L.latLng(y, x); // When doing XY(x, y); |
| | }; |
| | |
| | // 当前CAD地图范围 |
| | let bounds = new L.LatLngBounds([L.XY(mapBounds.min.toArray()), L.XY(mapBounds.max.toArray())]); |
| | let center = mapBounds.center(); // 地图中心点 |
| | |
| | // 创建leaflet的地图对象 |
| | let map = L.map('map', { |
| | // 坐标系 |
| | crs: new CadCRS(bounds), |
| | attributionControl: false |
| | }).setView(L.XY([center.x, center.y]), 2); // 设置初始中心点和缩放级别 |
| | // 如果要用L.latLng设置的话,x,y应写反进行设置。如 |
| | // map.setView(L.latLng([center.y, center.x]), 2); |
| | |
| | // 增加一个栅格瓦片图层 |
| | let layer = L.tileLayer( |
| | svc.rasterTileUrl(), // 唯杰地图服务提供的cad的栅格瓦片服务地址 |
| | { |
| | bounds: bounds // 当前CAD地图范围 |
| | } |
| | ).addTo(map); |
| | // 把图层增加至地图中 |
| | layer.addTo(map); |
Leaflet中选择高亮CAD实体
选择高亮的实现思路为:响应地图的点击事件,通过当前位置去后台查询当前的实体的数据。通过返回的geojson数据,在前端用leaflet的geoJSON
进行绘制即可。
| | |
| | |
| | let highlightLayer; // 高亮图层 |
| | const highlight\_ent = async co => { |
| | if (highlightLayer) { |
| | highlightLayer.remove(); // 先删除之前的高亮图层 |
| | highlightLayer = null; |
| | } |
| | let res = await svc.pointQueryFeature({ |
| | x: co[0], |
| | y: co[1], |
| | zoom: map.getZoom(), |
| | fields: "" |
| | }, pt => { |
| | // 查询到的每个点进行坐标处理回调 |
| | return mapPrj.fromMercator(pt);// 转成cad的坐标 |
| | }) |
| | if (res && res.result && res.result.length > 0) { |
| | let features = []; |
| | for (let ent of res.result) { |
| | if (ent.geom && ent.geom.geometries) { |
| | let clr = vjmap.entColorToHtmlColor(ent.color); |
| | for (let g = 0; g < ent.geom.geometries.length; g++) { |
| | features.push({ |
| | type: "Feature", |
| | properties: { |
| | objectid