AntVL7-上手流程

简介

基于 WebGL 的开源大规模地理空间数据可化视分析开发框架

L7 中的 L 代表 Location,7 代表世界七大洲。专注数据可视化表达,通过颜色、大小、纹理,方向,体积等视觉变量设置实现从数据到信息清晰,有效的表达。

L7 能够满足常见的地图图表,BI 系统的可视化分析、以及 GIS,交通,电力,国土,农业,城市等领域的空间信息管理,分析等应用系统开发需求。

教程

特点

  • 数据驱动可视化展示
    数据驱动,灵活数据映射,从数到形,支持丰富的地图可视化类型,更好洞察数据。
  • 2D,3D 一体化的海量数据高性能渲染
    海量空间数据实时,可交互,动态渲染,
  • 简单灵活的数据接入
    支持 CSV,JSON,GeoJSON 等数据格式接入,可以根据需求自定义数据格式,无需复杂的空间数据转换。
  • 多地图底图支持,支持离线内网部署
    屏蔽不同底图之间的差异,用户只需要关注数据层表达,交互。高德地图国内合法合规的地理底图,Mapbox 满足国际化业务需求。

快速上手

安装

  1. npm引入
// 安装L7 依赖 
npm install --save @antv/l7 
// 安装第三方底图依赖
npm install @antv/l7-maps
// 地理绘制库
npm install @antv/l7-draw

使用:

<script src="./node_modules/@antv/l7/dist/l7.js"></script>

const scene = new L7.Scene({
  id: 'map',
  map: new L7.GaodeMap({
    style: 'dark',
    center: [110.770672, 34.159869],
    pitch: 45,
  }),
});

模块内:

import { Scene } from '@antv/l7';
import { GaodeMap } from '@antv/l7-maps';
  1. cnd引入
<!-- 引入最新版的L7 -->
<script src="https://unpkg.com/@antv/l7"></script>
<!-- 指定版本号引入L7 -->
<script src="https://unpkg.com/@antv/l7@2.0.11"></script>
<!-- 地理绘制库 -->
<script src="https://unpkg.com/@antv/l7-draw@3.0.28/dist/l7-draw.min.js"></script>
const { Scene, GaodeMap } = L7
const scene = new Scene({
  id: 'map',
  map: new GaodeMap({
    style: 'dark', // 样式
    center: [104.288144, 31.239692], // 中心坐标点
    zoom: 4.4, // 缩放比例
  }),
})

初始化地图

  1. 引入L7相关的库文件
  2. 准备地图容器
  3. 创建场景实例
    <!-- 1. 引入L7 -->
    <script src="https://unpkg.com/@antv/l7"></script>

  <body>
    <!-- 2. 准备地图容器 -->
    <div id="map"></div>

    <script>
      // 3. 初始化对象
      const { Scene, GaodeMap } = L7
      const scene = new Scene({
        id: 'map',
        map: new GaodeMap({
          style: 'dark', // 样式
          center: [104.288144, 31.239692], // 中心坐标点
          zoom: 4.4, // 缩放比例
        }),
      })
    </script>
  </body>
  • 场景Scene: 包含地图, 控件, 组件, 加载资源的全局对象. 通过scene可以获取到操作地图需要的所有内容
  • 地图: 支持MapboxGaode地图

添加图层

  1. 面图层
      const { Scene, GaodeMap, PolygonLayer } = L7

      const scene = new Scene({
        id: 'map',
        map: new GaodeMap({
          style: 'normal',
          center: [114.3, 30.5],
          zoom: 5,
          // token: '',
        }),
      })
      // 通过fetch获取数据
      fetch('./data/province.json')
        .then((res) => res.json())
        .then((data) => {
          // 创建面图层
          const chinaPolygonLayer = new PolygonLayer({
            autoFit: true,
          })
            .source(data)
            .color('name', [
              'rgb(239,243,255)',
              'rgb(189,215,231)',
              'rgb(107,174,214)',
              'rgb(49,130,189)',
              'rgb(8,81,156)',
            ])

          // 添加图层
          scene.addLayer(chinaPolygonLayer)
        })
  1. 线图层
      // 3. 初始化对象
      const { Scene, GaodeMap, PolygonLayer, LineLayer } = L7
      const scene = new Scene({
        id: 'map',
        map: new GaodeMap({
          style: 'dark', // 样式
          center: [104.288144, 31.239692], // 中心坐标点
          zoom: 4.4, // 缩放比较
        }),
      })

      scene.on('loaded', () => {
        fetch('./data/province.json')
          .then((res) => res.json())
          .then((data) => {
            const chinaPolygonLayer = new PolygonLayer({
              autoFit: true,
            })
              .source(data)
              .color('name', [
                'rgb(239,243,255)',
                'rgb(189,215,231)',
                'rgb(107,174,214)',
                'rgb(49,130,189)',
                'rgb(8,81,156)',
              ])
            scene.addLayer(chinaPolygonLayer)
            //  设置省边界线图层
            const layer2 = new LineLayer({
              zIndex: 2,
            })
              .source(data)
              .color('rgb(93,112,146)')
              .size(0.6)
              .style({
                opacity: 1,
              })
            scene.addLayer(layer2)
          })
      })
  1. 标注文本
