作者: 桃花键神 发布时间: 已于 2026-04-23 19:58:19 修改
来源: https://blog.csdn.net/weixin_50843918/article/details/160384522
上周末,我沿着深圳湾公园骑行,海风拂面,夕阳西下。骑到观桥公园附近时,突然看到一群白鹭从海面上掠过,翅膀在夕阳下闪着金光。那一刻的惊喜,让我忍不住停下车来拍照。
回家后,我打开运动 App 看着今天的轨迹记录:12.5 公里,1 小时 23 分钟,最高时速 28.5 km/h,平均速度 9.1 km/h… 数字冷冰冰的,但骑行时的愉悦心情,却随着时间流逝逐渐淡忘了。
这让我产生了一个思考:轨迹数据记录了我的物理位移,但如何让它承载更多的情感价值?如何让每一段普通的轨迹,变成值得分享的故事?
带着这个问题,我开始探索 AI + 地图的结合方式,最终完成了「轨迹故事生成器」这个小程序项目。它能将你的轨迹数据,结合 AI 大模型的创作能力,生成一段段专属的朋友圈文案,让冰冷的数字变成有温度的故事。
演示视频如下:
📹 嵌入式视频: https://live.csdn.net/v/embed/522779
腾讯地图演示视频
末尾有项目地址可以自行拉取
「轨迹故事生成器」是一款运行在微信小程序端的工具类应用,专注于将用户的轨迹数据转化为生动的内容。
前端框架:微信小程序原生框架
地图服务:腾讯位置服务(小程序 SDK)
AI 能力:腾讯混元大模型 MaaS 平台
数据存储:本地存储(LocalStorage)
对于普通用户而言,运动轨迹只是一堆枯燥的数字。我希望通过 AI 的能力,让这些数字"开口说话",让每一次出行都能变成值得分享的故事。
本项目的开发过程全程借助WorkBuddy平台完成。WorkBuddy 是一个 AI 驱动的开发助手,它整合了多种 Skills(技能)和工具,能够帮助开发者快速完成项目搭建、功能开发和文档撰写。
在开发「轨迹故事生成器」时,我主要通过以下方式与 WorkBuddy 协作:
在开发过程中,我使用了以下专业 Skills 来获取技术指导:
这两个 Skills 提供了腾讯位置服务的完整开发文档,包括:
添加方式如下,可以把这四个都加进来。

以下是本项目开发过程中使用的一些关键提示词(Prompt):
① 初始化地图功能"我想在我的微信小程序里使用腾讯地图展示轨迹,需要注意什么?" → 加载 tencentmap-miniprogram-skill,获取 map 组件配置和权限申请指南② 接入 AI 大模型"帮我接入腾讯云AI大模型能力,修改生成故事功能。让用户输入这段轨迹上发生了哪些事,结合用户输入的内容和轨迹数据编写故事" → 生成云函数代码和前端调用逻辑③ 改成前端直接调用"改成前端直接调用API,移除云开发依赖" → 简化架构,直接用 wx.request 调用混元大模型 API④ 风格转换"把生成故事这个功能,改成生成朋友圈文案" → 调整 Prompt 设计,改写 UI 和文案风格⑤ 征文章节撰写"根据以下要求给这个项目写一个文章,可以先写一个大纲给我确认…" → 撰写参赛征文,包含架构设计、功能实现、代码示例

用户需求(自然语言)
↓
WorkBuddy AI 理解意图
↓
加载相关 Skills(腾讯地图开发指南)
↓
生成代码 / 提供方案
↓
用户确认 / 测试反馈
↓
迭代优化
使用 WorkBuddy 开发有以下几个显著优势:


