---
title: 三维应用
source: https://vjmap.com/guide/map3dapp.html
---

# 三维应用

## 介绍 
[唯杰地图3D](https://vjmap.com/map3d) `VJMAP3D`是一款基于[threejs](https://threejs.org/)开发的三维可视化引擎框架。通过VJMAP3D提供的丰富的功能，可以在浏览器中创建出绚丽的3D可视化应用。

该框架既可做为一个单独的3D引擎用于数据可视化、产品展示、数字孪生、三维GIS等多个领域的可视化开发, 也可以结合`唯杰地图VJMAP`做为一个`3D`图层，能够在保留二维图形信息的直观性同时，融入三维空间的深度感知和交互性，为用户带来更丰富、立体和沉浸式的视觉体验及数据分析能力。

具有如下特点：

- 完全兼容`AutoCAD`格式的`DWG`文件展示，无需转换
- 兼容`唯杰地图`，同一套框架，同一套代码，既兼容`VJMAP`的`3D`图层，又可单独做为三维引擎使用
- 基于`threejs`开发，兼容`threejs`写法。`threejs`拥有庞大的开发者社区和丰富的教程资源，能利用`threejs`生态资源
- 易用性高：学习门槛低，提供丰富的API接口，便于快速上手开发3D应用。
- 丰富的内置功能：提供了预设对象和材质，以及粒子系统、后期处理等高级特性，便于快速实现复杂视觉效果。
- 交互设计：提供丰富的交互组件和事件处理机制，增强用户体验和应用互动性。支持场景中的对象拾取与交互，简化了交互逻辑的实现。
- 扩展性强：基于模块化开发，支持自定义扩展，满足多样化开发需求。


 `vjmap3d`既可做为一个单独的3D引擎, 也可以基于[唯杰地图VJMAP](https://vjmap.com/doc/)做为一个`3D`图层，能够在保留二维图形信息的直观性同时，融入三维空间的深度感知和交互性，为用户带来更丰富、立体和沉浸式的视觉体验及数据分析能力。



 [唯杰地图3D官网](https://vjmap.com/map3d/)

 [唯杰地图3D文档](https://vjmap.com/map3d/docs/)

 [唯杰地图3D开发示例](https://vjmap.com/map3d/demo/#/gallery/map)

 [唯杰地图3D案例](https://vjmap.com/map3d/example.html)



## 做为唯杰地图的三维图层

 其步骤为：
 - 引入`vjmap`sdk,创建`vjmap.Map`地图对象，具体示例可查看 [https://vjmap.com/demo](https://vjmap.com/demo)
 - 创建 [MapThreeLayer](https://vjmap.com/map3d/api/classes/MapThreeLayer.html) 3d图层
 - 通过`map.addLayer`增加3d图层，通过3d图层获取[App](https://vjmap.com/map3d/api/classes/App.html)对象。

 示例如下:

<mapFrameEx>
<pre>
let svc = new vjmap.Service(env.serviceUrl, env.accessToken)
// 打开地图
let res = await svc.openMap({
    mapid: env.exampleMapId, // 地图ID
    // @ts-ignore
    mapopenway: vjmap.MapOpenWay.GeomRender, // 以几何数据渲染方式打开
    style: vjmap.openMapLightStyle() // div为深色背景颜色时，这里也传深色背景样式
})
if (res.error) {
    // 如果打开出错
    showError(res.error)
    return;
}
// 获取地图范围
let mapBounds = vjmap.GeoBounds.fromString(res.bounds);
// 根据地图范围建立几何投影坐标系
let prj = new vjmap.GeoProjection(mapBounds);
//
// 地图对象
let map = new vjmap.Map({
    container: 'map', // DIV容器ID
    style: svc.rasterStyle(), // 样式，这里是栅格样式
    center: prj.toLngLat(mapBounds.center()), // 设置地图中心点
    zoom: 2, // 设置地图缩放级别
    pitch: 45,
    antialias: true, // 反锯齿
    renderWorldCopies: false // 不显示多屏地图
});
//
// 关联服务对象和投影对象
map.attach(svc, prj);
await map.onLoad();
//
// 创建3d图层
let mapLayer = new vjmap3d.MapThreeLayer(map, {
    stat: {
        show: true,
        left: "0"
    }
});
map.addLayer(new vjmap.ThreeLayer({ context: mapLayer }))
let app = mapLayer.app;
//
// 在CAD图中心上方创建一个Mesh
let cadLen = mapBounds.width() / 50; // 取cad图长度的1/50
let len = vjmap3d.toDist(cadLen); // cad长度转世界坐标长度
let box = new THREE.BoxGeometry(len, len, len)
const material = new THREE.MeshStandardMaterial({
    color: "#f00",
    side: THREE.DoubleSide
});
let mesh = new THREE.Mesh(box, material);
let cadPos = [mapBounds.center().x, mapBounds.center().y, cadLen]; // mesh在cad中坐标
//
let worldPos = vjmap3d.toWorld(cadPos);// cad坐标转世界坐标
mesh.position.copy(worldPos);
//app.scene.add(mesh) // 可以直接把 mesh 加进场景中不与实体相关联
// 创建一个实体与mesh相关联
let entity = vjmap3d.Entity.fromObject3d(mesh);
entity.addTo(app);
// 增加一个事件模块，用来高亮提示
entity.add(vjmap3d.EventModule, {
    hoverSelect: true,
    hoverHtmlText: '我是用vjmap3d创建的Box',
    popupOptions: {
        anchor: "bottom"
    }
});
</pre>
</mapFrameEx>
   


[点击查看 做为唯杰地图的三维图层具体 案例效果]( https://vjmap.com/effect/design3d/?map2d=true)
![image-20240923105036677](https://vjmap.com/blogimages/202409231050875.png)
  

     

## 创建CAD为底图的3D应用

通过 `vjmap3d` 中的 [MapViewEntity](https://vjmap.com/map3d/api/classes/MapViewEntity.html) 来创建一个地图实体。

<mapFrameEx>
<pre>
// 创建一个服务类，与服务连接
let svc = new vjmap3d.Service(env.serviceUrl, env.accessToken);
let app = new vjmap3d.App(svc, {
    container: "map", // 容器id
    camera: {  // 相机设置
        viewHelper: { enable: true } // 是否显示视角指示器
    }
})
let res = await app.svc.openMap({
        mapid: env.exampleMapId, // 地图ID,(请确保此ID已存在，可上传新图形新建ID)
        mapopenway: vjmap3d.MapOpenWay.GeomRender, // 以几何数据渲染方式打开
        style: vjmap3d.openMapDarkStyle()
});
if (res.error) {
    showError(res.error);
    return;
}
// 获取当前地图的可视范围
let clipPolygon = vjmap3d.GeoBounds.fromString(res.drawBounds).toPointArray();
let provider = new vjmap3d.MapProvider(
    [
        {
            url: app.svc.rasterTileUrl()
        }
    ],
    {
        transparent: true
    }
);
let mapBounds = vjmap3d.GeoBounds.fromString(res.bounds)
let scale = 100;
let mapviewEnt = new vjmap3d.MapViewEntity({
    provider,
    baseScale: scale,
    mapBounds: mapBounds.toArray(),
    clipPolygon //  如果透明的话，不能使用裁剪区载
});
mapviewEnt.addTo(app);
//
// 在CAD图中心上方创建一个Mesh
let cadLen = mapBounds.width() / 50; // 取cad图长度的1/50
let len = vjmap3d.toDist(cadLen); // cad长度转世界坐标长度
let box = new THREE.BoxGeometry(len, len, len)
const material = new THREE.MeshStandardMaterial({
    color: "#f00",
    side: THREE.DoubleSide
});
let mesh = new THREE.Mesh(box, material);
let cadPos = [mapBounds.center().x, mapBounds.center().y, cadLen]; // mesh在cad中坐标
//
let worldPos = vjmap3d.toWorld(cadPos);// cad坐标转世界坐标
mesh.position.copy(worldPos);
//app.scene.add(mesh) // 可以直接把 mesh 加进场景中不与实体相关联
// 创建一个实体与mesh相关联
let entity = vjmap3d.Entity.fromObject3d(mesh);
entity.addTo(app);
// 增加一个事件模块，用来高亮提示
entity.add(vjmap3d.EventModule, {
    hoverSelect: true,
    hoverHtmlText: '我是用vjmap3d创建的Box',
    popupOptions: {
        anchor: "bottom"
    }
});
</pre>
</mapFrameEx>
       


[点击查看 做为唯杰地图的三维图层具体 案例效果]( https://vjmap.com/effect/design3d/)
![image-20240923110109457](https://vjmap.com/blogimages/202409231101523.png)
  
       

::: tip 总结
使用`vjmap3d`创建`3d应用` 和 `做为唯杰地图的三维图层` 使用，除了初始化代码不同外，业务代码基本上可复用，做到同一套代码用在不同的框架上。

需要说明的是：当`vjmap3d`做为唯杰地图的三维图层使用时，其相机是由`唯杰地图`控制的，`vjmap3d`的相机会和`唯杰地图`相机保持同步。因此在这种模式下，不能直接操作`vjmap3d`的相机。同时因为`唯杰地图`暂不支持后期处理，所以在这种模式下，`vjmap3d`的后期处理功能会自动禁用。
:::