fetch(
    "https://gw.alipayobjects.com/os/bmw-prod/c4a6aa9d-8923-4193-a695-455fd8f6638c.json" //  标注数据
  )
    .then(res => res.json())
    .then(data => {
      const labelLayer = new PointLayer({
        zIndex: 5
      })
        .source(data, {
          parser: {
            type: "json",
            coordinates: "center"
          }
        })
        .color("#fff")
        .shape("name", "text")
        .size(12)
        .style({
          opacity: 1,
          stroke: "#fff",
          strokeWidth: 0,
          padding: [5, 5],
          textAllowOverlap: false
        });

      scene.addLayer(labelLayer);
    });

L7组件

L7 中的 Component 主要包含以下三种类型:

  • Control 控件类型:指的是悬停在地图四周,可以对地图以及图层等元素进行信息呈现或交互的组件。
  • Popup 气泡类型:用于在地图上指定经纬度位置展示气泡,气泡内容完全交由开发者自定义。
  • Marker 类型:与 Popup 相似,不同的是 Marker 展示的内容不会在气泡内展示,而是完全交由开发者自定义。

Control

  1. Logo
      const { Scene, GaodeMap, Logo } = L7
      // 3. 初始化对象
      const scene = new Scene({
        id: 'map',
        map: new GaodeMap({
          style: 'dark', // 样式
          center: [104.288144, 31.239692], // 中心坐标点
          zoom: 4.4, // 缩放比较
          logo: true,
        }),
        logoVisible: false, // 关闭L7 默认logo
      })
      // 4. 添加组件
      // logo组件
      scene.on('loaded', () => {
        const logo = new Logo({
          // 图片 url
          img: 'https://img.gejiba.com/images/dfdb6db1623eb881e724f58d9a366af8.png',
          // 跳转地址
          href: 'http://www.x-zd.com/',
        })
        scene.addControl(logo)
      })
  1. Zoom
const { Zoom } = L7;
scene.on('loaded', () => {
  const zoom = new Zoom({
    position: 'bottomright',
    zoomInTitle: '放大',
    zoomOutTitle: '缩小',
  });
  scene.addControl(zoom);
});
  1. Scale
const { Scale } = L7;
scene.on('loaded', () => {
  const scale = new Scale({
    position: 'bottomleft',
    metric: true,
    imperial: false,
    maxWidth: 100,
  })
  scene.addControl(scale)
})
  1. Fullscreen
const { Fullscreen } = L7
scene.on('loaded', () => {
    const fullscreen = new Fullscreen({
          btnText: '全屏',
          exitBtnText: '退出全屏',
    });
    scene.addControl(fullscreen)
});
  1. ExportImage
const { ExportImage } = L7
scene.on('loaded', () => {
  const exportImage = new ExportImage({
    onExport: (base64) => {
      alert(base64)
    },
  })
  scene.addControl(exportImage)
})
  1. 图层切换
const { PointLayer, LayerSwitch } = L7
scene.on('loaded', () => {
  const layer = new PointLayer({
    name: '点图层',
  })
  layer
    .source({
      type: 'FeatureCollection',
      features: [
        {
          type: 'Feature',
          geometry: {
            type: 'Point',
            coordinates: [114.3, 30.5],
          },
        },
      ],
    })
    .shape('circle')
    .color('#333')
    .style({
      opacity: 0.5,
      strokeWidth: 1,
    })
    .size(20)
    .active(true)
  scene.addLayer(layer)

  const layerSwitch = new LayerSwitch({
    layers: [layer],
  })
  scene.addControl(layerSwitch)
})
  1. MouseLocation