本项目深度使用了腾讯位置服务的以下能力:
1. 轨迹解析的跨格式支持
不同运动 App 导出的轨迹格式各异,我通过统一的解析接口屏蔽了这些差异:
// trajectory-parser.js
class TrajectoryParser {
parse(content, type) {
switch (type.toLowerCase()) {
case 'gpx':
return this.parseGPX(content)
case 'kml':
return this.parseKML(content)
case 'json':
return this.parseJSON(content)
default:
throw new Error('不支持的格式')
}
}
}
2. 小程序环境兼容性
微信小程序环境下,DOM API(如 DOMParser)不可用,我采用纯正则表达式解析 XML 格式:
// GPX 解析核心逻辑
parseGPX(gpxContent) {
const points = []
const trackPattern = /<trkpt[^>]*lat="([^"]*)"[^>]*lon="([^"]*)"[^>]*>[\s\S]*?<\/trkpt>/gi
let match
while ((match = trackPattern.exec(gpxContent)) !== null) {
points.push({
lat: parseFloat(match[1]),
lon: parseFloat(match[2])
})
}
return points
}
轨迹解析是整个应用的起点。我需要从不同格式的文件中提取关键信息:
核心数据结构:
{
points: [
{ lat: 22.4870, lon: 113.9400, ele: 5, time: Date },
// ... 更多轨迹点
],
metadata: {
name: '深圳湾骑行',
totalDistance: 12500, // 米
totalTime: 4980, // 秒
elevationGain: 128, // 米
maxSpeed: 28.5, // km/h
avgSpeed: 9.1, // km/h
duration: '1小时23分' // 格式化时长
}
}
轨迹统计计算:
// 计算两点间距离( Haversine 公式)
calculateDistance(p1, p2) {
const R = 6371000 // 地球半径(米)
const dLat = this.toRad(p2.lat - p1.lat)
const dLon = this.toRad(p2.lon - p1.lon)
const a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(this.toRad(p1.lat)) * Math.cos(this.toRad(p2.lat)) *
Math.sin(dLon/2) * Math.sin(dLon/2)
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a))
return R * c
}
地图可视化是用户感知最强的部分。我实现了以下功能:
1. 轨迹渲染配置
// lbs-skill-wrapper.js
getTrajectoryConfig(points, options = {}) {
return {
polyline: [{
points: points.map(p => ({
latitude: p.lat,
longitude: p.lon
})),
color: options.color || '#FF6B6B',
width: options.width || 6,
borderWidth: 2,
borderColor: '#FFFFFF',
dottedLine: false,
arrowIconPath: '/assets/images/arrow.png',
arrowColor: '#FFFFFF'
}]
}
}
2. 标记点配置
getMarkersConfig(points, options = {}) {
return [
{
id: 1,
latitude: points[0].lat,
longitude: points[0].lon,
iconPath: '/assets/images/start-point.png',
width: 30,
height: 30,
title: options.startLabel || '起点'
},
{
id: 2,
latitude: points[points.length - 1].lat,
longitude: points[points.length - 1].lon,
iconPath: '/assets/images/end-point.png',
width: 30,
height: 30,
title: options.endLabel || '终点'
}
]
}
3. 轨迹动画播放
// 定时器驱动动画
startPlayback() {
const { points } = this.data
let currentIndex = 0
const play = () => {
if (currentIndex >= points.length) {
this.stopPlayback()
return
}
const point = points[currentIndex]
this.setData({
currentMarker: {
latitude: point.lat,
longitude: point.lon,
iconPath: '/assets/images/moving-point.png'
}
})
currentIndex++
setTimeout(play, 100) // 每 100ms 移动一次
}
play()
}
这是本项目最有技术含量的部分。我直接调用腾讯混元大模型的 MaaS 平台 API,实现智能文案生成。
1. API 调用实现
// 腾讯云 MaaS API 配置
const API_BASE_URL = 'https://tokenhub.tencentmaas.com'
const API_KEY = 'sk-xxxxx' // 你的 API Key
const MODEL_NAME = 'hunyuan-2.0-instruct-20251111'
callAIAPI(data) {
return new Promise((resolve, reject) => {
wx.request({
url: `${API_BASE_URL}/v1/chat/completions`,
method: 'POST',
header: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${API_KEY}`
},
data: {
model: MODEL_NAME,
messages: [
{
role: 'system',
content: '你是一位专业的朋友圈文案大师'
},
{
role: 'user',
content: this.buildPrompt(data)
}
],
temperature: 0.8,
max_tokens: 500
},
success: (res) => {
if (res.statusCode === 200) {
resolve(res.data.choices[0].message.content)
} else {
reject(new Error('API 调用失败'))
}
},
fail: reject
})
})
}
2. Prompt 工程设计
Prompt 的质量直接决定了生成文案的效果。我经过多次调优,设计了如下结构:
buildPrompt({ trajectoryData, userStory, style }) {
const { metadata } = trajectoryData
const styleNames = {
literary: '文艺清新',
humorous: '轻松有趣',
motivational: '正能量'
}
return `你是一位朋友圈文案大师,擅长创作吸引人点赞的文案。
## 用户记录的内容
${userStory}
## 轨迹数据
- 地点:${metadata.name || '未知地点'}
- 距离:${(metadata.totalDistance/1000).toFixed(1)}公里
- 时长:${metadata.duration || '未知'}
## 文案风格
${styleNames[style]}
## 输出要求
1. 字数控制在100字以内
2. 语言自然流畅
3. 适当使用emoji增加活力
4. 文艺风格避免过度煽情
5. 幽默风格要有梗
请直接输出文案。`
}
3. 降级策略
为了保证用户体验,我实现了本地模板生成作为兜底方案:
generateLocalContent(trajectoryData, style, userStory) {
const templates = {
literary: [
'「${userStory}」\n\n在${place},我找到了属于自己的小确幸。\n\n${distance}公里,继续前行~ 📍 ${place}',
],
humorous: [
'救命!${userStory}\n\n顺带走了${distance}公里,今天步数排行榜第一!💪',
],
motivational: [
'${userStory}\n\n每一步都是风景,每一程都是成长。\n\n继续加油!💪',
]
}
return templates[style][0]
.replace('${userStory}', userStory)
.replace('${place}', trajectoryData.metadata.name)
.replace('${distance}', (trajectoryData.metadata.totalDistance/1000).toFixed(1))
}
传统的位置服务只提供数据展示能力,而我的项目实现了从数据到内容的转化:
我针对不同风格设计了差异化的 Prompt:
文艺风格 Prompt 特点:
幽默风格 Prompt 特点:
正能量风格 Prompt 特点:
async onGenerate() {
try {
// 尝试 AI 生成
const result = await this.callAIAPI(...)
this.setData({ story: result })
} catch (error) {
// AI 失败时,询问用户是否使用模板
wx.showModal({
title: 'AI生成遇到问题',
content: '是否使用本地模板生成?',
success: (res) => {
if (res.confirm) {
this.generateLocalContent()
}
}
})
}
}
周末和朋友一起去骑行,用 App 记录轨迹后,打开小程序生成一条文案:
今天的海边骑行太治愈了!海风超舒服,还看到了一群白鹭从海面上掠过~ 🌊🦢顺便走了28公里,今天也是努力的一天呢!
轨迹地图是可移动的

周末一个人在城市里乱逛,随手记录:
今天没有目的地,就是想走走。穿过老街小巷,吃了碗地道的竹升面,发现了一家藏在巷子里的独立书店。📍 东门老街 | 5.2公里

「轨迹故事生成器」是一个小而美的尝试,它展示了 AI + 地图的无限可能。
通过这个项目,我收获了:
更重要的是,它让我意识到:地图不仅仅是导航工具,它可以成为记录生活、表达情感的载体。
项目我上传到了GitHub,大家可以自行下载体验。https://github.com/w16638771062/txdt
在智慧出行零售选址物流调度等场景中,精准的地图服务已成为企业连接用户与线下空间的核心能力。腾讯位置服
在智慧零售物流调度城市治理等场景中,精准的地图制作能力直接影响业务效率与用户体验。腾讯位置服务依托多
作者: 一只牛博 发布时间: 于20260429 18:32:06发布 来源: https:bl