Openlayers介绍

​ Openlayers是一个基于Javacript开发,免费、开源的前端地图开发库,使用它,可以很容易的开发出WebGIS系统。目前Openlayers支持地图瓦片、矢量数据等众多地图数据格式,支持比较完整的地图交互操作。目前OpenLayers已经成为一个拥有众多开发者和帮助社区的成熟、流行的框架,在国内外的GIS相关行业中得到了广泛的应用。

openlayers 官网地址 https://openlayers.org/

openlayers 源码地址 https://github.com/openlayers/openlayers

Openlayers中加载CAD栅格瓦片

// 地图服务对象,调用唯杰地图服务打开地图,获取地图的元数据
let svc = new vjmap.Service(env.serviceUrl, env.accessToken)
// 打开地图
let mapId = "sys_zp";
let res = await svc.openMap({mapid: mapId, // 地图IDmapopenway: vjmap.MapOpenWay.GeomRender, // 以几何数据渲染方式打开style: vjmap.openMapDarkStyle() // div为深色背景颜色时,这里也传深色背景样式
})
if (res.error) {// 如果打开出错message.error(res.error)
}
// 获取地图范围
let mapBounds = vjmap.GeoBounds.fromString(res.bounds);//自定义投影参数
let cadProjection = new ol.proj.Projection({// extent用于确定缩放级别extent: mapBounds.toArray(),units: 'm'
});
// 设置每级的分辨率
let resolutions= [];
for(let i = 0; i < 25; i++) {resolutions.push(mapBounds.width() / (512 * Math.pow(2, i - 1)))
}
// 增加自定义的cad的坐标系
ol.proj.addProjection(cadProjection);// 创建openlayer的地图对象
let map = new ol.Map({target: 'map', // div的idview: new ol.View({center: mapBounds.center().toArray(),  // 地图中心点projection: cadProjection, // 刚自定义的cad的坐标系resolutions:resolutions, // 分辨率zoom: 2// 初始缩放级别})
});// 增加一个瓦片图层
let layer = new ol.layer.Tile({// 增加一个瓦片数据源source: new ol.source.TileImage({url: svc.rasterTileUrl() // 唯杰地图服务提供的cad的栅格瓦片服务地址})
});
// 在地图中增加上面的瓦片图层
map.addLayer(layer);

Openlayers中加载CAD矢量瓦片


// 增加一个矢量瓦片图层
let layer = new ol.layer.VectorTile({// 增加一个瓦片数据源source: new ol.source.VectorTile({projection: cadProjection,format: new ol.format.MVT(),url: svc.vectorTileUrl() // 唯杰地图服务提供的cad的矢量瓦片服务地址}),style: createVjMapVectorStyle(ol.style.Style, ol.style.Fill, ol.style.Stroke, ol.style.Circle)
});
// 在地图中增加上面的瓦片图层
map.addLayer(layer);

Openlayers中选择高亮CAD实体


const highlight_ent = async co => {vectorSource.clear();let res = await svc.pointQueryFeature({x: co[0],y: co[1],zoom: map.getView().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: ent.objectid + "_" + g,color: clr,alpha: ent.alpha / 255,lineWidth: 1,name: ent.name,isline: ent.isline,layerindex: ent.layerindex},geometry: ent.geom.geometries[g]})}// 选择提示let content = `feature: ${ent.objectid}; layer: ${cadLayers[ent.layerindex].name}; type: ${ent.name}`message.info({ content, key: "info", duration: 3});}}geojsonObject.features = features;if (geojsonObject.features.length > 0) {vectorSource.addFeatures( new ol.format.GeoJSON().readFeatures(geojsonObject, {dataProjection: cadProjection}))}}
};

Openlayers中上传打开CAD的DWG图形


