cesium制作自己的骑行轨迹
制作自己的骑行轨迹
马上国庆节了,计划骑车回家,突然想到把所有的骑行线路汇总一下,无奈码表和APP不支持这样的操作,出于职业病,在此操作一下。
我用的是黑鸟码表,可以导出fit运动轨迹,但是fit还需要转gpx格式才能读取,否在二进制无法读取。想到在官网也可以看骑行记录,做为一名开发,我嗅到了可以从官网的个人中心去爬取骑行数据,比直接读取文件更为方便和快捷。
效果
链接地址 壮壮壮壮壮的骑行记录。
获取轨迹数据
登陆
登陆黑鸟官网,右上角进入个人中心
查单条数据
F12打开开发人员选项后,随便点击一条骑行记录进入详情,查看网络选项卡,找到请求骑行数据的请求,做为GISer,对经纬度格外敏感,看到38,114就知道这是需要的数据了。
提取骑行数据
提取骑行数据,postman里测试,设置请求头的Cookie,成功请求到数据。各个网站验证可能是不一样的,有的用Cookie,有的用Token,有的用Authorization,酌情而定。
记住请求地址中的关键信息 56135240
,推测此为记录ID,后面肯定会在列表中存在。
http://www.blackbirdsport.com/api/records/
56135240
/data
提取骑行列表
提取骑行列表,返回上一页,查看网络选项卡,找到请求骑行列表的数据,在记录里找到recordID,和前面查询具体数据的关键字一致,那么就可以准备爬下所有数据了。
postman测试地址,正常返回所有数据。http://www.blackbirdsport.com/api/records?lastRecordId=0&pageSize=25
末尾的 pageSize=25
改为 pageSize=100
一次爬取100条数据,小菜腿还没骑够100次。
爬取
java爬取,数据输出到控制台,复制保存好,接下来前台会用到,至此,数据爬取已经完成。
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
/**
* 获取黑鸟的行车行车数据
* @author lizhuang
* @date 2021/9/9 14:00
*/
public class GetBickRecord {
public static void main(String[] args) {
String detailUrl = "http://www.blackbirdsport.com/api/records/{}/data";
String listUrl = "http://www.blackbirdsport.com/api/records?lastRecordId=0&pageSize=100";
String cookie = "xxxxxx";//自己在网站上获取的cookie
String strRes = HttpRequest.get(listUrl).header("Cookie",cookie).execute().body();
JSONObject o = JSONUtil.parseObj(strRes);
JSONArray list = o.getJSONArray("content");
JSONArray jSONArray = new JSONArray();
for (int i = 0; i < list.size(); i++) {
JSONObject obj = list.getJSONObject(i);
String temp = StrUtil.format(detailUrl, obj.getStr("recordId"));
String strData = HttpRequest.get(temp).header("Cookie",cookie).execute().body();
String[] track = JSONUtil.parseObj(strData).getJSONObject("content").getStr("track").split(";");
JSONArray j = new JSONArray();
StringBuilder sb = new StringBuilder();
try {
Thread.sleep(1000);
}catch (Exception e){
}
for (int i1 = 0; i1 < track.length; i1++) {
String[] s1 = track[i1].split(",");
JSONArray json = new JSONArray();
json.add(s1[0]);
json.add(s1[1]);
json.add(s1[2]);
j.add(json);
}
jSONArray.add(j);
}
System.out.println(jSONArray.toString());
}
}
页面制作
2102年了,当然要三维了。
关于展示想法
想做成骑行次数越多的线路颜色越亮,最好在加上动态效果,也就OD线可以实现了。
矢量地图和影像地图切换,采用百度暗色系矢量地图和天地图影像,天地图加载速度时快时慢,其他互联网影像精度不够,国外大厂又被墙了,只能用天地图了。
关于地形,加载了地形后,发现OD线不能贴地,像要贴地只能改为普通线,暂时把地形去掉了,后面想到好方法再往上加吧。
地形+普通线贴地的效果图
代码
直接上代码吧,前台使用cesium,采用百度暗色系底图,线条采用OD线。
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<!-- <title>骑行记录</title> -->
<!-- 0 引入js文件:XbsjEarth.js和vue.min.js -->
<script src="../lib/XbsjEarth/XbsjEarth.js"></script>
<!-- <script src="http://earthsdk.com/v/last/XbsjEarth/XbsjEarth.js"></script> -->
<script src="./scripts/vue.min.js"></script>
<!-- <script src="http://earthsdk.com/v/last/Apps/Examples/scripts/vue.min.js"></script> -->
<style>
html,
body {
width: 100%;
height: 100%;
margin: 0px;
padding: 0px;
overflow: hidden;
}
</style>
</head>
<body>
<div id="vueApp" style="width: 100%; height: 100%; background: grey; position: relative;">
<earth-comp></earth-comp>
</div>
<script>
function switchMap(){
earth.sceneTree.root.children[1].enabled = !earth.sceneTree.root.children[1].enabled
}
function loadData(dataFunc) {
var data = [[["38.07765", "114.53156"], ["38.07769", "114.53156"]]] //'此处为上面java代码System.out.println()输出的数据,三位数组'
var timeDuration = 10.0;
var moveBaseDuration = 4.0;
var hStep = 300 / (data.length - 1);
var busLines = [];
data.map(function (busLine, idx) {
var points = [];
busLine.map(function (item, idx) {
if (Cesium.Math.toRadians(item[1]) != 0) {
// points.push([Cesium.Math.toRadians(item[1]), Cesium.Math.toRadians(item[0]),item[2]]) 此为添加z值的数据(x,y,z)
points.push([Cesium.Math.toRadians(item[1]), Cesium.Math.toRadians(item[0])]) // 仅有x,y
}
})
busLines.push({
positions: points,
color: [Math.random() * 0.5 + 0.5, Math.random() * 0.8 + 0.2, 0.0, 1.0],
width: 2.0,
startTime: timeDuration * Math.random(),
duration: moveBaseDuration + 1.0 * Math.random()
});
});
console.log('busLines', busLines)
dataFunc(busLines, timeDuration);
}
// 1 创建Earth的vue组件
var EarthComp = {
template: `
<div style="width: 100%; height: 100%">
<div ref="earthContainer" style="width: 100%; height: 100%">
</div>
<div style=" position: absolute; z-index: 99; display: inline-block; left: 2%; top: 2%;">
<button style=" width: 130px; height: 40px; color: #fff; border-radius: 5px; padding: 10px 25px; font-family: 'Lato', sans-serif; font-weight: 500; background: transparent; cursor: pointer; transition: all 0.3s ease; position: relative; display: inline-block; box-shadow: inset 2px 2px 2px 0px rgb(255 255 255 / 50%), 7px 7px 20px 0px rgb(0 0 0 / 10%), 4px 4px 5px 0px rgb(0 0 0 / 10%); outline: none;" onclick="switchMap()">切换地图</button>
</div>
</div>
`,
data() {
return {
_earth: undefined, // 注意:Earth和Cesium的相关变量放在vue中,必须使用下划线作为前缀!
_bgImagery: undefined,
fps: 0,
elapsedTime: 0
};
},
// 1.1 资源创建
mounted() {
// 1.1.1 创建地球
var earth = new XE.Earth(this.$refs.earthContainer);
// 1.1.2 添加默认地球影像
earth.sceneTree.root = {
"children": [
{
"czmObject": {
"xbsjType": "Imagery",
"xbsjImageryProvider": {
"XbsjImageryProvider": {
"url": "http://map.geoq.cn/arcgis/rest/services/ChinaOnlineStreetPurplishBlue/MapServer/tile/{z}/{y}/{x}",
}
}
}
},
{
"czmObject": {
"xbsjType": "Imagery",
"xbsjImageryProvider": {
"XbsjImageryProvider": {
"url": "http://t6.tianditu.com/DataServer?T=img_w&x={x}&y={y}&l={z}&tk=2cda5caa13d033e23a39407fc62accdb",
"dstCoordType": "GCJ02"
}
}
}
},
/** 中国14级地形
{
"czmObject": {
"xbsjType": "Terrain",
"xbsjTerrainProvider": {
"type": "XbsjCesiumTerrainProvider",
"XbsjCesiumTerrainProvider": {
"url": "http://lab.earthsdk.com/terrain/577fd5b0ac1f11e99dbd8fd044883638",
"requestVertexNormals": true,
"requestWaterMask": true
}
}
}
}
*/
]
}
earth.sceneTree.root.children[1].enabled = false
earth._viewer.camera.flyTo({
destination: new Cesium.Cartesian3(-2102351.020236049, 4605886.135770324, 3909950.0555654215),
orientation: {
heading: 6.270938378736673,
pitch: -0.8989671219533877,
roll: 6.282706587562512
},
duration: 3
});
this._odlines = new XE.Obj.ODLines(earth);
this._odlines.translucentPass = false;
this._odlines.color = [1, 1, 1, 1];
window.earth = earth
window.odlines = this._odlines
loadData((data, timeDuration) => {
this._odlines.data = data;
this._odlines.timeDuration = timeDuration;
this._odlines.playing = true;
});
},
// 1.2 资源销毁
beforeDestroy() {
// vue程序销毁时,需要清理相关资源
this._fpsUnbind = this._fpsUnbind && this._fpsUnbind();
this._elapsedTimeUnbind = this._elapsedTimeUnbind && this._elapsedTimeUnbind();
this._earth = this._earth && this._earth.destroy();
},
}
// 2 创建vue程序
// XE.ready()用来加载Cesium.js等相关资源
XE.ready().then(() => {
var app = new Vue({
el: '#vueApp',
components: {
EarthComp,
},
});
});
</script>
</body>
</html>
不足
OD线效果在手机浏览器里无法显示,后面想办法解决一下 地形 + 贴地、移动端适配的问题。
原文地址
cesium制作自己的骑行轨迹的更多相关文章
- 使用python进行运动轨迹合并:多次骑行跑步轨迹叠加显示
现有各种各样的运动app.运动手表手环以及gps码表等可以用于记录日常骑行或跑步等运动轨迹;但轨迹显示多数只限于显示一天的轨迹,经过搜索只发现一篇文章介绍跑步轨迹叠加方法(查看),根据教程尝试了下还因 ...
- 智能头盔 "Livall携全球首款智能骑行头盔亮相CES"
LIVALL是全球首创集音乐.通讯.智能灯光为一体的智能骑行头盔的研发者,日前Livall携旗下智能骑行头盔BH 100和BH 60参展CES 2017,这也是目前世全球首款智能骑行头盔类产品,同时亮 ...
- 黑鸟码表BB10S骑行记录导入行者
前言 开始骑车用行者app记录, 后来觉得每次都要开app很麻烦, 于是在骑友的推荐下入手了黑鸟BB10S, 使用了一段时间感觉还不错, 不过也遇到之前大家说的问题, 黑鸟不支持直接导出fit文件, ...
- 2876: [Noi2012]骑行川藏 - BZOJ
Description 蛋蛋非常热衷于挑战自我,今年暑假他准备沿川藏线骑着自行车从成都前往拉萨.川藏线的沿途有着非常美丽的风景,但在这一路上也有着很多的艰难险阻,路况变化多端,而蛋蛋的体力十分有限,因 ...
- bzoj 2876: [Noi2012]骑行川藏 拉格朗日数乘
2876: [Noi2012]骑行川藏 Time Limit: 20 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 1033 Solved: ...
- 高等数学(拉格朗日乘子法):NOI 2012 骑行川藏
[NOI2012] 骑行川藏 输入文件:bicycling.in 输出文件:bicycling.out 评测插件 时间限制:1 s 内存限制:128 MB NOI2012 Day1 Des ...
- bzoj2876 [Noi2012]骑行川藏
Description 蛋蛋非常热衷于挑战自我,今年暑假他准备沿川藏线骑着自行车从成都前往拉萨.川藏线的沿途有着非常美丽的风景,但在这一路上也有着很多的艰难险阻,路况变化多端,而蛋蛋的体力十分有限,因 ...
- bzoj2876 [NOI2012]骑行川藏(拉格朗日乘数法)
题目描述 蛋蛋非常热衷于挑战自我,今年暑假他准备沿川藏线骑着自行车从成都前往拉萨.川藏线的沿途有着非常美丽的风景,但在这一路上也有着很多的艰难险阻,路况变化多端,而蛋蛋的体力十分有限,因此在每天的骑行 ...
- BZOJ 2876 【NOI2012】 骑行川藏
题目链接:骑行川藏 听说这道题需要一些高数知识 于是膜了一发dalao的题解……然后就没了…… 不要吐槽我的精度TAT……eps设太小了就TLE,大了就Wa……我二分的边界是对着数据卡的…… 下面贴代 ...
随机推荐
- 修改 CubeMX 生成的 RT-Thread makefile 工程
修改 CubeMX 生成的 RT-Thread makefile 工程 使用 RT-Thread 官方 基于 CubeMX 移植 RT-Thread Nano 生成的 Makefile 工程在编译时有 ...
- 在PHP中检测一个类是否可以被foreach遍历
在PHP中,我们可以非常简单的判断一个变量是什么类型,也可以非常方便的确定一个数组的长度从而决定这个数组是否可以遍历.那么类呢?我们要如何知道这个类是否可以通过 foreach 来进行遍历呢?其实,P ...
- Java基础系列(7)- 标识符和关键字
关键字 标识符 Java所有的组成部分都需要名字.类名.变量名.方法名都称为标识符 首字母以字母(A-Z或者a-z),美元符号($),或者下划线(_)开头 首字母之后可以用字母.美元符号.下划线.数字 ...
- LR集合点策略
给大家分享一个LR集合点策略,跑并发脚本时,一定要设置策略,要不然得出的响应时间无意义.默认选择第一个(当所有虚拟用户中的x % 到达集合点进释放,即仅当指定百分比的虚拟用户到达集合点时,才释放虚拟用 ...
- P4922-[MtOI2018]崩坏3?非酋之战!【dp】
正题 题目链接:https://www.luogu.com.cn/problem/P4922 题目大意 题目好长直接放了 在崩坏 3 中有一个叫做天命基地的地方,女武神们将在基地中开派对与敌人们厮杀. ...
- 从0到1告诉你搭建完整Python+requests接口自动化测试框架!
前言 很多小伙伴不知道什么是框架?框架有哪些东西? 一步步从需求分析到报告生成告诉你如何搭自动化建框架. 学完unittest后这里基本上可以搭建一个简易的项目框架了,我们可以用一条run_main. ...
- 基于深度学习的建筑能耗预测02——安装Tensorflow-gpu
一.检查显卡 ·查看自己的显卡配置是否能支持cuda,以及Tensorflow不同版本要求与CUDA及CUDNN版本对应关系: https://developer.nvidia.com/zh-cn/c ...
- IP多播与NAT地址转化
IP多播 与单播相比,在一对多的通信中,多播可以大大减少网络资源.在互联网上进行多播就叫做IP多播,IP多播所传送的分组需要使用IP多播地址. 如果某台主机想要收到某个特定的多播分组,那么怎样才能是这 ...
- FastAPI(54)- 详解 Request 请求对象
背景 前面讲了可以自定义 Response,那么这里就讲下请求对象 Request 可以通过 Request 来获取一些数据 获取请求基础信息 @app.get("/base") ...
- 踩坑系列《一》数据库建表权限 CREATE command denied to user for table
今天在表中用Navicat连接服务器上的mysql账号进行建表,报了个这样类似的错, CREATE command denied to user for table 是数据库权限设置的问题,所以无法进 ...