vue项目中mapboxgl的几个经典操作代码示例

简介: vue项目中mapboxgl的几个经典操作代码示例

1、创建标记并显示在地图上

功能:在地图上点击时,创建一个标记,并在该标记的弹窗中显示点击位置的经纬度坐标信息。点击标记时,弹窗会显示在地图上。

代码示例:

map.on('click', function (e) {
  const coordinates = e.lngLat;
  const longitude = coordinates.lng;
  const latitude = coordinates.lat;
  // 创建一个标记
  const marker = new mapboxgl.Marker()
    .setLngLat(coordinates)
    .addTo(map);
  // 创建一个弹窗,并将坐标信息添加到弹窗内容中
  const popup = new mapboxgl.Popup()
    .setLngLat(coordinates)
    .setHTML(`<p>经度: ${longitude}</p><p>纬度: ${latitude}</p>`)
    .addTo(map);
  // 给标记添加点击事件,点击时显示弹窗
  marker.getElement().addEventListener('click', function () {
    popup.addTo(map);
  });
});

2、实现插点效果

功能:使用 Mapbox GL JS 中的符号图层(Symbol Layer)来在地图上绘制点标记,并根据项目列表的位置信息进行插点展示。

代码示例:

// 假设项目列表的数据格式为以下形式
const projectList = [
  {
    name: '项目1',
    latitude: 39.9042,
    longitude: 116.4074,
  },
  {
    name: '项目2',
    latitude: 31.2304,
    longitude: 121.4737,
  },
  // ...
];
// 创建一个符号图层,用于绘制点标记
map.on('load', function () {
  map.addLayer({
    id: 'project-markers',
    type: 'symbol',
    source: {
      type: 'geojson',
      data: {
        type: 'FeatureCollection',
        features: projectList.map((project) => ({
          type: 'Feature',
          properties: {},
          geometry: {
            type: 'Point',
            coordinates: [project.longitude, project.latitude],
          },
        })),
      },
    },
    layout: {
      'icon-image': 'marker-15', // 使用预定义的图标作为点标记的样式
      'icon-size': 1.5,
    },
  });
});

在上述代码中,我们根据项目列表的位置信息,创建了一个 GeoJSON 对象,其中每个项目都被转换为一个点要素。然后,将该 GeoJSON 对象作为符号图层的数据源,将每个点标记绘制在地图上。

需要注意的是,上述代码中使用了预定义的图标样式 ‘marker-15’,你可以根据需求自定义图标样式或使用其他图标。

通过上述方式,可以将项目列表的位置信息以插点的方式展示在地图上,实现插点效果,并与其他地图元素进行交互。

3、实现点选地图上展示位置

功能:实现点选设备在地图上展示位置

示例代码:

<template>
  <div id="app">
    <div id="map"></div>
    <div class="sidebar">
      <h2>项目列表</h2>
      <el-collapse v-model="collapse">
        <el-collapse-item v-for="project in projectList" :title="project.name" :key="project.id">
          <div class="project-details">
            <div class="project-info">
              <p><strong>项目名称:</strong> {{ project.name }}</p>
              <p><strong>项目经理:</strong> {{ project.manager }}</p>
              <p><strong>设备数量:</strong> {{ project.deviceCount }}</p>
            </div>
            <div class="device-list">
              <h4>设备列表</h4>
              <ul>
                <li v-for="device in project.devices" :key="device.id" @click="showDeviceLocation(device)">
                  {{ device.name }}
                </li>
              </ul>
            </div>
          </div>
        </el-collapse-item>
      </el-collapse>
    </div>
    <div id="charts"></div>
  </div>
