準備工作:
????????安裝mars3d依賴:
????????????????npm i?mars3d?
????????????????npm i mars3d-heatmap (熱力圖,需要的話安裝)
????????????????npm i -D?copy-webpack-plugin
????????????????增加mars3d目錄配置,修改vue.config.js中configureWebpack里的內(nèi)容如下:
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內(nèi)部資源加載、多線程等處理時需要用到
new webpack.DefinePlugin({
CESIUM_BASE_URL: JSON.stringify(path.join(config.output.publicPath, cesiumRunPath))
}),
// Cesium相關資源目錄需要拷貝到系統(tǒng)目錄下面(部分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,//不生成調(diào)試文件
parallel: true // 使用多進程并行運行來提高構(gòu)建速度
})
);
}
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>
mapController.js:(地圖操作類)
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()
}
/**
* 創(chuàng)建天地圖層
* @param name 描述
* @auth Roffer
* @date 2022/9/29 15:50
*
*/
initMap() {
// 需要覆蓋config.json中地圖屬性參數(shù)(當前示例框架中自動處理合并)
//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()實現(xiàn)截圖需要將該項設置為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); //支持的參數(shù)請看API文檔:http://mars3d.cn/api/Map.html
this.instance.basemap = 2017 // 藍色底圖
const mapLayer = mars3d.LayerUtil.create({
type: "wmts",
url: mapUrl,
//wmts服務元數(shù)據(jù)中指定的layer值
format: "image/png",
layer: "defaultLayer",
style: "default",
//跨域支持,在使用html2canvas截屏的時候,如果不設置該屬性,會截不到地圖內(nèi)容
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)
//獲取右鍵菜單繪制完成數(shù)據(jù)
this.instance.on(mars3d.EventType.drawCreated, (e) => {
console.log(JSON.stringify(e.graphic));
})
}
/**
* 區(qū)域標記
* @param areaCode 區(qū)域編碼
* @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, // 重要參數(shù),指定材質(zhì)
// materialType: mars3d.MaterialType.Stripe, // 重要參數(shù),指定材質(zhì)
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數(shù)據(jù)
* @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條數(shù)據(jù)
* @param point 經(jīng)緯度,示例:[123.1,22.444]
* @param html 要顯示的html內(nèi)容
* @param popup 自定義詳細信息(String,Array,function)
* @param popupOptions 自定義詳細信息參數(shù)設置(Object)詳情:http://mars3d.cn/api/Popup.html#.StyleOptions
* @param tooltip 自定義鼠標懸浮提示信息(String,Array,function)
* @param tooltipOptions 自定義鼠標懸浮提示信息參數(shù)設置(Object)詳情:http://mars3d.cn/api/Tooltip.html#.StyleOptions
* @param attr 附加自定義屬性(可在點擊時,通過e.target.attr獲?。? * @param click 點擊回調(diào)函數(shù)(返回點擊的對象)
* @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 數(shù)據(jù),
* 格式為:
* [{
* point:[103.111,30.123],html:'<div>xxx</div>',attr:{},click:()=>{}
* },...]
* @auth Roffer
* @date 2022/11/11 14:00
*
*/
batchAddDivLayer(list = []) {
// 創(chuàng)建矢量數(shù)據(jù)圖層
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 參數(shù)對象,包含以下:
* url 請求數(shù)據(jù)的接口地址(url、data二選一)
* dataColumn data字段key(url時指定)
* data 請求數(shù)據(jù)的接口地址(url、data二選一)
* lngColumn 經(jīng)緯字段key
* latColumn 緯緯字段key
* altColumn 高度字段key
* positionIconImg 顯示的圖標圖片
* showGroup 是否顯示聚合分組數(shù)據(jù),默認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
}
// 創(chuàng)建矢量數(shù)據(jù)圖層(業(yè)務數(shù)據(jù)圖層)
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) {
// 飛行完成回調(diào)方法
// graphic.openPopup()
}
})
} else {
// 單擊了聚合的點
const arrEntity = event.pickedObject.id
this.instance.flyTo(arrEntity)
}
}
})
return busineDataLayer
}
/**
* 兩點連線(弧線)
* @param startPoint 起始經(jīng)緯度
* @param endPoint 結(jié)束經(jīng)緯度
* @param attr 顯示的信息對象(object,key、value格式)
* @param popup 點擊時顯示的信息
* @param popupOptions 點擊時顯示的信息參數(shù)設置對象,如可以設置偏移量{offsetX:-10,offsetY:-10},更多參數(shù):http://mars3d.cn/api/Popup.html#.StyleOptions
* @param tooltip hover時顯示的信息
* @param tooltipOptions hover時顯示的信息參數(shù)設置對象,如可以設置偏移量{offsetX:-10,offsetY:-10},更多參數(shù):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,
// 動畫線材質(zhì)
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 經(jīng)緯度數(shù)組 [{lng:123,lat:456},...]
* @auth Roffer
* @date 2022/11/11 14:58
*
*/
addHeatLayer(pointData) {
// 熱力圖 圖層
let heatLayer = new mars3d.layer.HeatLayer({
positions: pointData,
// rectangle: rectangle,
// 以下為熱力圖本身的樣式參數(shù),可參閱api:https://www.patrick-wied.at/static/heatmapjs/docs.html
heatStyle: {
radius: 40,
blur: 0.85
},
// 以下為矩形矢量對象的樣式參數(shù)
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}`
?省市區(qū)地圖json數(shù)據(jù),請移步到https://geojson.cn/?根據(jù)業(yè)務需求下載對應的json數(shù)據(jù)文章來源:http://www.zghlxwxcb.cn/news/detail-616106.html
mars3d官網(wǎng)?文章來源地址http://www.zghlxwxcb.cn/news/detail-616106.html
到了這里,關于vue3 mars3d 天地圖的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!