openlayers
本文回答:在 OpenLayers 项目里叠加 vjmap CAD。
一、OL 上叠 CAD WMS
import "ol/ol.css";
import Map from "ol/Map";
import View from "ol/View";
import TileLayer from "ol/layer/Tile";
import TileImage from "ol/source/TileImage";
import TileWMS from "ol/source/TileWMS";
const svc = new vjmap.Service(URL, TOKEN);
await svc.openMap({ mapid: "sys_cad2000", mapopenway: vjmap.MapOpenWay.GeomRender });
const wmsUrl = svc.wmsTileUrl({
mapid: "sys_cad2000",
layers: "默认图层名",
bbox: "", // ⚠️ 必传空串:默认 "{bbox-epsg-3857}" 只有 vjmap 引擎会填,OL 不认
srs: "EPSG:3857",
crs: "EPSG:4548" // sys_cad2000 是 CGCS2000 3° 带 117°E(无带号)
});
// 用 TileWMS(由它追加 BBOX);TileImage 会把 {bbox-epsg-3857} 原样发给后端
const cadLayer = new TileLayer({
source: new TileWMS({ url: wmsUrl, params: { TILED: true } })
});
const olMap = new Map({
target: "map",
layers: [cadLayer],
view: new View({ center: [13000000, 3100000], zoom: 16 })
});
二、以 CAD 为底图,加互联网瓦片
webMapUrl 返回的瓦片按 vjmap 的 CAD 瓦片网格切,OL 的 View 必须用以 CAD 范围为 extent 的自定义投影 + 匹配的 resolutions(官方示例 12olwebCad.js),CAD 本身用 svc.rasterTileUrl() 作底图;在默认 EPSG:3857 的 View 上叠不齐:
import Projection from "ol/proj/Projection";
import { addProjection } from "ol/proj";
const mapBounds = vjmap.GeoBounds.fromString(res.bounds);
const cadProjection = new Projection({ code: "cad", extent: mapBounds.toArray(), units: "m" });
addProjection(cadProjection);
const resolutions = [];
for (let i = 0; i < 25; i++) resolutions.push(mapBounds.width() / (512 * Math.pow(2, i - 1)));
const olMap = new Map({
target: "map",
layers: [new TileLayer({ source: new TileImage({ url: svc.rasterTileUrl() }) })], // CAD 底图
view: new View({ projection: cadProjection, resolutions, center: mapBounds.center().toArray(), zoom: 9 })
});
再叠互联网瓦片:
const tileUrl = svc.webMapUrl({
tileCrs: "gcj02",
tileUrl: ["https://webrd0{s}.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=8&x={x}&y={y}&z={z}"],
tileSize: 256,
tileShards: "1,2,3,4",
mapbounds: res.bounds,
srs: "EPSG:4527",
fourParameterBefore: "39000000,0,1,0"
});
const gdLayer = new TileLayer({
source: new TileImage({ url: tileUrl }),
zIndex: -1
});
olMap.addLayer(gdLayer);
三、坐标系配置
OL 默认 EPSG:3857。如果 CAD 是 WMS-based 叠加,已经由 WMS 服务做坐标转换,不需动 OL 投影。
如果想让 OL 直接用 CAD 坐标系(EPSG:4544 等):
import proj4 from "proj4";
import { register } from "ol/proj/proj4";
import { get as getProjection } from "ol/proj";
proj4.defs("EPSG:4544", "+proj=tmerc +lat_0=0 +lon_0=105 +k=1 +x_0=500000 +y_0=0 +ellps=GRS80 +units=m +no_defs"); // 4544 = CGCS2000 3° 带 105°E;117°E 是 EPSG:4548
register(proj4);
const view = new View({
projection: getProjection("EPSG:4544"),
center: [100000, 3000000],
zoom: 14
});
四、点击查询
olMap.on("click", async (evt) => {
const [lng, lat] = evt.coordinate; // EPSG:3857 坐标(默认)
// 转 CAD
// 目标 EPSG 必须与 WMS 的 crs 一致(sys_cad2000 → EPSG:4548)
const r = await svc.cmdTransform("EPSG:3857", "EPSG:4548", vjmap.geoPoint([lng, lat])); // 必须 geoPoint 包装,裸数组会序列化成 undefined,undefined
const [x, y] = r[0];
// 查询附近实体:zoom 参数按 vjmap 的缩放级别换算像素容差,OL 的 zoom 不是同一套——改传每像素地理长度
const q = await svc.pointQueryFeature({
x, y, pixelsize: 5,
pixelToGeoLength: olMap.getView().getResolution() // 3857 米/像素,近似 CAD 米(纬度 φ 处偏大 1/cosφ),作拾取容差够用
});
console.log(q);
});
五、常见坑
-
OL 默认 tileSize 256 → 没问题;vjmap WMS 动态生成瓦片会按请求 size 渲染。
-
图像旋转:WMS
useImageRotate默认自动;若底图与 CAD 有夹角会自动旋转。 -
OL 不支持
{s}subdomain → 用 tileUrls 数组自己做负载均衡:source: new TileImage({ urls: [url1, url2, url3] })