uniapp结合Canvas+renderjs根据经纬度绘制轨迹
文章目录
- 根据官方建议要想在
app-vue
流畅使用Canvas
动画,需要使用renderjs
技术,把操作canvas
的js逻辑放到视图层运行,避免逻辑层和视图层频繁通信。 - 这里呢结合
renderjs
技术实现绘制轨迹图形。
你可能需要先了解renderjs
如何数据通讯:renderjs 与 app-vue之间数据交互
效果图
template
coordsAll
监听数据变化,只要coordsAll
数据改变,就是触发initData
方法。
html
<template>
<view class="map-track-wrap">
<!-- xxx -->
<view class="track-list" :prop="coordsAll" :change:prop="canvas.initData">
<!-- xxx -->
<view class="d-flex canvas-box">
<canvas class="canvas" :class="`canvas${index}`"></canvas>
</view>
</view>
</view>
</template>
renderjs
javascript
<script module="canvas" lang="renderjs">
export default {
methods: {
initData() {
for (let i = 0; i < this.coordsAll.length; i++) {
// 绘制图形
this.draw(this.coordsAll[i], i);
}
},
draw(locationList, idx) {
let canvasHeight = 72,
canvasWidth = 72,
canvasEle = document.querySelectorAll(`.canvas${idx}>canvas`)[0],
ctx = canvasEle.getContext('2d'),
amuXArr = [],
amuYArr = []
for (let i = 0; i < locationList.length; i++) {
amuXArr.push(locationList[i].lat);
amuYArr.push(locationList[i].lng);
}
amuYArr = amuYArr.map((item) => {
return item * -1;
});
let xMax = Math.max(...amuXArr);
let xMin = Math.min(...amuXArr);
let yMax = Math.max(...amuYArr);
let yMin = Math.min(...amuYArr);
let xScale = canvasWidth / (xMax - xMin);
let yScale = canvasHeight / (yMax - yMin);
let scale = xScale < yScale ? xScale : yScale;
let xoffset = (canvasWidth - (xMax - xMin) * scale) / 2;
let yoffset = (canvasHeight - (yMax - yMin) * scale) / 2;
ctx.save(); // 保存状态
ctx.translate(0, canvasHeight);
ctx.rotate(-Math.PI / 2);
ctx.beginPath();
// 根据偏移量移动点位并画图
ctx.moveTo(
(amuXArr[0] - xMin) * scale + xoffset,
(yMax - amuYArr[0]) * scale + yoffset
);
for (let i = 1; i < amuXArr.length; i++) {
ctx.lineTo(
(amuXArr[i] - xMin) * scale + xoffset,
(yMax - amuYArr[i]) * scale + yoffset
);
}
ctx.strokeStyle = '#1FE298';
ctx.stroke();
ctx.restore(); // 恢复状态
}
}
}
</script>
js
renderjs
中不支持uni.request
,所以请求后台获取数据操作在script
中进行,然后监听
参数变化,将参数传递过来进行渲染。
javascript
searchList() {
// 处理数据
let list = this.dataList;
if (list.length > 0) {
for(let i = 0; i < list.length; i++) {
let tmpLocation = list[i].locations;
// 页面监听 coordsAll,把数据传递renderjs,会触发 initData 方法
this.coordsAll.push(JSON.parse(tmpLocation));
}
}
}
数据结构
- 测试数据,具体根据个人所需处理数据
json
[
{
locations: [
{
"lng": 113.980502,
"lat": 22.54161
},
{
"lng": 113.972839,
"lat": 22.533976
},
{
"lng": 113.98925,
"lat": 22.524669
},
{
"lng": 113.990034,
"lat": 22.537097
},
{
"lng": 114.00916,
"lat": 22.534477
}
]
},
{
locations: [
{
"lng": 113.924271,
"lat": 22.537654
},
{
"lng": 113.9367,
"lat": 22.532806
},
{
"lng": 113.928494,
"lat": 22.518594
},
{
"lng": 113.942673,
"lat": 22.524502
},
{
"lng": 113.944302,
"lat": 22.538601
}
]
},
{
locations: [
{
"lng": 113.98049,
"lat": 22.54301
},
{
"lng": 114.06374,
"lat": 22.51134
},
{
"lng": 114.06259,
"lat": 22.50951
},
{
"lng": 114.06178,
"lat": 22.51031
},
{
"lng": 113.96047,
"lat": 22.54611
}
]
}
]