每次旅行或探店后,你是否想过把那些值得纪念的地点可视化?微信小程序的map组件为我们提供了实现这一想法的绝佳工具。今天,我将带你从零开始构建一个能记录并展示足迹的个性化地图应用,不仅会涵盖基础功能,还会分享几个提升用户体验的小技巧。
在开始编码前,我们需要确保开发环境就绪。首先下载并安装微信开发者工具,这是官方提供的集成开发环境(IDE),支持代码编辑、调试和预览。创建新项目时,记得选择"小程序"模板,并填写正确的AppID(可以在微信公众平台获取)。
提示:如果你只是学习测试,可以使用测试号AppID,但部分高级API可能受限。
基础项目结构通常包括以下几个关键文件:
app.json:全局配置,如页面路径、窗口样式等pages/:存放各个页面的目录utils/:工具函数存放处在app.json中,我们需要声明位置权限,这是后续获取用户位置的关键:
json复制{
"pages": ["pages/index/index"],
"permission": {
"scope.userLocation": {
"desc": "需要获取您的位置以记录足迹"
}
}
}
在页面配置文件index.json中,我们需要声明使用map组件:
json复制{
"usingComponents": {},
"navigationBarTitleText": "我的足迹地图"
}
接着,在index.wxml中添加map组件的基本结构:
html复制<map
id="myMap"
longitude="{{longitude}}"
latitude="{{latitude}}"
scale="16"
show-location
markers="{{markers}}"
bindmarkertap="onMarkerTap"
style="width: 100%; height: 100vh;"
></map>
在index.js中,我们首先需要获取用户的当前位置:
javascript复制Page({
data: {
longitude: 0,
latitude: 0,
markers: []
},
onLoad() {
this.getLocation()
},
getLocation() {
wx.getLocation({
type: 'gcj02',
success: (res) => {
this.setData({
longitude: res.longitude,
latitude: res.latitude
})
this.addMarker(res, '当前位置', '/images/current.png')
},
fail: (err) => {
console.error('获取位置失败:', err)
wx.showToast({
title: '获取位置失败',
icon: 'none'
})
}
})
}
})
足迹地图的核心功能是记录用户到访的地点。我们可以通过以下方式添加标记点:
javascript复制addMarker(location, title, iconPath) {
const newMarker = {
id: Date.now(), // 使用时间戳作为唯一ID
longitude: location.longitude,
latitude: location.latitude,
iconPath: iconPath,
width: 30,
height: 30,
callout: {
content: title,
color: '#ffffff',
bgColor: '#07c160',
padding: 5,
borderRadius: 10,
display: 'ALWAYS'
}
}
this.setData({
markers: [...this.data.markers, newMarker]
})
// 保存到本地存储
this.saveMarkers()
}
为了确保用户关闭小程序后数据不丢失,我们需要使用微信的本地存储功能:
javascript复制saveMarkers() {
wx.setStorageSync('savedMarkers', this.data.markers)
},
loadMarkers() {
const savedMarkers = wx.getStorageSync('savedMarkers') || []
this.setData({ markers: savedMarkers })
}
让用户可以点击标记点查看详情:
javascript复制onMarkerTap(e) {
const markerId = e.markerId
const marker = this.data.markers.find(m => m.id === markerId)
wx.showModal({
title: marker.callout.content,
content: `经度: ${marker.longitude}\n纬度: ${marker.latitude}`,
showCancel: false
})
}
在map组件上添加按钮控件,提升用户体验:
html复制<map ...>
<cover-view class="controls">
<cover-image
src="/images/add.png"
bindtap="addCurrentLocation"
class="control-btn"
></cover-image>
<cover-image
src="/images/center.png"
bindtap="moveToLocation"
class="control-btn"
></cover-image>
</cover-view>
</map>
对应的样式和交互逻辑:
css复制.controls {
position: absolute;
bottom: 20px;
right: 20px;
display: flex;
flex-direction: column;
}
.control-btn {
width: 50px;
height: 50px;
margin-top: 10px;
}
javascript复制addCurrentLocation() {
wx.getLocation({
type: 'gcj02',
success: (res) => {
const date = new Date()
const title = `地点 ${date.toLocaleDateString()}`
this.addMarker(res, title, '/images/marker.png')
}
})
},
moveToLocation() {
this.mapCtx = this.mapCtx || wx.createMapContext('myMap')
this.mapCtx.moveToLocation()
}
根据地点类型使用不同的标记图标:
| 地点类型 | 图标路径 | 颜色 |
|---|---|---|
| 餐厅 | /images/food.png | #FF5252 |
| 景点 | /images/view.png | #4CAF50 |
| 酒店 | /images/hotel.png | #2196F3 |
| 购物 | /images/shop.png | #FF9800 |
实现代码示例:
javascript复制addCustomMarker(location, type, title) {
const iconMap = {
'food': '/images/food.png',
'view': '/images/view.png',
'hotel': '/images/hotel.png',
'shop': '/images/shop.png'
}
this.addMarker(location, title, iconMap[type])
}
除了标记点,我们还可以绘制用户的行进轨迹:
javascript复制drawPolyline(points) {
this.setData({
polyline: [{
points: points,
color: '#1aad19',
width: 4,
dottedLine: false
}]
})
}
当地图标记点较多时,可以考虑以下优化措施:
在实际开发中,你可能会遇到以下典型问题:
地图显示空白
标记点不显示
位置获取失败
真机调试问题
以下是项目的主要文件结构:
code复制/miniprogram
/pages
/index
index.wxml
index.wxss
index.js
index.json
/images
current.png
marker.png
food.png
view.png
hotel.png
shop.png
add.png
center.png
app.js
app.json
app.wxss
关键实现代码汇总:
javascript复制// index.js
Page({
data: {
longitude: 116.397428,
latitude: 39.90923,
markers: [],
polyline: []
},
onLoad() {
this.loadMarkers()
this.getLocation()
},
// 其他方法如前文所示...
})
html复制<!-- index.wxml -->
<map
id="myMap"
longitude="{{longitude}}"
latitude="{{latitude}}"
markers="{{markers}}"
polyline="{{polyline}}"
bindmarkertap="onMarkerTap"
style="width: 100%; height: 100vh;"
>
<cover-view class="controls">
<cover-image
src="/images/add.png"
bindtap="addCurrentLocation"
class="control-btn"
></cover-image>
<cover-image
src="/images/center.png"
bindtap="moveToLocation"
class="control-btn"
></cover-image>
</cover-view>
</map>
在实际项目中,我发现地图组件的性能优化尤为重要,特别是当标记点超过50个时,合理使用include-points属性限定显示范围可以显著提升渲染效率。另外,为不同类型的标记点设计独特的视觉样式,不仅能增强美观性,还能提升信息的可读性。