</template>
<script>
import mapboxgl from 'mapbox-gl'
import * as echarts from 'echarts'
import 'echarts-gl'
export default {
  data() {
    return {
      map: null,
      projectList: [
        {
          id: 1,
          name: '项目1',
          manager: '经理1',
          deviceCount: 5,
          devices: [
            { id: 1, name: '设备1', latitude: 39.9042, longitude: 116.4074 },
            { id: 2, name: '设备2', latitude: 31.2304, longitude: 121.4737 },
            { id: 3, name: '设备3', latitude: 25.7617, longitude: -80.1918 },
            { id: 4, name: '设备4', latitude: 51.5074, longitude: -0.1278 },
            { id: 5, name: '设备5', latitude: 37.7749, longitude: -122.4194 },
          ],
        },
        // ...
      ],
      collapse: [],
    }
  },
  mounted() {
    // 初始化地图
    mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN'
    this.map = new mapboxgl.Map({
      container: 'map',
      style: 'mapbox://styles/mapbox/streets-v11',
      center: [0, 0],
      zoom: 2,
    })
    // 添加插点图层
    this.map.on('load', () => {
      this.addMarkers()
    })
    // 初始化 ECharts 图表
    this.initCharts()
  },
  methods: {
    addMarkers() {
      this.projectList.forEach((project) => {
        project.devices.forEach((device) => {
          const marker = new mapboxgl.Marker().setLngLat([device.longitude, device.latitude]).addTo(this.map)
          marker.getElement().addEventListener('click', () => {
            this.showDeviceLocation(device)
          })
        })
      })
    },
    showDeviceLocation(device) {
      this.map.flyTo({
        center: [device.longitude, device.latitude],
        zoom: 10,
      })
    },
    initCharts() {
      // 初始化 ECharts 图表
      const chartContainer = document.getElementById('charts')
      const chart = echarts.init(chartContainer)
      const option = {
        // 配置 ECharts 统计图的选项
        // ...
      }
      chart.setOption(option)
    },
  },
}
</script>
<style>
#app {
  display: flex;
  height: 100vh;
}
#map {
  flex: 1;
}
.sidebar {
  width: 300px;
  padding: 20px;
  background-color: #f5f5f5;
  overflow-y: auto;
}
.project-details {
  margin-bottom: 10px;
}
.project-info p {
  margin-bottom: 5px;
}
.device-list {
  margin-top: 10px;
}
.device-list h4 {
  margin-bottom: 5px;
}
.device-list ul {
  list-style: none;
  padding: 0;
  margin: 0;
}
#charts {
  flex: 1;
}
</style>

在上述代码示例中,设备信息中包含了经纬度信息,通过点击设备列表中的设备,在地图上展示设备的位置信息。通过调用 setLngLat 方法设置 Marker 的经纬度,然后使用 addTo 方法将 Marker 添加到地图上。同时,为 Marker 的元素添加点击事件监听器,点击 Marker 时会调用 showDeviceLocation 方法,在地图上展示设备的位置。

将 YOUR_MAPBOX_ACCESS_TOKEN 替换为你自己的 Mapbox 访问令牌。

4、结合 Mapbox GL、ECharts、Element UI 的综合示例1

<template>
  <div id="app">
    <div id="map"></div>
    <div class="sidebar">
      <h2>项目列表</h2>
      <el-collapse v-model="collapse">
        <el-collapse-item v-for="project in projectList" :title="project.name" :key="project.id">
          <div class="project-details">
            <div class="project-info">
              <p><strong>项目名称:</strong> {{ project.name }}</p>
              <p><strong>项目经理:</strong> {{ project.manager }}</p>
              <p><strong>设备数量:</strong> {{ project.deviceCount }}</p>
            </div>
            <div class="device-list">
              <h4>设备列表</h4>
              <ul>
                <li v-for="device in project.devices" :key="device.id">{{ device.name }}</li>
              </ul>
            </div>
          </div>
        </el-collapse-item>
      </el-collapse>
    </div>
    <div id="charts"></div>
  </div>
</template>
<script>
import mapboxgl from 'mapbox-gl'
import * as echarts from 'echarts'
import 'echarts-gl'
export default {
  data() {
    return {
      map: null,
      projectList: [
        {
          id: 1,
          name: '项目1',
          manager: '经理1',
          deviceCount: 5,
          latitude: 39.9042,
          longitude: 116.4074,
          devices: [
            { id: 1, name: '设备1' },
            { id: 2, name: '设备2' },
            { id: 3, name: '设备3' },
            { id: 4, name: '设备4' },
            { id: 5, name: '设备5' },
          ],
        },
        {
          id: 2,
          name: '项目2',
          manager: '经理2',
          deviceCount: 3,
          latitude: 31.2304,
          longitude: 121.4737,
          devices: [
            { id: 6, name: '设备6' },
            { id: 7, name: '设备7' },
            { id: 8, name: '设备8' },
          ],
        },
      ],
      collapse: [],
    }
  },
  mounted() {
    // 初始化地图
    mapboxgl.accessToken = 'YOUR_MAPBOX_ACCESS_TOKEN'
    this.map = new mapboxgl.Map({
      container: 'map',
      style: 'mapbox://styles/mapbox/streets-v11',
      center: [0, 0],
      zoom: 2,
    })
    // 添加插点图层
    this.map.on('load', () => {
      this.addMarkers()
    })
    // 初始化 ECharts 图表
    this.initCharts()
  },
  methods: {
    addMarkers() {
      this.projectList.forEach((project) => {
        const marker = new mapboxgl.Marker().setLngLat([project.longitude, project.latitude]).addTo(this.map)
        marker.getElement().addEventListener('click', () => {
          this.showProjectDetails(project.id)
        })
      })
    },
    showProjectDetails(projectId) {
      this.collapse = [projectId]
    },
    initCharts() {
      const chartContainer = document.getElementById('charts')
      const chart = echarts.init(chartContainer)
      const option = {
        // 配置 ECharts 统计图的选项
        // ...
      }
      chart.setOption(option)
    },
  },
}
</script>
<style>
#app {
  display: flex;
  height: 100vh;
}
#map {
  flex: 1;
}
.sidebar {
  width: 300px;
  padding: 20px;
  background-color: #f5f5f5;
  overflow-y: auto;
}
.project-details {
  margin-bottom: 10px;
}
.project-info p {
  margin-bottom: 5px;
}
.device-list {
  margin-top: 10px;
}
.device-list h4 {
  margin-bottom: 5px;
}
.device-list ul {
  list-style: none;
  padding: 0;
  margin: 0;
}
#charts {
  flex: 1;
}
</style>

