赞
踩
npm i mars3d
npm i mars3d-heatmap (热力图,需要的话安装)
npm i -D copy-webpack-plugin
增加mars3d目录配置,修改vue.config.js中configureWebpack里的内容如下:
- const CopyWebpackPlugin = require("copy-webpack-plugin");
- const cesiumSourcePath = "node_modules/mars3d-cesium/Build/Cesium/"; // cesium库安装目录
- const cesiumRunPath = "./mars3d-cesium/"; // cesium运行时路径
- const timeStamp = Date.now()
- module.exports = {
- configureWebpack: (config) => {
- const plugins = [
- // 标识cesium资源所在的主目录,cesium内部资源加载、多线程等处理时需要用到
- new webpack.DefinePlugin({
- CESIUM_BASE_URL: JSON.stringify(path.join(config.output.publicPath, cesiumRunPath))
- }),
- // Cesium相关资源目录需要拷贝到系统目录下面(部分CopyWebpackPlugin版本的语法可能没有patterns)
- new CopyWebpackPlugin([
- { from: path.join(cesiumSourcePath, 'Workers'), to: path.join(config.output.path, cesiumRunPath, 'Workers') },
- { from: path.join(cesiumSourcePath, 'Assets'), to: path.join(config.output.path, cesiumRunPath, 'Assets') },
- { from: path.join(cesiumSourcePath, 'ThirdParty'), to: path.join(config.output.path, cesiumRunPath, 'ThirdParty') },
- { from: path.join(cesiumSourcePath, 'Widgets'), to: path.join(config.output.path, cesiumRunPath, 'Widgets') }
- ])
- ]
-
- if (process.env.NODE_ENV === "production") {
- plugins.push(
- new UglifyJSPlugin({
- uglifyOptions: {
- //删除注释
- output: {comments: false},
- warnings: false,
- //删除console 和 debugger 删除警告
- compress: {
- drop_debugger: true,
- drop_console: true
- }
- },
- cache: true, // 启用文件缓存
- sourceMap: false,//不生成调试文件
- parallel: true // 使用多进程并行运行来提高构建速度
- })
- );
- }
- config.plugins = [...config.plugins, ...plugins]
- //给打包的文件名加上时间戳,防止浏览器缓存
-
- config.output.filename = `js/[name].${timeStamp}.js`
- config.output.chunkFilename = `js/[name].${timeStamp}.js`
-
- return {
- module: { unknownContextCritical: false }, // 配置加载的模块类型,cesium时必须配置
- plugins: plugins
- }
- },
- //...其它配置
- }
- <template>
- <div class="r-map-3d">
- <div class="map-box" :id="mapId"></div>
- </div>
- </template>
- <script setup>
- import {defineEmits, defineProps, onMounted, reactive, ref} from 'vue'
- import mars3D from '@/plugins/mars3d/mapController'
-
- const props = defineProps({
- //中心点
- center: {
- type: Array,
- default: () => [0, 0]
- }
- })
- const emit = defineEmits(['onLoad']);
- const mapId = ref(`map_${Date.now()}`)
-
- const data = reactive({
- map: null,
- })
-
- onMounted(() => {
- data.map = new mars3D(mapId.value, props.center)
- emit('onLoad', data.map)
- })
- </script>
- <style scoped lang="scss">
- .r-map-3d {
- width: 100%;
- height: 100%;
-
- .map-box {
- height: 100%;
- width: 100%;
- }
- }
- </style>
- import {mapUrl, mapAk} from "@/config/baseURL";
- //引入cesium基础库
- import "mars3d-cesium/Build/Cesium/Widgets/widgets.css";
- import * as Cesium from "mars3d-cesium";
- //导入mars3d主库
- import "mars3d/dist/mars3d.css";
- import * as mars3d from "mars3d";
- import "mars3d-heatmap"
-
- export default class MapController {
- constructor(mapId) {
- this.ak = mapAk
- this.mapId = mapId
-
- /** 地图实例 */
- this.instance = null
-
- this.initMap()
- }
-
- /**
- * 创建天地图层
- * @param name 描述
- * @auth Roffer
- * @date 2022/9/29 15:50
- *
- */
- initMap() {
- // 需要覆盖config.json中地图属性参数(当前示例框架中自动处理合并)
- //option相关设置:http://mars3d.cn/apidoc.html#Map
- const mapOptions = {
- //scene相关设置:http://mars3d.cn/api/Map.html#.sceneOptions
- scene: {
- center: {lat: 29.068075, lng: 103.966252, alt: 82849.5, heading: 358.9, pitch: -28.4},
- showSkyAtmosphere: false,
- backgroundColor: '#000',
- contextOptions: {
- webgl: {
- //通过canvas.toDataURL()实现截图需要将该项设置为true
- preserveDrawingBuffer: true
- }
- },
- cameraController: {
- //相机最近视距,变焦时相机位置的最小量级(以米为单位),默认为1。该值是相机与地表(含地形)的相对距离。默认1.0
- minimumZoomDistance: 1,
- //相机最远视距,变焦时相机位置的最大值(以米为单位)。该值是相机与地表(含地形)的相对距离。默认50000000.0
- maximumZoomDistance: 200000
- },
- globe: {
- show: true,//是否显示地球
- }
- },
- // control: {
- // locationBar: {
- // fps: true,//是否显示实时FPS帧率
- // navigationHelpButton: true
- // }
- // },
- }
-
- this.instance = new mars3d.Map(this.mapId, mapOptions); //支持的参数请看API文档:http://mars3d.cn/api/Map.html
- this.instance.basemap = 2017 // 蓝色底图
- const mapLayer = mars3d.LayerUtil.create({
- type: "wmts",
- url: mapUrl,
- //wmts服务元数据中指定的layer值
- format: "image/png",
- layer: "defaultLayer",
- style: "default",
- //跨域支持,在使用html2canvas截屏的时候,如果不设置该属性,会截不到地图内容
- crossOrigin: 'Anonymous',
- tileMatrixSetID: "GetTileMatrix",
- minimumLevel: 3,
- maximumLevel: 17,
- minimumTerrainLevel: 1,
- maximumTerrainLevel: 25,
- zIndex: 2,
- crs: "EPSG4490",
- chinaCRS: "WGS84",
- tileWidth: 256,
- tileHeight: 256,
- name: "影像",
- extent: {
- xmin: 96.8064823,
- ymin: 25.68096106,
- xmax: 109.1252279,
- ymax: 34.75215408
- }
- })
-
- this.instance.addLayer(mapLayer)
-
- //获取右键菜单绘制完成数据
- this.instance.on(mars3d.EventType.drawCreated, (e) => {
- console.log(JSON.stringify(e.graphic));
- })
- }
-
- /**
- * 区域标记
- * @param areaCode 区域编码
- * @param filter 透明度,默认不透明,值范围:0~1
- * @param popupState 点击地图popup显隐
- * @auth Roffer
- * @date 2022/11/10 19:03
- *
- */
- addAreaLayer(areaCode = '510100000000', filter = 1, styleCback,popupState=true) {
- const geoJsonLayer = new mars3d.layer.GeoJsonLayer({
- name: "成都市",
- url: `/json/5101/${areaCode}.json`,
- allowDrillPick: true,
- symbol: {
- type: "polygon",
- styleOptions: {
- materialType: mars3d.MaterialType.PolyGradient, // 重要参数,指定材质
- // materialType: mars3d.MaterialType.Stripe, // 重要参数,指定材质
- materialOptions: {
- color: "#3388cc",
- opacity: 0.7,
- alphaPower: 1.3
- },
- // 面中心点,显示文字的配置
- label: {
- text: "{name}", // 对应的属性名称
- opacity: 1,
- font_size: 18,
- color: "#fff",
- font_family: "宋体",
- outline: false,
- scaleByDistance: true,
- scaleByDistance_far: 20000000,
- scaleByDistance_farValue: 0.1,
- scaleByDistance_near: 1000,
- scaleByDistance_nearValue: 1
- }
- },
- callback: styleCback ? styleCback : function (attr, styleOpt) {
- const randomHeight = (attr.childrenNum || 1) * 600 // 测试的高度
- return {
- materialOptions: {
- color: attr.fill,
- alphaPower: filter
- // color: getColor()
- },
- height: 20,
- diffHeight: randomHeight
- }
- }
- },
- popup:popupState ? "{name}" : false
- })
- this.instance.addLayer(geoJsonLayer)
-
- const arrColor = ["rgb(15,176,255)", "rgb(18,76,154)", "#40C4E4", "#42B2BE", "rgb(51,176,204)", "#8CB7E5", "rgb(0,244,188)", "#139FF0"]
-
- let index = 0
-
- function getColor() {
- return arrColor[++index % arrColor.length]
- }
-
- return geoJsonLayer
- }
-
- /**
- * 添加自定义多边形
- * @param geoJson geoJson数据
- * @param color 多边形颜色
- * @auth Roffer
- * @date 2022/12/8 11:01
- *
- */
- addCustomLayer({pointList, color, text, popup, popupOptions, tooltip, tooltipOptions}) {
- const graphicLayer = this.genGraphicLayer()
- const graphic = new mars3d.graphic.PolygonEntity({
- positions: pointList,
- style: {
- color,
- opacity: 0.5,
- outline: false,
- outlineWidth: 3,
- outlineColor: "#ffffff",
- highlight: {
- opacity: 0.8
- },
- label: {
- show: false,
- text,
- font_size: 12,
- color: "#ffffff",
- distanceDisplayCondition: true,
- distanceDisplayCondition_far: 500000,
- distanceDisplayCondition_near: 0
- }
- },
- popup,
- popupOptions,
- tooltip,
- tooltipOptions
- })
-
- graphicLayer.addGraphic(graphic)
- this.instance.addLayer(graphicLayer)
-
- return graphicLayer
- }
-
- /**
- * 添加一个自定义标注层
- * @auth Roffer
- * @date 2022/11/11 14:19
- *
- */
- genGraphicLayer() {
- let graphicLayer = new mars3d.layer.GraphicLayer()
- this.instance.addLayer(graphicLayer)
- return graphicLayer
- }
-
- /**
- * 添加自定义html标记点,适用于小于100条数据
- * @param point 经纬度,示例:[123.1,22.444]
- * @param html 要显示的html内容
- * @param popup 自定义详细信息(String,Array,function)
- * @param popupOptions 自定义详细信息参数设置(Object)详情:http://mars3d.cn/api/Popup.html#.StyleOptions
- * @param tooltip 自定义鼠标悬浮提示信息(String,Array,function)
- * @param tooltipOptions 自定义鼠标悬浮提示信息参数设置(Object)详情:http://mars3d.cn/api/Tooltip.html#.StyleOptions
- * @param attr 附加自定义属性(可在点击时,通过e.target.attr获取)
- * @param click 点击回调函数(返回点击的对象)
- * @param style Object,覆盖style对象中的属性值
- * @auth Roffer
- * @date 2022/10/22 14:55
- *
- */
- addDivLayer({point, html, popup, popupOptions, tooltip, tooltipOptions, attr, click, style}, graphicLayer) {
- const graphic = new mars3d.graphic.DivGraphic({
- position: new mars3d.LngLatPoint(point[0], point[1], 915),
- style: {
- html,
- horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
- verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
- clampToGround: true,
- offsetX: -20,
- offsetY: -30,
- ...style
- },
- attr,
- popup,
- popupOptions,
- tooltip,
- tooltipOptions,
- eventParent: false,//不冒泡事件
- })
- graphicLayer.addGraphic(graphic)
-
- click && graphic.on(mars3d.EventType.click, click)
-
- return graphicLayer
- }
-
- /**
- * 批量添加html标标注
- * @param list 数据,
- * 格式为:
- * [{
- * point:[103.111,30.123],html:'<div>xxx</div>',attr:{},click:()=>{}
- * },...]
- * @auth Roffer
- * @date 2022/11/11 14:00
- *
- */
- batchAddDivLayer(list = []) {
- // 创建矢量数据图层
- let graphicLayer = this.genGraphicLayer()
-
- list.forEach(item => {
- this.addDivLayer(item, graphicLayer)
- })
-
- return graphicLayer
- }
-
- /**
- * 获取当前屏幕边界坐标
- * @auth Roffer
- * @date 2022/11/21 15:37
- *
- */
- getScreenXY() {
- //屏幕边界坐标
- let info = this.instance.viewer.camera.computeViewRectangle()
- info.east = Cesium.Math.toDegrees(info.east)
- info.north = Cesium.Math.toDegrees(info.north)
- info.south = Cesium.Math.toDegrees(info.south)
- info.west = Cesium.Math.toDegrees(info.west)
- // east 104.58916517174933
- // north 30.8081617249502
- // south 30.48271217718593
- // west 103.95342383654778
- return info
- }
-
- /**
- * 添加自定义标记点
- * @param data 参数对象,包含以下:
- * url 请求数据的接口地址(url、data二选一)
- * dataColumn data字段key(url时指定)
- * data 请求数据的接口地址(url、data二选一)
- * lngColumn 经纬字段key
- * latColumn 纬纬字段key
- * altColumn 高度字段key
- * positionIconImg 显示的图标图片
- * showGroup 是否显示聚合分组数据,默认true显示
- * text 显示的名称字段key
- * @param popup 详细信息对象
- * key:对象中的key值
- * item[key]:显示的名称 eg:{name:'名称'}
- * @auth Roffer
- * @date 2022/10/22 14:55
- *
- */
- addBusineDataLayer(data, popup) {
- let option = {
- showGroup: true,
- ...data
- }
- // 创建矢量数据图层(业务数据图层)
- let busineDataLayer = new mars3d.layer.BusineDataLayer({
- ...option,
- symbol: {
- type: "billboard", // 对应是 mars3d.graphic.BillboardEntity
- styleOptions: {
- image: option.positionIconImg,
- horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
- verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
- scaleByDistance: new Cesium.NearFarScalar(1000, 0.7, 5000000, 0.3),
- visibleDepth: false,
- // label: {
- // text: `{${data.text || 'text'}}`,
- // font_size: 13,
- // color: Cesium.Color.AZURE,
- // outline: true,
- // outlineColor: Cesium.Color.BLACK,
- // outlineWidth: 2,
- // horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
- // verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
- // pixelOffset: new Cesium.Cartesian2(10, 0), // 偏移量
- // distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0.0, 80000)
- // }
- }
- },
- // 点的聚合配置
- clustering: {
- enabled: option.showGroup,
- pixelRange: 20,
- clampToGround: false,
- opacity: 1,
- // getImage: function (count) { //getImage是完全自定义方式
- // let colorIn
- // if (count < 10) {
- // colorIn = 'rgba(110, 204, 57, 0.6)'
- // } else if (count < 100) {
- // colorIn = 'rgba(240, 194, 12, 0.6)'
- // } else {
- // colorIn = 'rgba(241, 128, 23, 0.6)'
- // }
- // return mars3d.Util.getCircleImage(count, {
- // color: colorIn,
- // radius: 30,
- // })
- // },
- }
- })
-
- this.instance.addLayer(busineDataLayer)
-
- //包含详情
- if (popup) {
- //详细信息弹窗
- busineDataLayer.bindPopup(function (event) {
- const item = event.graphic?.attr
- if (!item) {
- return false
- }
- const tabData = [
- `<table style="width: auto;">
- <tr><th scope="col" colspan="2" style="text-align:center;font-size:15px;">${item[option.text]}</th></tr>`
- ]
- for (let key in popup) {
- tabData.push(`<tr>`)
- tabData.push(`<td>${popup[key]}</td><td>${item[key]}</td>`)
- tabData.push(`</tr>`)
- }
- tabData.push('</table>')
- return tabData.join('')
- })
-
- busineDataLayer.bindTooltip(function (event) {
- const item = event.graphic?.attr
- if (!item) {
- return false
- }
- const tabData = [
- `<table style="width: auto;">
- <tr><th scope="col" colspan="2" style="text-align:center;font-size:15px;">${item[option.text]}</th></tr>`
- ]
- for (let key in popup) {
- tabData.push(`<tr>`)
- tabData.push(`<td>${popup[key]}</td><td>${item[key]}</td>`)
- tabData.push(`</tr>`)
- }
- tabData.push('</table>')
- return tabData.join('')
- })
- }
-
- // 单击事件
- busineDataLayer.on(mars3d.EventType.click, (event) => {
- if (this.instance.camera.positionCartographic.height > 1000) {
- const graphic = event.graphic
- if (graphic) {
- // 单击了具体的点对象
- // graphic.closePopup()
-
- const position = graphic.positionShow
- this.instance.flyToPoint(position, {
- radius: 1000, // 距离目标点的距离
- duration: 3,
- complete: function (e) {
- // 飞行完成回调方法
- // graphic.openPopup()
- }
- })
- } else {
- // 单击了聚合的点
- const arrEntity = event.pickedObject.id
- this.instance.flyTo(arrEntity)
- }
- }
- })
-
- return busineDataLayer
- }
-
- /**
- * 两点连线(弧线)
- * @param startPoint 起始经纬度
- * @param endPoint 结束经纬度
- * @param attr 显示的信息对象(object,key、value格式)
- * @param popup 点击时显示的信息
- * @param popupOptions 点击时显示的信息参数设置对象,如可以设置偏移量{offsetX:-10,offsetY:-10},更多参数:http://mars3d.cn/api/Popup.html#.StyleOptions
- * @param tooltip hover时显示的信息
- * @param tooltipOptions hover时显示的信息参数设置对象,如可以设置偏移量{offsetX:-10,offsetY:-10},更多参数:http://mars3d.cn/api/Tooltip.html#.StyleOptions
- * @param lineColor 线条的颜色(默认:#1a9850)
- * @auth Roffer
- * @date 2022/12/3 11:04
- *
- */
- addArc({startPoint, endPoint, attr, popup, popupOptions, tooltip, tooltipOptions, lineColor}, graphicLayer) {
- graphicLayer = graphicLayer || this.genGraphicLayer()
- const start = Cesium.Cartesian3.fromDegrees(...startPoint, 42.31)
- const end = Cesium.Cartesian3.fromDegrees(...endPoint, 37.53)
- const positions = mars3d.PolyUtil.getLinkedPointList(start, end, 20000, 50) // 计算曲线点
-
- const graphic = new mars3d.graphic.PolylineEntity({
- positions: positions,
- style: {
- width: 10,
- // 动画线材质
- materialType: mars3d.MaterialType.LineFlow,
- materialOptions: {
- image: require('@/assets/img/map_icon/line-arrow-blue.png'),
- color: lineColor || '#1a9850',
- mixt: false,
- speed: 20,
- repeat: new Cesium.Cartesian2(5, 1)
- }
- },
- attr,
- popup,
- popupOptions,
- tooltip,
- tooltipOptions
- })
- graphicLayer.addGraphic(graphic)
-
- return graphicLayer
- }
-
- /**
- * 热力图
- * @param pointData 经纬度数组 [{lng:123,lat:456},...]
- * @auth Roffer
- * @date 2022/11/11 14:58
- *
- */
- addHeatLayer(pointData) {
- // 热力图 图层
- let heatLayer = new mars3d.layer.HeatLayer({
- positions: pointData,
- // rectangle: rectangle,
- // 以下为热力图本身的样式参数,可参阅api:https://www.patrick-wied.at/static/heatmapjs/docs.html
- heatStyle: {
- radius: 40,
- blur: 0.85
- },
- // 以下为矩形矢量对象的样式参数
- style: {
- arc: true, // 是否为曲面
- height: 100.0,
- opacity: 0.6,
- // classificationType: Cesium.ClassificationType.CESIUM_3D_TILE,
- // clampToGround: true
- }
- })
-
- this.instance.addLayer(heatLayer)
-
- return heatLayer
- }
-
- /**
- * 删除layer
- * @param layer layer对象
- * @auth Roffer
- * @date 2022/11/11 14:26
- *
- */
- removeLayer(layer) {
- this.instance.removeLayer(layer)
- }
- }
使用:
<r-map-3d @onLoad="mapLoad"/>
- <script setup>
- let map = null//地图实例
- let areaLayer = null//图层的操作最好不要定义在vue3的响应式对象中,否则会引起页面卡顿
- /** 地图加载完成 */
- const mapLoad = (instance) => {
- map = instance
- areaLayer = map.addAreaLayer('510100000000')
- }
- </script>
最后附上天地图mapUrl地址:
- export const mapAk = 'xxxx'//请自行去官方申请
- //浅色底图
- // export const mapUrl = `http://www.scgis.net/services/newtianditudlg/WMTS?ak=${mapAk}`
- //暗色底图
- export const mapUrl = `http://www.scgis.net/services/tdtdarkmap/WMTS?ak=${mapAk}`
省市区地图json数据,请移步到https://geojson.cn/ 根据业务需求下载对应的json数据
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。