前端开发道路艰难,竞争激烈。唯有掌握稀缺技能,提升综合能力,才能杀出一条血路。下面我们将详细讲解如何使用 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 的样式:
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
文件:
<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: '© <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
组件:
<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
文件中添加标记点功能:
<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: '© <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: '© <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: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}),
'OpenTopoMap': L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
attribution: '© <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: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}),
'OpenTopoMap': L.tileLayer('https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png', {
attribution: '© <a href="https://opentopomap.org">OpenTopoMap</a> contributors'
}),
'GenshinMap': L.tileLayer('path/to/your/genshin-map/{z}/{x}/{y}.png', {
attribution: '© <a href="your-attribution-link">Genshin Map</a>'
})
};
baseLayers['GenshinMap'].addTo(map.value);
L.control.layers(baseLayers).addTo(map.value);
map.value