将 YOUR_MAPBOX_ACCESS_TOKEN 替换为你自己的 Mapbox 访问令牌。

以上代码示例中,使用了 Vue.js、Mapbox GL、ECharts 和 Element UI。通过插点效果在地图上展示项目的位置信息,并通过点击项目列表展示项目的详细信息。统计图使用 ECharts 进行可视化展示。同时,使用了 Element UI 的 Collapse 组件实现可收缩的弹框效果。

5、结合 Mapbox GL、ECharts、Element UI 的综合示例2

项目分布和设备调配案例代码示例:

<template>
  <div class="container">
    <div class="sidebar">
      <h2>项目列表</h2>
      <el-collapse v-model="activeProjects">
        <el-collapse-item v-for="project in projects" :key="project.id">
          <template slot="title">
            {{ project.name }}
          </template>
          <el-row>
            <el-col :span="12">
              <h4>项目信息</h4>
              <p>工作量: {{ project.workload }}</p>
              <p>位置: {{ project.location }}</p>
              <p>开始日期: {{ project.startDate }}</p>
              <p>负责人: {{ project.projectManager }}</p>
            </el-col>
            <el-col :span="12">
              <h4>设备列表</h4>
              <ul>
                <li v-for="deviceId in project.equipmentList" :key="deviceId">
                  {{ getDeviceName(deviceId) }}
                </li>
              </ul>
            </el-col>
          </el-row>
        </el-collapse-item>
      </el-collapse>
    </div>
    <div id="map" class="map"></div>
  </div>
</template>
<script>
import mapboxgl from 'mapbox-gl';
import axios from 'axios';
import * as echarts from 'echarts';
export default {
  data() {
    return {
      projects: [], // 项目列表数据
      devices: [], // 设备列表数据
      activeProjects: [], // 展开的项目列表项
      map: null, // Mapbox GL 实例
      chart: null, // ECharts 实例
    };
  },
  mounted() {
    // 初始化地图
    mapboxgl.accessToken = 'your-mapbox-access-token';
    this.map = new mapboxgl.Map({
      container: 'map',
      style: 'mapbox://styles/mapbox/light-v10',
      center: [0, 0],
      zoom: 1,
    });
    // 初始化图表
    this.chart = echarts.init(document.getElementById('chart'));
    // 获取设备列表数据
    axios.get('/api/devices')
      .then(response => {
        this.devices = response.data;
      })
      .catch(error => {
        console.error('Failed to fetch devices:', error);
      });
    // 获取项目列表数据
    axios.get('/api/projects')
      .then(response => {
        this.projects = response.data;
      })
      .catch(error => {
        console.error('Failed to fetch projects:', error);
      });
  },
  methods: {
    // 根据设备ID获取设备名称
    getDeviceName(deviceId) {
      const device = this.devices.find(d => d.id === deviceId);
      return device ? device.name : '';
    },
    // 根据项目ID获取项目位置坐标
    getProjectCoordinates(projectId) {
      // 这里假设项目的位置是经纬度坐标 [longitude, latitude]
      const project = this.projects.find(p => p.id === projectId);
      return project ? project.location : null;
    },
    // 在地图上展示项目位置
    showProjectLocation(projectId) {
      const coordinates = this.getProjectCoordinates(projectId);
      if (coordinates) {
        // 创建地图标记
        const marker = new mapboxgl.Marker().setLngLat(coordinates).addTo(this.map);
        // 将地图中心移动到标记位置
        this.map.flyTo({ center: coordinates, zoom: 10 });
      }
    },
    // 绘制设备统计图表
    drawDeviceChart() {
      // 获取设备状态统计数据
      const deviceStatus = this.devices.reduce((result, device) => {
        result[device.status] = result[device.status] ? result[device.status] + 1 : 1;
        return result;
      }, {});
      // 绘制统计图表
      const options = {
        title: { text: '设备状态统计' },
        series: [
          {
            name: '设备状态',
            type: 'pie',
            radius: '60%',
            data: Object.entries(deviceStatus).map(([status, count]) => ({ name: status, value: count })),
          },
        ],
      };
      this.chart.setOption(options);
    },
  },
};
</script>
<style>
.container {
  display: flex;
}
.sidebar {
  width: 300px;
  padding: 20px;
  background-color: #f5f5f5;
}
.map {
  flex: 1;
  height: 600px;
}
</style>

