Vue3 + TS + Leafletjs 打造企业级原神大地图(高の青)

2024-07-03 10:17:25 浏览数 (1)

前端开发道路艰难,竞争激烈。唯有掌握稀缺技能,提升综合能力,才能杀出一条血路。下面我们将详细讲解如何使用 Vue3、TypeScript 和 Leaflet.js 打造web游戏大地图项目。我们从项目初始化开始,逐步构建一个功能完善的地图应用。

1. 项目初始化

1.1 安装 Vue CLI

首先,确保你已经安装了 Vue CLI。如果没有,可以通过以下命令安装:

代码语言:txt复制
npm install -g @vue/cli

1.2 创建项目

使用 Vue CLI 创建一个新的 Vue3 项目:

代码语言:txt复制
vue create genshin-map

在项目创建过程中,选择 TypeScript 作为开发语言。

1.3 安装 Leaflet.js

进入项目目录,并安装 Leaflet.js:

代码语言:txt复制
cd genshin-map
npm install leaflet
npm install --save-dev @types/leaflet

2. 项目结构

项目创建完成后,目录结构如下:

代码语言:txt复制
genshin-map/
├── node_modules/
├── public/
│   ├── index.html
├── src/
│   ├── assets/
│   ├── components/
│   │   └── MapView.vue
│   ├── views/
│   │   └── Home.vue
│   ├── App.vue
│   ├── main.ts
├── package.json
├── tsconfig.json
├── vue.config.js

3. Leaflet.js 基础配置

3.1 引入 Leaflet 样式

src/main.ts 文件中引入 Leaflet 的样式:

代码语言:txt复制
import 'leaflet/dist/leaflet.css';
import { createApp } from 'vue';
import App from './App.vue';
import router from './router';

createApp(App).use(router).mount('#app');

3.2 创建 MapView 组件

src/components/ 目录下创建 MapView.vue 文件:

代码语言:txt复制
<template>
  <div id="map" :style="{ height: '100vh', width: '100%' }"></div>
</template>

<script lang="ts">
import { defineComponent, onMounted } from 'vue';
import L from 'leaflet';

export default defineComponent({
  name: 'MapView',
  setup() {
    onMounted(() => {
      const map = L.map('map').setView([0, 0], 2);
      L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
      }).addTo(map);
    });
  }
});
</script>

<style scoped>
#map {
  height: 100%;
}
</style>

3.3 在 Home 视图中使用 MapView

修改 src/views/Home.vue 文件,引入并使用 MapView 组件:

代码语言:txt复制
<template>
  <div>
    <MapView />
  </div>
</template>

<script lang="ts">
import { defineComponent } from 'vue';
import MapView from '@/components/MapView.vue';

export default defineComponent({
  name: 'Home',
  components: {
    MapView
  }
});
</script>

<style scoped>
/* 添加必要的样式 */
</style>

4. 添加地图交互功能

4.1 添加标记点功能

MapView.vue 文件中添加标记点功能:

代码语言:txt复制
<template>
  <div id="map" :style="{ height: '100vh', width: '100%' }"></div>
</template>

<script lang="ts">
import { defineComponent, onMounted, ref } from 'vue';
import L from 'leaflet';

export default defineComponent({
  name: 'MapView',
  setup() {
    const map = ref<L.Map>();

    onMounted(() => {
      map.value = L.map('map').setView([0, 0], 2);
      L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
      }).addTo(map.value);

      const marker = L.marker([0, 0]).addTo(map.value);
      marker.bindPopup('原神大地图标记点').openPopup();
    });

    return {
      map
    };
  }
});
</script>

<style scoped>
#map {
  height: 100%;
}
</style>

4.2 添加点击事件

允许用户点击地图添加标记点:

代码语言:txt复制
<template>
  <div id="map" :style="{ height: '100vh', width: '100%' }"></div>
</template>

<script lang="ts">
import { defineComponent, onMounted, ref } from 'vue';
import L from 'leaflet';

export default defineComponent({
  name: 'MapView',
  setup() {
    const map = ref<L.Map>();

    onMounted(() => {
      map.value = L.map('map').setView([0, 0], 2);
      L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
        attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
      }).addTo(map.value);

      map.value.on('click', (e: L.LeafletMouseEvent) => {
        const { lat, lng } = e.latlng;
        L.marker([lat, lng]).addTo(map.value!).bindPopup(`Lat: ${lat}, Lng: ${lng}`).openPopup();
      });
    });

    return {
      map
    };
  }
});
</script>

<style scoped>
#map {
  height: 100%;
}
</style>

5. 添加地图图层

5.1 配置多种图层

为地图添加多种图层,允许用户切换:

代码语言:txt复制
<template>
  <div id="map" :style="{ height: '100vh', width: '100%' }"></div>
</template>

<script lang="ts">
import { defineComponent, onMounted, ref } from 'vue';
import L from 'leaflet';

export default defineComponent({
  name: 'MapView',
  setup() {
    const map = ref<L.Map>();

    onMounted(() => {
      map.value = L.map('map').setView([0, 0], 2);

      const baseLayers = {
        'OpenStreetMap': L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
          attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
        }),
        'OpenTopoMap': L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
          attribution: '&copy; <a href="https://opentopomap.org">OpenTopoMap</a> contributors'
        })
      };

      baseLayers['OpenStreetMap'].addTo(map.value);
      L.control.layers(baseLayers).addTo(map.value);

      map.value.on('click', (e: L.LeafletMouseEvent) => {
        const { lat, lng } = e.latlng;
        L.marker([lat, lng]).addTo(map.value!).bindPopup(`Lat: ${lat}, Lng: ${lng}`).openPopup();
      });
    });

    return {
      map
    };
  }
});
</script>

<style scoped>
#map {
  height: 100%;
}
</style>

5.2 添加自定义图层

在项目中添加自定义图层,例如原神地图:

代码语言:txt复制
<template>
  <div id="map" :style="{ height: '100vh', width: '100%' }"></div>
</template>

<script lang="ts">
import { defineComponent, onMounted, ref } from 'vue';
import L from 'leaflet';

export default defineComponent({
  name: 'MapView',
  setup() {
    const map = ref<L.Map>();

    onMounted(() => {
      map.value = L.map('map').setView([0, 0], 2);

      const baseLayers = {
        'OpenStreetMap': L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
          attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
        }),
        'OpenTopoMap': L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
          attribution: '&copy; <a href="https://opentopomap.org">OpenTopoMap</a> contributors'
        }),
        'GenshinMap': L.tileLayer('path/to/your/genshin-map/{z}/{x}/{y}.png', {
          attribution: '&copy; <a href="your-attribution-link">Genshin Map</a>'
        })
      };

      baseLayers['GenshinMap'].addTo(map.value);
      L.control.layers(baseLayers).addTo(map.value);

      map.value

0 人点赞