// 地图服务对象,调用唯杰地图服务打开地图,获取地图的元数据
let svc = new vjmap.Service(env.serviceUrl, env.accessToken)// 上传dwg文件
const uploadDwgFile = async file => {message.info("正在上传图形,请稍候", 2);let res = await svc.uploadMap(file); // 上传地图// 输入图idlet mapid = prompt("请输入图名称ID", res.mapid);res.mapid = mapid;res.mapopenway = vjmap.MapOpenWay.GeomRender; // 几何渲染,内存渲染用vjmap.MapOpenWay.Memoryres.isVector = false; // 使用栅格瓦片res.style = vjmap.openMapDarkStyle(); // 深色样式,浅色用openMapDarkStylemessage.info("正在打开图形,请稍候,第一次打开时根据图的大小可能需要几十秒至几分钟不等", 5);let data = await svc.openMap(res); // 打开地图if (data.error) {message.error(data.error)return;}openMap(data);
}

Openlayers中切换CAD图层

// 切换图层
const switchLayer = async layers => {let res = await svc.cmdSwitchLayers(layers); // 调用唯杰服务切换图层,返回图层id {layerid: "xxxx"}let source = layer.getSource();// 重新设置新的唯杰地图服务提供的cad的栅格瓦片服务地址source.setUrl(svc.rasterTileUrl());// 刷新source.refresh();
}

Openlayers中切换CAD图形