const { MouseLocation } = L7
scene.on('loaded', () => {
  const mouseLocation = new MouseLocation({
    transform: (position) => {
      return position
    },
  })
  scene.addControl(mouseLocation)
})
  1. 地图主题
const { MapTheme } = L7;
scene.on('loaded', () => {
      const mapTheme = new MapTheme({});
      scene.addControl(mapTheme);
});

Marker

  1. 基本示例
    <div id="map"></div>
    <script>
      const { Scene, GaodeMap, Marker } = L7

      const scene = new Scene({
        id: 'map',
        map: new GaodeMap({
          style: 'normal',
          center: [114.3, 30.5],
          zoom: 5,
        }),
      })

      scene.on('loaded', () => {
        const marker = new Marker()
        // console.log(marker)
        marker.setLnglat([114.3, 30.5])

        scene.addMarker(marker)
      })
    </script>
  </body>
</html>
  1. marker结合popup
    <script>
      const { Scene, GaodeMap, Marker, Popup } = L7

      const scene = new Scene({
        id: 'map',
        map: new GaodeMap({
          style: 'normal',
          center: [114.3, 30.5],
          zoom: 5,
        }),
      })

      scene.on('loaded', () => {
        const marker = new Marker()
        marker.setLnglat([114.3, 30.5])

        const popup = new Popup({
          offsets: [0, 50],
        }).setText('武汉')
        marker.setPopup(popup)

        scene.addMarker(marker)
      })
    </script>
  1. 自定义marker
