123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447 |
- import { LineLayer, PointLayer, PolygonLayer, Popup, RasterLayer, Scene } from '@antv/l7'
- import type { ICameraOptions, ISourceCFG, Point } from '@antv/l7-core'
- import { Mapbox } from '@antv/l7-maps'
- import { formatStringByTemplate } from '@/utils/string'
- import bus from '@/utils/bus'
- import boundary from '@/assets/json/zmw.json'
- import boundaryTri from '@/assets/json/tri.json'
- import thData from '@/assets/json/thly-all.json'
- import lakeData from '@/assets/json/lake.json'
- import thly from '@/assets/images/thly-all.png'
- export let scene: Scene
- // 加载状态
- export let loadedStatus = false
- export let imageMap = new Map()
- function loadImage(images: any[]) {
- images.forEach((item: any) => {
- if (!imageMap.has(item.name)) {
- imageMap.set(item.name, item.src)
- scene.addImage(item.name, item.src)
- }
- })
- }
- /**
- * 初始化地图
- */
- export function init(config: any) {
- loadedStatus = false
- imageMap = new Map()
- scene = new Scene({
- id: 'mapDiv',
- map: new Mapbox({
- center: [120.83, 31.05],
- zoom: 9,
- maxZoom: 10,
- minZoom: 5,
- pitch: 90, // 地图倾斜度
- style: 'blank'
- })
- })
- scene.on('loaded', () => {
- loadedStatus = true
- loadBaseLayer()
- // 加载图片
- if (config && config.images && config.images.length > 0) {
- loadImage(config.images)
- }
- setTimeout(function() {
- const map = scene.map
- const startZoom = 6.5
- const endZoom = 9
- const duration = 6000 // 动画持续时间,单位毫秒
- const interval = 100 // 每次更新间隔,单位毫秒
- const step = (endZoom - startZoom) * (interval / duration)
- const zoomAnimation = setInterval(() => {
- const currentZoom = map.getZoom()
- if (currentZoom <= startZoom) {
- clearInterval(zoomAnimation)
- map.setZoom(startZoom)
- } else {
- const newZoom = currentZoom - step
- map.setZoom(newZoom)
- }
- }, interval)
- }, 9000)
- })
- // 地图平移时触发事件
- scene.on('mapmove', () => {
- console.log('中心点:', scene.getCenter().lng, scene.getCenter().lat, scene.getZoom(), scene.getPitch())
- })
- }
- /**
- * 加载底图
- */
- function loadBaseLayer() {
- // //添加太湖流域地图
- const thMap = new PolygonLayer({})
- .source(thData) //使用的数据为下载到本地的json数据
- .shape('extrude') //用于绘制几何体
- .size(30000)
- .active({
- color: 'rgba(0, 0, 0, .1)'
- })
- .style({
- mapTexture: thly,
- heightfixed: true, //抬升高度是否随 zoom 变化
- raisingHeight: 1000, //抬升高度
- sourceColor: '#67bdec', //抬高高度的颜色
- targetColor: '#67bdec',
- opacity: 0.5
- })
- const triLayer = new LineLayer({ zIndex: 2 })
- .source(boundaryTri)
- .color('rgb(241,152,49)')
- .size(2)
- .style({
- raisingHeight: 50000
- })
- scene.addLayer(triLayer)
- const layerBoundary = new LineLayer({ zIndex: 2 })
- .source(boundary)
- .size(50)
- .shape('wall')
- .style({
- opacity: 1,
- sourceColor: '#0DCCFF',
- targetColor: 'rbga(255,255,255, 0)',
- raisingHeight: 50000
- })
- scene.addLayer(layerBoundary)
- scene.addLayer(thMap)
- setMark(lakeData)
- }
- /**
- * 设置地图视角
- * @param center 中心点
- * @param zoom 层级
- * @param pitch 倾斜角度
- * @param padding
- */
- export function setCenter(center: Point, zoom: number, pitch = 0, padding = {}) {
- if (center && zoom) {
- scene.setZoomAndCenter(zoom, center)
- } else if (center) {
- scene.setCenter(center, padding as ICameraOptions)
- } else if (zoom) {
- scene.setZoom(zoom)
- }
- scene.setPitch(pitch)
- }
- export function loadMap(option: any) {
- const loadMapFun = (option: any) => {
- if (option.view) {
- setCenter(option.view.center, option.view.zoom)
- }
- if (option.layers) {
- // 清空图层
- scene.removeAllLayer()
- // 加载地图
- loadBaseLayer()
- option.layers.forEach((layer: any) => {
- switch (layer.type) {
- case 'point':
- createPointByCongfig(layer)
- break
- // case 'line':
- // createLineByCongfig(layer, mapJson)
- // break
- // case 'polygon':
- // createPolygonByCongfig(layer, mapJson)
- // break
- // case 'mark':
- // setMark(config)
- // break
- }
- })
- }
- }
- function checkStatus(option: any) {
- if (loadedStatus) {
- loadMapFun(option)
- } else {
- setTimeout(() => checkStatus(option), 1000)
- }
- }
- checkStatus(option)
- }
- function createPointByCongfig(config: any) {
- console.log('config', config, imageMap)
- const layer = new PointLayer({})
- .source(config.data, config.dataOptions)
- .size(config.size)
- .active(config.emphasis.show).shape('triangleColumn')
- .color('#3ae33d')
- // setLayerShape(layer, config.shape)
- // 颜色配置
- // setLayerColor(layer, config.color);
- scene.addLayer(layer)
- setMark(config)
- // setPopup(layer, config);
- // 点击事件
- layer.on('click', (e: any) => {
- let row = e.feature.properties || e.feature
- bus.emit('point_click', { data: row, e })
- })
- }
- function createLakePoint(config: any) {
- const layer = new PointLayer({})
- .source(config.data, config.dataOptions)
- .size(config.size)
- .active(config.emphasis.show)
- setLayerShape(layer, config.shape)
- // 颜色配置
- // setLayerColor(layer, config.color);
- scene.addLayer(layer)
- setMark(config)
- // setPopup(layer, config);
- // 点击事件
- layer.on('click', (e: any) => {
- let row = e.feature.properties || e.feature
- bus.emit('point_click', { data: row, e })
- })
- }
- function getValueByConditions(data: any, conditions: any, field: any) {
- let condition
- for (const item of conditions) {
- if (compareByConditions(data, item)) {
- condition = item
- break
- }
- }
- if (!condition) {
- return null
- }
- if (field === 'color') {
- return condition[field]
- }
- if (condition[field] !== 'image') {
- return condition[field]
- }
- if (condition[field] === 'image') {
- return condition.imageName
- }
- return null
- }
- function compareByConditions(data: any, condition: any) {
- switch (condition.cond) {
- case 'lt':
- if (data < condition.value) {
- return true
- }
- break
- case 'lte':
- if (data <= condition.value) {
- return true
- }
- break
- case 'eq':
- if (data == condition.value) {
- return true
- }
- break
- case 'gt':
- if (data > condition.value) {
- return true
- }
- break
- case 'gte':
- if (data >= condition.value) {
- return true
- }
- break
- case 'ne':
- if (data != condition.value) {
- return true
- }
- break
- }
- return false
- }
- /**
- * 图层数据配置
- * @param dataType
- * @returns {{parser: {x: string, y: string, type: string}}|null}
- */
- function getSourceOptions(dataType: any) {
- switch (dataType) {
- case 'geojson':
- return null
- case 'list':
- return {
- parser: {
- type: 'json',
- x: '经度',
- y: '纬度'
- }
- }
- default:
- }
- }
- /**
- * 图层形状配置
- * @param layer
- * @param config
- */
- function setLayerShape(layer: any, config: any) {
- if (config.isConstant) {
- layer.shape(config.value)
- } else {
- layer.shape(config.field, config.value)
- }
- }
- /**
- * 图层颜色配置
- * @param layer
- * @param config
- */
- function setLayerColor(layer: any, config: any) {
- if (config.isConstant) {
- layer.color(config.value)
- } else {
- const field = config.field
- const conditions = config.conditions
- layer.color(field, (field: any) => {
- return getValueByConditions(field, conditions, 'color')
- })
- }
- }
- export function setMark(config: any) {
- if (!config.label.show) {
- return
- }
- // 标注
- const markLayer = new PointLayer({})
- .source(config.data, config.dataOptions)
- .shape(config.label.field, 'text')
- .size(16)
- .color(config.label.color || '#000')
- .style({
- textAnchor: config.label.position || 'center', // 文本相对锚点的位置 center|left|right|top|bottom|top-left
- textOffset: [0, 40], // 文本相对锚点的偏移量 [水平, 垂直]
- spacing: 2, // 字符间距
- padding: [1, 1], // 文本包围盒 padding [水平,垂直],影响碰撞检测结果,避免相邻文本靠的太近
- stroke: config.label.stroke || '#ffffff', // 描边颜色
- strokeWidth: 2, // 描边宽度
- strokeOpacity: 1.0
- })
- scene.addLayer(markLayer)
- }
- function setPopup(layer: any, config: any) {
- if (!config.enabled) {
- return
- }
- layer.on(config.trigger, (e: any) => {
- let properties = e.feature.properties || e.feature
- const content = formatStringByTemplate(properties, config.content)
- // offsets: [0, 0], closeButton: false,
- const popup = new Popup({})
- .setLnglat(e.lngLat)
- .setHTML(content)
- scene.addPopup(popup)
- })
- }
- /**
- * 创建线图层
- * @param config 配置
- * @param dataType 图层数据类型
- * @param mapData 图层数据
- */
- function createLineByCongfig(config: any, dataType: any, mapData: any) {
- const sourceOptions = getSourceOptions(dataType) as ISourceCFG
- const layer = new LineLayer({})
- .source(mapData, sourceOptions)
- .size(1)
- .style({
- lineType: 'dash',
- dashArray: [2, 2]
- })
- .active(config.active)
- scene.addLayer(layer)
- setMark(config)
- setPopup(layer, config.popup)
- }
- /**
- * 创建面图层
- * @param config 配置
- * @param dataType 图层数据类型
- * @param mapData 图层数据
- */
- function createPolygonByCongfig(config: any, dataType: any, mapData: any) {
- const sourceOptions = getSourceOptions(dataType) as ISourceCFG
- const layer = new PolygonLayer({})
- .source(mapData, sourceOptions)
- .shape('fill')
- .active(config.active)
- // 颜色配置
- setLayerColor(layer, config.color)
- scene.addLayer(layer)
- setMark(config)
- setPopup(layer, config.popup)
- }
- export function getLegendData(config: any) {
- const layers = config.layers
- const layerLegend = layers.reduce((acc: any, item: any) => {
- if (item.legend && item.legend.data) {
- return acc.concat(item.legend.data)
- } else {
- return acc
- }
- }, [])
- // return layerLegend.map((item: any) => {
- // const data = {label: item.text}
- // if (item.shape === 'image') {
- // data.imgType = 'img'
- // data.src = item.imgSrc
- // } else {
- // data.imgType = 'svg'
- // data.src = item.shape
- // data.imgStyle = {fill: item.color}
- // }
- // return data
- // })
- return null
- }
|