const switchToMapId = async (mapId)=> {let res = await svc.openMap({mapid: mapId, // 地图IDmapopenway: vjmap.MapOpenWay.GeomRender, // 以几何数据渲染方式打开style: vjmap.openMapDarkStyle() // div为深色背景颜色时,这里也传深色背景样式})if (res.error) {// 如果打开出错message.error(res.error)return;}
// 获取地图范围let mapBounds = vjmap.GeoBounds.fromString(res.bounds);//自定义投影参数let cadProjection = new ol.proj.Projection({// extent用于确定缩放级别extent: mapBounds.toArray(),units: 'm'});
// 设置每级的分辨率let resolutions= [];for(let i = 0; i < 25; i++) {resolutions.push(mapBounds.width() / (512 * Math.pow(2, i - 1)))}
// 增加自定义的cad的坐标系ol.proj.addProjection(cadProjection);// 重新创建openlayer的地图对象map = new ol.Map({target: createNewMapDivId(), // div的idview: new ol.View({center: mapBounds.center().toArray(),  // 地图中心点projection: cadProjection, // 刚自定义的cad的坐标系resolutions:resolutions, // 分辨率zoom: 2 // 初始缩放级别})});// 增加一个瓦片图层let layer = new ol.layer.Tile({// 增加一个瓦片数据源source: new ol.source.TileImage({url: svc.rasterTileUrl() // 唯杰地图服务提供的cad的栅格瓦片服务地址})});
// 在地图中增加上面的瓦片图层map.addLayer(layer);map.on('click', (e) => message.info({content: `您点击的坐标为: ${JSON.stringify(e.coordinate)}`, key: "info", duration: 3}));
}

Openlayers中深色浅色切换主题

let curIsDarkTheme = true;
const switchToDarkTheme = async () => {if (curIsDarkTheme) return;curIsDarkTheme = true;document.body.style.background = "#022B4F"; // 背景色改为深色await updateStyle(curIsDarkTheme)
}const switchToLightTheme = async () => {if (!curIsDarkTheme) return;curIsDarkTheme = false;document.body.style.backgroundImage = "linear-gradient(rgba(255, 255, 255, 1), rgba(233,255,255, 1), rgba(233,255,255, 1))"await updateStyle(curIsDarkTheme)
}const updateStyle = async (isDarkTheme) => {style.backcolor = isDarkTheme ? 0 : 0xFFFFFF;//深色为黑色,浅色为白色let res = await svc.cmdUpdateStyle(style);let source = layer.getSource();// 重新设置新的唯杰地图服务提供的cad的栅格瓦片服务地址source.setUrl(svc.rasterTileUrl());// 刷新source.refresh();
}

Openlayers中自定义CAD地图样式

通过修改CAD地图后台样式数据自定义地图


// 更改样式
const expressionList = [] ;// 表达式数组
const updateStyle = async (style) => {let res = await svc.cmdUpdateStyle({name: "customStyle2",backcolor: 0,expression: expressionList.join("\n"),...style});let source = layer.getSource();// 重新设置新的唯杰地图服务提供的cad的栅格瓦片服务地址source.setUrl(svc.rasterTileUrl());// 刷新source.refresh();
}// 表达式语法和变量请参考
// 服务端条件查询和表达式查询 https://vjmap.com/guide/svrStyleVar.html
// 服务端渲染表达式语法 https://vjmap.com/guide/expr.html// 修改颜色  红color.r, 绿color.g, 蓝color.b, 透明度color.a,如果输入了级别的话,表示此级别及以上的设置
const modifyColor = (color, zoom) => {let result = "";let z = Number.isInteger(zoom) ? `[${zoom + 1}]` : '';if ("r" in color) result += `gOutColorRed${z}:=${color.r};`;if ("g" in color) result += `gOutColorGreen${z}:=${color.g};`;if ("b" in color) result += `gOutColorBlue${z}:=${color.b};`;if ("a" in color) result += `gOutColorAlpha${z}:=${color.a};`;return result;
}

Openlayers中对CAD图处理组合

对多个cad图进行图层开关裁剪旋转缩放处理后合并成一个新的cad图


// 组合成新的图,将sys_world图进行一定的处理后,再与sys_hello进行合成,生成新的地图文件名
let rsp = await svc.composeNewMap([{mapid: "sys_world", // 地图id// 下面的参数可以根据实际需要来设置,可以对图层,范围,坐标转换来进行处理layers: ["经纬度标注","COUNTRY"], // 要显示的图层名称列表//clipbounds: [10201.981489534268, 9040.030491346213, 26501.267379,  4445.465999], // 要显示的范围//fourParameter: [0,0,1,0] // 对地图进行四参数转换计算},{mapid: "sys_hello"}
])
if (!rsp.status) {message.error(rsp.error)
}
// 返回结果为
/*
{"fileid": "pec9c5f73f1d","mapdependencies": "sys_world||sys_hello","mapfrom": "sys_world&&v1&&&&0&&&&&&&&&&00A0&&10||sys_hello&&v1&&&&0&&&&&&&&&&&&2","status": true
}*/

Openlayers中查询图中所有文字并绘制边框


// 实体类型ID和名称映射
const { entTypeIdMap } = await svc.getConstData();
const getTypeNameById = name => {for(let id in entTypeIdMap) {if (entTypeIdMap[id] == name) {return id}}
}
const queryTextAndDrawBounds = async () => {let queryTextEntTypeId = getTypeNameById("AcDbText"); // 单行文字let queryMTextEntTypeId = getTypeNameById("AcDbMText"); // 多行文字let queryAttDefEntTypeId = getTypeNameById("AcDbAttributeDefinition"); // 属性定义文字let queryAttEntTypeId = getTypeNameById("AcDbAttribute"); // 属性文字let query = await svc.conditionQueryFeature({condition: `name='${queryTextEntTypeId}' or name='${queryMTextEntTypeId}' or name='${queryAttDefEntTypeId}' or name='${queryAttEntTypeId}'`, // 只需要写sql语句where后面的条件内容,字段内容请参考文档"服务端条件查询和表达式查询"fields: "",limit: 100000 //设置很大,相当于把所有的圆都查出来。不传的话,默认只能取100条}, pt => {// 查询到的每个点进行坐标处理回调return mapPrj.fromMercator(pt);// 转成cad的坐标})if (query.error) {message.error(query.error)} else {message.info(`查询到符合的记数条数:${query.recordCount}`)if (query.recordCount > 0) {let features = [];for(var i = 0; i < query.recordCount; i++) {let bounds = vjmap.getEnvelopBounds(query.result[i].envelop, mapPrj);let clr = vjmap.entColorToHtmlColor(query.result[i].color); // 实体颜色转html颜色(features.push({type: "Feature",properties: {name: "objectid:" + query.result[i].objectid,color: clr},geometry: {'type': 'Polygon','coordinates': [bounds.toPointArray(),],}})}if (!vectorSource) {// 如果之前没有高亮矢量图层addHighLightLayer();}vectorSource.clear();let geojsonObject = {'type': 'FeatureCollection','features': features}// 修改矢量数据源数据vectorSource.addFeatures( new ol.format.GeoJSON().readFeatures(geojsonObject, {dataProjection: cadProjection}))}}
}

Openlayers中图形绘制


const source = new ol.source.Vector({wrapX: false});const vector = new ol.layer.Vector({source: source,
});map.addLayer(vector);let draw; // global so we can remove it later
function addInteraction(value) {map.removeInteraction(draw);if (value !== 'None') {draw = new ol.interaction.Draw({source: source,type: value,});map.addInteraction(draw);}
}addInteraction('Point');

Openlayers中CAD图叠加互联网地图[CAD为底图]


// 增加高德地图底图
let gdlayer;
const addGaodeMap = async (isRoadway) => {const tileUrl = svc.webMapUrl({tileCrs: "gcj02",tileUrl:  isRoadway ? ["https://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}"] :/* 如果用影像 */["https://webst0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=6&x={x}&y={y}&z={z}","https://webst0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}"],tileSize: 256,tileRetina: 1,tileMaxZoom: 18,tileShards: "1,2,3,4",tileToken: "",tileFlipY: false,mapbounds: res.bounds,srs: "EPSG:4527",// 可通过前两位获取 vjmap.transform.getEpsgParam(vjmap.transform.EpsgCrsTypes.CGCS2000, 39).epsg// 因为sys_cad2000这个图只有6位,没有带系。需要在坐标转换前平移下带系  https://blog.csdn.net/thinkpang/article/details/124172626fourParameterBefore: "39000000,0,1,0"})// 增加一个瓦片图层gdlayer = new ol.layer.Tile({// 增加一个瓦片数据源source: new ol.source.TileImage({url: tileUrl})});gdlayer.setZIndex(-1);
// 在地图中增加上面的瓦片图层map.addLayer(gdlayer);// cad坐标与高德坐标相互转换示例let webCo = await cad2webCoordinate(center, false); // cad转高德let cadCo = await web2cadCoordinate(webCo, false); // 高德转cadconsole.log(center, webCo, cadCo)
}

Openlayers中互联网地图自动叠加CAD图[互联网图为底图]


let cadEpsg = "EPSG:4544";// cad图的espg代号
// 增加cad的wms图层
let wmsUrl = svc.wmsTileUrl({mapid: mapId, // 地图idlayers: layer, // 图层名称bbox: '', // bbox这里不需要srs: "EPSG:3857", //crs: cadEpsg
})
function getQueryStringArgs(url) {let theRequest = {};let idx = url.indexOf("?");if (idx != -1) {let str = url.substr(idx + 1);let strs = str.split("&");for (let i = 0; i < strs.length; i++) {let items = strs[i].split("=");theRequest[items[0]] = items[1];}}return theRequest;
}let mapBounds = vjmap.GeoBounds.fromString(res.bounds);
// cad图坐标转web wgs84坐标
const cadToWebCoordinate = async point => {let co = await svc.cmdTransform(cadEpsg, "EPSG:4326", point);return co[0]
}
// cad转wgs84经纬度
let boundsMin = await cadToWebCoordinate(mapBounds.min);
let boundsMax = await cadToWebCoordinate(mapBounds.max);
// wgs84经纬度转墨卡托
boundsMin = vjmap.Projection.lngLat2Mercator(boundsMin);
boundsMax = vjmap.Projection.lngLat2Mercator(boundsMax);// 在openlayer中增加wms图层
map.addLayer(new ol.layer.Tile({// 范围extent: [boundsMin[0], boundsMin[1], boundsMax[0], boundsMax[1]],source: new ol.source.TileWMS({url: wmsUrl.substr(0, wmsUrl.indexOf("?")),params: {...getQueryStringArgs(wmsUrl),'TILED': true}}),
}))

Openlayers中互联网地图公共点叠加CAD图[互联网图为底图]


// cad上面的点坐标
let cadPoints = [vjmap.geoPoint([587464448.8435847, 3104003685.208651,]),vjmap.geoPoint([587761927.7224838, 3104005967.655292]),vjmap.geoPoint([587463688.0280377, 3103796743.3798513]),vjmap.geoPoint([587760406.0913897, 3103793700.1176634])
];// 在互联网图上面拾取的与上面的点一一对应的坐标(wgs84坐标)
let webPoints = [vjmap.geoPoint([116.48476281710168, 39.96200739703454]),vjmap.geoPoint([116.48746772021137, 39.96022062215167]),vjmap.geoPoint([116.48585059441585, 39.9588451134361]),vjmap.geoPoint([116.48317418949145, 39.960515760972356])
]
// 通过坐标参数求出四参数
let epsg3857Points = webPoints.map(w => vjmap.geoPoint(vjmap.Projection.lngLat2Mercator(w)));
let param = vjmap.coordTransfromGetFourParamter(epsg3857Points, cadPoints , false); // 这里考虑旋转
let fourparam = [param.dx, param.dy, param.scale, param.rotate]// wms图层地址
const getCadWmsUrl = (transparent) => {let wmsUrl = svc.wmsTileUrl({mapid: mapId, // 地图idlayers: layer, // 图层名称bbox: '', // bbox这里不需要fourParameter: fourparam,transparent: transparent,backgroundColor: 'rgba(240, 255, 255)' // 不透明时有效})return wmsUrl
}let mapBounds = vjmap.GeoBounds.fromString(res.bounds);
let cadPrj = new vjmap.GeoProjection(mapBounds);// cad图坐标转3857坐标
const cadToWebCoordinate = point => {// 再调用四参数反算求出web的坐标return vjmap.coordTransfromByInvFourParamter(vjmap.geoPoint(point), param)
}
// 3857转cad图坐标
const webToCadCoordinate = point => {return vjmap.coordTransfromByFourParamter(vjmap.geoPoint(point), param)
}let wmsLayer;
const addWmsLayer = async (transparent)=> {removeWmsLayer();let wmsUrl = getCadWmsUrl(transparent);wmsLayer = new ol.layer.Tile({// 范围extent: bounds.toArray(),source: new ol.source.TileWMS({url: wmsUrl.substr(0, wmsUrl.indexOf("?")),params: {...getQueryStringArgs(wmsUrl),'TILED': true}}),});// 在openlayer中增加wms图层map.addLayer(wmsLayer);
}

最后

可点击 https://vjmap.com/demo/#/demo/map/openlayers/01olraster 在线体验上面功能

如果需要用openlayers来加载CAD图进行开发,请参考示例 https://vjmap.com/demo/#/demo/map/openlayers/01olraster

如果需要用leaflet来加载CAD图进行开发,请参考示例 https://vjmap.com/demo/#/demo/map/leaflet/01leafletraster

如果需要用maptalks来加载CAD图进行开发,请参考示例 https://vjmap.com/demo/#/demo/map/maptalks/01maptalksraster

如何基于vue3来开发openlayers应用,可查看此开源代码 https://github.com/MelihAltintas/vue3-openlayers

如何基于vue2来开发openlayers应用,可查看此开源代码 https://github.com/ghettovoice/vuelayers

通过openlayers加载dwg格式的CAD图并与互联网地图叠加相关推荐

  1. 如何实现通过Leaflet加载dwg格式的CAD图

  2. android中读取svg文件,Android如何加载SVG格式的矢量图

    为何要加载SVG图片 相对于.JPG和.PNG甚至.webp的图片来说,SVG的图片有两个优点,第一:省空间,APK瘦身有一个方面就是从图片瘦身,使用SVG图片可以大量减轻程序的大小.第二:省时间,切 ...

  3. 通过 OpenLayers 加载CAD导出位图 和 math.js 构造的仿射变换实现地理坐标系到任意CAD图上像素坐标系的互转

    WebGIS开发过程中会遇到这样一种情况:需要使用OpenLayers加载一个未校准的CAD导出的位图:并且还需要通过经纬度坐标数据在这个位图上做一些标记,还需要能通过在OpenLayers取得的图上 ...

  4. Vue中使用Openlayers加载Geoserver发布的TileWMS时单击获取shp文件的坐标信息

    场景 Vue中使用Openlayers加载Geoserver发布的TileWMS: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/ ...

  5. OpenLayers 加载天地图

    要使用 OpenLayers 3 加载天地图,首先要弄清楚天地图发布的原理,以及遵循的发布规范,上一篇中我们提到了使用 OpenLayers 3 加载百度地图,我们提到一般网络地图为了加快访问速度,都 ...

  6. openlayers加载本地arcgis切片(explodes)的两种方式,利用geowebcache进行发布和直接读取本地切片

    由于Arcgis的普及,经常会使用ArcgisServer对地图进行切片,且缓存在本地.如果能使用开源工具对该本地缓存进行加载的话,有时候能够节省不少精力和时间,因此本人对openlayers加载ar ...

  7. Openlayers加载离线地图Arcgis瓦片

    文章目录 一.介绍 二.快速入门 一.下载地图瓦片 二.OpenLayers加载离线Arcgis瓦片 一.介绍 OpenLayers 是一个专为Web GIS 客户端开发提供的JavaScript 类 ...

  8. Vue+Openlayers加载Geoserver发布的TileWMS后更换shp数据源的流程

    场景 Vue中使用Openlayers加载Geoserver发布的TileWMS: Vue中使用Openlayers加载Geoserver发布的TileWMS_BADAO_LIUMANG_QIZHI的 ...

  9. Vue中使用Openlayers加载Geoserver发布的TileWMS

    场景 Openlayers下载与加载geoserver的wms服务显示地图: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/114 ...

最新文章

  1. labview曲线上两点画延长线_教你用直尺画各种几何图形
  2. 【哈佛商评】关于数据分析,管理者的四个常规错误
  3. [js高手之路] 跟GhostWu一起封装一个字符串工具库-扩展字符串位置方法(4)
  4. 如何为物联网选择微控制器?
  5. 收藏!MySQL 面试必须掌握的 8 个知识点!
  6. python库怎么绘画_python中的turtle库(图形绘画库)
  7. 【PMP认证考试之个人总结】第 3 章 项目整合管理
  8. php云标签,php 创建标签云的代码示例
  9. Java8实现List转Map
  10. 全面解析 UI/UE/交互设计
  11. nRF52 PWM 使用
  12. 如何把root登陆的shell改为csh?
  13. 飞书从个性到共性,企业微信从共性到个性
  14. 齐天大圣蟠桃园吃桃子
  15. 批量将MP3或者m4a转为wav格式
  16. s2sh整合(详细版)
  17. android手机CPU的浅显认识与比较
  18. web安全防火墙介绍
  19. 论金融IT公司程序员的职业发展
  20. 1.1 命题逻辑 笔记

热门文章

  1. 武大计算机学院钱铁云,何德彪(武汉大学计算机学院教授)_百度百科
  2. 电动牙刷的正确使用方法
  3. Ajax处理servlet的返回值
  4. 2020ICPC·小米 网络选拔赛第一场 D.Router Mesh
  5. XMC外设学习之USIC
  6. 新建项目拷贝html报错,ESA2GJK1DH1K基础篇: 移植源码中SmartConfig程序到自己的项目...
  7. 艾司博讯:拼多多上开店铺需要什么条件
  8. 【操作系统之哲学导论】其它
  9. 单片机快速开方 -- 整数开方
  10. 词对齐任务:依附于机器翻译