#marker {
  text-align: center;
  background-color: #652e8092;
  line-height: 50px;
  color: #fff;
  width: 50px;
  height: 50px;
  border-radius: 50%;
  cursor: pointer;
}
// 创建DOM元素
const element = document.createElement('div')
element.id = 'marker'
// 基于DOM元素创建Marker标注
const marker = new Marker({
  element: element,
})
marker.setLnglat([114.3, 30.5])
scene.addMarker(marker)
  1. Marker图层
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      .marker {
        text-align: center;
        background-color: #652e8092;
        line-height: 50px;
        color: #fff;
        width: 50px;
        height: 50px;
        border-radius: 50%;
        cursor: pointer;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>

    <script>
      const { Scene, GaodeMap, Marker, MarkerLayer } = L7

      const scene = new Scene({
        id: 'map',
        map: new GaodeMap({
          style: 'normal',
          center: [114.3, 30.5],
          zoom: 5,
        }),
      })

      // 定义数据
      const data = [
        {
          lng: 114.3,
          lat: 30.5,
          name: '武汉',
        },
        {
          lng: 112.59,
          lat: 28.12,
          name: '长沙',
        },
      ]
      scene.on('loaded', () => {
        // 创建标注图层
        const markerLayer = new MarkerLayer({})
        for (const city of data) {
          const { lng, lat, name } = city
          // 创建标注对象
          const element = document.createElement('div')
          element.className = 'marker'
          element.innerHTML = name

          const marker = new Marker({
            element: element,
          })
          marker.setLnglat([lng, lat])
          markerLayer.addMarker(marker)
        }

        // 将标注图层添加到场景上
        scene.addMarkerLayer(markerLayer)
      })
    </script>
  </body>
</html>

图层

点图层

  • 点图层(PointLayer) 由点对象(Point)组成

  • 点对象可以由图片或者文本描述

  1. 符号点
      const { Scene, GaodeMap, PointLayer } = L7

      const scene = new Scene({
        id: 'map',
        map: new GaodeMap({
          style: 'normal',
          center: [114.3, 30.5],
          zoom: 10,
        }),
      })

      const data = [
        {
          lng: 114.3,
          lat: 30.5,
          name: '白沙洲',
        },
        {
          lng: 114.4,
          lat: 30.45,
          name: '中南路',
        },
      ]

      scene.on('loaded', () => {
        scene.addImage('police', './images/avatar.png')
        const policeLayer = new PointLayer()
          .source(data, {
            parser: {
              type: 'json',
              x: 'lng',
              y: 'lat',
            },
          })
          .shape('police') // 形状: 使用police图片
          .size(16) // 大小: 单位px
        scene.addLayer(policeLayer)
      })
  1. 圆环动图
      const data = {
        type: 'FeatureCollection',
        features: [
          {
            type: 'Feature',
            geometry: {
              type: 'Point',
              coordinates: [114.3, 30.5],
            },
          },
        ],
      }

      scene.on('loaded', () => {
        const pointLayer = new PointLayer()
          .source(data) // 设置数据源
          .animate(true) // 开启动画
          .color('#ff0000') // 设置颜色
          .shape('circle') // 设置形状
          .size(100) // 设置大小 px
          .active(true) // 选中状态
        scene.addLayer(pointLayer)
      })
  1. 雷达图
      scene.on('loaded', () => {
        const pointLayer = new PointLayer()
          .source(data) // 设置数据源
          .animate(true) // 开启动画, 设置雷达图, 必须开启动画
          .color('#ff0000') // 设置颜色
          .shape('radar') // 设置形状
          .size(100) // 设置大小 px
          .active(true) // 选中状态
        scene.addLayer(pointLayer)
      })

线图层

  1. 流线动图
      const { Scene, GaodeMap, LineLayer } = L7
      const scene = new Scene({
        id: 'map',
        map: new GaodeMap({
          style: 'normal',
          center: [114.3, 30.5],
          zoom: 10,
        }),
      })

      const data = {
        type: 'FeatureCollection',
        features: [
          {
            type: 'Feature',
            geometry: {
              type: 'LineString',
              coordinates: [
                [114.292975, 30.488542],
                [114.29292, 30.493947],
                [114.293779, 30.498206],
                [114.299404, 30.498046],
                [114.302326, 30.497993],
              ],
            },
          },
        ],
      }

      scene.on('loaded', () => {
        const layer = new LineLayer()
          .source(data)
          .shape('line')
          .size(2)
          .color('#f00')
          .animate({
            trailLength: 1, // 流线长度
            interval: 0.5, // 实现流线的间隔,分两段执行完流线
            duration: 2, // 每段轨迹执行的时间
          })
        scene.addLayer(layer)
      })
  1. 3D弧线图
      scene.on('loaded', () => {
        scene.setRotation(30)
        const layer = new LineLayer({
          blend: 'normal',
        })
          .source(data)
          .shape('arc3d')
          .size(2)
          .color('#f00')
          .animate({
            trailLength: 1,
            interval: 0.5,
            duration: 2,
          })
        scene.addLayer(layer)
      })

面图层

  1. 深圳智慧城市
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <!-- 引入库文件 -->
    <link
      href="https://api.mapbox.com/mapbox-gl-js/v2.9.1/mapbox-gl.css"
      rel="stylesheet"
    />
    <script src="https://api.mapbox.com/mapbox-gl-js/v2.9.1/mapbox-gl.js"></script>
    <script src="https://unpkg.com/@antv/l7"></script>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      body {
        overflow: hidden;
      }
      #map {
        height: 100vh;
      }
    </style>
  </head>
  <body>
    <div id="map"></div>

    <script>
      // 创建mapbox地图对象
      mapboxgl.accessToken = ''
      const map = new mapboxgl.Map({
        container: 'map',
        style: 'mapbox://styles/mapbox/dark-v10',
        pitch: 50,
        center: [114.050008, 22.529272],
        zoom: 14,
      })

      // 创建L7的场景
      const { Scene, Mapbox, PolygonLayer } = L7
      const scene = new Scene({
        id: 'map',
        map: new Mapbox({
          mapInstance: map,
        }),
      })

      scene.on('loaded', () => {
        fetch('https://gw.alipayobjects.com/os/basement_prod/972566c5-a2b9-4a7e-8da1-bae9d0eb0117.json'
        )
          .then((res) => res.json())
          .then((data) => {
            // console.log(data)
            const layer = new PolygonLayer()
              .source(data)
              .shape('extrude')
              .size('h10', [100, 120, 160, 200, 260, 500])
              .color('h10', [
                '#816CAD',
                '#A67FB5',
                '#C997C7',
                '#DEB8D4',
                '#F5D4E6',
                '#FAE4F1',
                '#FFF3FC',
              ])
              .active(true)
            scene.addLayer(layer)
          })
      })
    </script>
  </body>