替换 your-mapbox-access-token,并根据您的后端 API 配置更新数据请求的 URL。

目录
相关文章
|
5天前
|
JavaScript 前端开发
如何在 Vue 项目中配置 Tree Shaking?
通过以上针对 Webpack 或 Rollup 的配置方法,就可以在 Vue 项目中有效地启用 Tree Shaking,从而优化项目的打包体积,提高项目的性能和加载速度。在实际配置过程中,需要根据项目的具体情况和需求,对配置进行适当的调整和优化。
|
4天前
|
JavaScript 前端开发 UED
vue学习第二章
欢迎来到我的博客!我是一名自学了2年半前端的大一学生,熟悉JavaScript与Vue,目前正在向全栈方向发展。如果你从我的博客中有所收获,欢迎关注我,我将持续更新更多优质文章。你的支持是我最大的动力!🎉🎉🎉
|
4天前
|
JavaScript 前端开发 开发者
vue学习第一章
欢迎来到我的博客!我是瑞雨溪,一名热爱JavaScript和Vue的大一学生。自学前端2年半,熟悉JavaScript与Vue,正向全栈方向发展。博客内容涵盖Vue基础、列表展示及计数器案例等,希望能对你有所帮助。关注我,持续更新中!🎉🎉🎉
|
19天前
|
数据采集 监控 JavaScript
在 Vue 项目中使用预渲染技术
【10月更文挑战第23天】在 Vue 项目中使用预渲染技术是提升 SEO 效果的有效途径之一。通过选择合适的预渲染工具,正确配置和运行预渲染操作,结合其他 SEO 策略,可以实现更好的搜索引擎优化效果。同时,需要不断地监控和优化预渲染效果,以适应不断变化的搜索引擎环境和用户需求。
|
5天前
|
存储 缓存 JavaScript
在 Vue 中使用 computed 和 watch 时,性能问题探讨
本文探讨了在 Vue.js 中使用 computed 计算属性和 watch 监听器时可能遇到的性能问题,并提供了优化建议,帮助开发者提高应用性能。
|
5天前
|
存储 缓存 JavaScript
如何在大型 Vue 应用中有效地管理计算属性和侦听器
在大型 Vue 应用中,合理管理计算属性和侦听器是优化性能和维护性的关键。本文介绍了如何通过模块化、状态管理和避免冗余计算等方法,有效提升应用的响应性和可维护性。
|
5天前
|
存储 缓存 JavaScript
Vue 中 computed 和 watch 的差异
Vue 中的 `computed` 和 `watch` 都用于处理数据变化,但使用场景不同。`computed` 用于计算属性,依赖于其他数据自动更新;`watch` 用于监听数据变化,执行异步或复杂操作。
|
6天前
|
存储 JavaScript 开发者
Vue 组件间通信的最佳实践
本文总结了 Vue.js 中组件间通信的多种方法,包括 props、事件、Vuex 状态管理等,帮助开发者选择最适合项目需求的通信方式,提高开发效率和代码可维护性。
|
6天前
|
存储 JavaScript
Vue 组件间如何通信
Vue组件间通信是指在Vue应用中,不同组件之间传递数据和事件的方法。常用的方式有:props、自定义事件、$emit、$attrs、$refs、provide/inject、Vuex等。掌握这些方法可以实现父子组件、兄弟组件及跨级组件间的高效通信。
|
11天前
|
JavaScript
Vue基础知识总结 4:vue组件化开发
Vue基础知识总结 4:vue组件化开发