文章同步更新于我的个人博客:松果猿的博客,欢迎访问获取更多技术分享。

同时,您也可以关注我的微信公众号:松果猿的代码工坊,获取最新文章推送和编程技巧。

前言

这应该算是这个项目的完结篇了,其实这个项目特别蠢,我应该有一个明确的规划,但都是走一步看一步,踩了许多坑,毕竟我也是初学者,比如说不知道Mybatis无法处理Geometry数据格式,前后端wkt、wkb、geojson格式互转瞎搞一通,然后tmd搞到后面我都不知道是什么了,代码胡乱改一通。

本人的这次改动有点多,如果真的有人跟着我这个项目来系统学习的话(大概率没人看),那你真的是太nb了哈哈哈哈,直接去我的github仓库下载源码来学习吧。

演示视频放在B站了:webgis课程作业:Vue3+Springboot共享单车系统

前端

添加@/hooks/useBikeGeom.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import { ref } from "vue";
import { Point } from "ol/geom";
import axios from "axios";
import { useMapStore } from "@/stores/mapStore.js";
import bikeIcon from "@/assets/img/bike.png";
import { Vector as VectorLayer } from "ol/layer";
import { Vector as VectorSource } from "ol/source";
import { Feature } from "ol";
import { Icon, Style } from "ol/style";
import { Heatmap as HeatmapLayer } from "ol/layer";
import { fromLonLat } from "ol/proj";

export function useBikeGeom() {
const bikeGeom = ref([]);

const bikeGeomLayer = ref(null);
const mapStore = useMapStore();
const map = mapStore.map;
const bikeGeomSource = ref(null);
const bikeGeomFeature = ref([]);

const fetchBikeGeom = async () => {
try {
const res = await axios.get(`${import.meta.env.VITE_API_URL}/bikes`);
console.log("API返回数据:", res.data.data);

bikeGeom.value = res.data.data.map((item) => {
// 将字符串解析为 JSON 对象
const locationObj = JSON.parse(item.location);
const coordinates = locationObj.coordinates;
const transformedCoords = fromLonLat(coordinates);
return new Point(transformedCoords);
});

console.log("转换后的坐标点:", bikeGeom.value);
} catch (error) {
console.error("获取单车数据失败:", error);
throw error;
}
};

const loadBikeGeom = async () => {
await fetchBikeGeom();
console.log(bikeGeom.value);
bikeGeomFeature.value = bikeGeom.value.map((item) => {
return new Feature({
geometry: item,
});
});

bikeGeomSource.value = new VectorSource({
features: bikeGeomFeature.value,
});

bikeGeomLayer.value = new VectorLayer({
source: bikeGeomSource.value,
style: new Style({
image: new Icon({
src: bikeIcon,
scale: 0.05,
}),
}),
});
};

const addBikeGeomLayer = async () => {
await loadBikeGeom();
mapStore.map.addLayer(bikeGeomLayer.value);
};

const toggleBikeHeatMap = async () => {
await loadBikeGeom();
if (bikeGeomLayer.value) {
mapStore.map.removeLayer(bikeGeomLayer.value);
}
bikeGeomLayer.value = new HeatmapLayer({
source: bikeGeomSource.value,
blur: 10,
radius: 20,
});
mapStore.map.addLayer(bikeGeomLayer.value);
};

return {
toggleBikeHeatMap,
addBikeGeomLayer,
};
}

Header.vue中添加点击事件:

后端

后端魔改的比较多,就不赘述了

效果:

.gif)

项目地址:https://github.com/songguo1/Share_bike