</html>
  1. 水体
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <!-- 1. 引入L7库 -->
    <script src="https://unpkg.com/@antv/l7"></script>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
    </style>
  </head>
  <body>
    <!-- 2. 准备地图容器 -->
    <div id="map"></div>

    <!-- 3. 创建场景和地图对象 -->
    <script>
      const { Scene, GaodeMap, PolygonLayer } = L7
      const scene = new Scene({
        id: 'map',
        map: new GaodeMap({
          style: 'normal',
          center: [120.144689, 30.250433],
          zoom: 14,
          token: 'bda17043c3dfbbbfd24900155b3fa909',
          pitch: 45,
        }),
      })
      scene.on('loaded', () => {
        fetch(
          'https://gw.alipayobjects.com/os/bmw-prod/67130c6c-7f49-4680-915c-54e69730861d.json'
        )
          .then((data) => data.json())
          .then((data) => {
            const { lakeData } = data
            const lakeLayer = new PolygonLayer()
              .source(lakeData)
              .shape('ocean')
              .color('#1E90FF')
              .style({ speed: 0.4 })
              .animate(true)
            scene.addLayer(lakeLayer)
          })
      })
    </script>
  </body>
</html>

图形绘制

绘制点

DrawPoint

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <!-- 1. 引入L7库 -->
    <script src="https://unpkg.com/@antv/l7"></script>
    <script src="./node_modules/@antv/l7-draw/dist/l7-draw.js"></script>
    <style>
      * {
        margin: 0;
        padding: 0;
      }
      .btn {
        padding: 5px;
      }
      .enable {
        position: absolute;
        top: 0;
        left: 0;
        z-index: 99;
      }
      .exit {
        position: absolute;
        top: 0;
        left: 100px;
        z-index: 99;
      }
    </style>
  </head>
  <body>
    <button onclick="addPoint()" class="btn enable">开启点绘制</button>
    <button onclick="exit()" class="btn exit">退出</button>
    <div id="map"></div>

    <script>
      const { Scene, GaodeMap } = L7
      const { DrawPoint, DrawEvent } = L7.Draw
      const scene = new Scene({
        id: 'map',
        map: new GaodeMap({
          style: 'normal',
          center: [114.3, 30.5],
          zoom: 10,
        }),
      })

      let draw = null
      scene.on('loaded', () => {
        // 创建绘制点的工具
        draw = new DrawPoint(scene, {})
      })

      function addPoint() {
        draw.enable()
      }
      function exit() {
        draw.disable()
      }
    </script>
  </body>
</html>

绘制线

DrawLine

      const { Scene, GaodeMap } = L7
      const { DrawLine, DrawEvent } = L7.Draw

      const scene = new Scene({
        id: 'map',
        map: new GaodeMap({
          style: 'normal',
          center: [114.3, 30.5],
          zoom: 10,
        }),
      })
      scene.on('loaded', () => {
        const drawLine = new DrawLine(scene, {
          // 测量距离的参数
          distanceOptions: {
            showTotalDistance: false, // 不显示总长度
            showDashDistance: true, // 显示分段长度
            format: (meters) => {
              if (meters >= 1000) {
                return +(meters / 1000).toFixed(2) + 'km'
              } else {
                return +meters.toFixed(2) + 'm'
              }
            },
          },
        })
        drawLine.enable()
      })

绘制面

DrawPolygon

      const { DrawPolygon, DrawEvent } = L7.Draw

      scene.on('loaded', () => {
        const drawPolygon = new DrawPolygon(scene, {
          areaOptions: {
            format: (squareMeters) => {
              return squareMeters > 1000000
                ? `${+(squareMeters / 1000000).toFixed(2)}km²`
                : `${+squareMeters.toFixed(2)}m²`
            },
          },
        })
        drawPolygon.enable()
      })

绘制矩形

DrawRect

const { DrawEvent, DrawRect } = L7.Draw
scene.on('loaded', () => {
      const drawRect = new DrawRect(scene, {});
      drawRect.enable();

      drawRect.on(DrawEvent.Change, (allFeatures) => {
            console.log(allFeatures);
      });
});

绘制图

DrawCircle

const { DrawEvent, DrawCircle } = L7.Draw
scene.on('loaded', () => {
      const drawCircle = new DrawCircle(scene, {});
      drawCircle.enable();

      drawCircle.on(DrawEvent.Change, (allFeatures) => {
            console.log(allFeatures);
      });
});
posted @ 2024-12-02 22:19  Khru  阅读(47)  评论(0编辑  收藏  举报