微信小程序地图组件,根据行驶速度绘制彩虹线
彩虹线
可以自定义一段地图折线中的颜色值达到一条线段出现过个颜色的效果
小程序地图组件的踩红线参数
[图片]
效果演示:
[图片]
[图片]
甚至
[图片]
小程序代码片段
https://developers.weixin.qq.com/s/XwWhRhmW7UKc
测试数据
[图片]
waySpeed 一个记录行驶速度的数组 与记录点列表的长度相同
wayPath 记录点 经纬度
基本原理
使用HSL 色彩空间中的色相数值达到变换颜色的效果
起始颜色 速度最慢 红色
[图片]
结束颜色 速度最快 绿色
[图片]
只改变H 色相值 使饱和度和亮度保持不变时 颜色值表现出的色彩不同,但亮度和饱和度相同
[图片]
色相不同 但亮度 饱和度相同的三种颜色
[图片]
参考:
https://blog.csdn.net/qq_36984465/article/details/109715123
https://zhuanlan.zhihu.com/p/158524543
实现原理
计算速度的最大速度和最小速度的差值 得到速度区间
计算结束颜色减去起始颜色的差值
生成时计算当前速度在速度区间的占比 通过这个比值拿到应有的色相值进行取整
将这个色相与饱和度和亮度重新组成hsl颜色转为hex格式进行使用
代码片段
[代码]drawMap(){
const mapContext = wx.createMapContext('map')
// 拿到全部坐标点
let allPoints = this.data.wayPath.map(({latitude,longitude})=>{
return {
latitude: latitude, // 纬度
longitude:longitude // 经度
}
})
// 最大速度和最小速度
const minSpeed = parseFloat((Math.min(...this.data.waySpeed)).toFixed(2))
const maxSpeed = parseFloat(Math.max(...this.data.waySpeed).toFixed(2))
// 最小速度和最大速度的差值
const diffSpeed = maxSpeed - minSpeed
// 起始色相和终止色相
const startColorHsb = rgbToHsb(hexToRgb(this.data.minSpeedColor))
const endColorHsb = rgbToHsb(hexToRgb(this.data.maxSpeedColor))
// 色相差值 色相范围区间
const diffHue = endColorHsb[0] - startColorHsb[0]
// 最小色相
const minHue = startColorHsb[0]
// 生成整段路线的颜色列表
const colorList = this.data.waySpeed.map((speed, index)=>{
// 当前速度的占比
const ratioSpeed = parseFloat(((speed - minSpeed) / (minSpeed + diffSpeed)).toFixed(2))
// 当前色相
const hue = minHue + Math.round(Math.round(diffHue / 32) * Math.round(ratioSpeed*32))
// 颜色
return rgbToHex(hsbToRgb(...[hue, startColorHsb[1], startColorHsb[2]]))
})
// 地图中的全部折线
let polylines = []
// 拆分每段的个数
const splitCount = 31
// 拆分整个数组
for (let i = 0; i < allPoints.length; i += splitCount) {
const pointL = allPoints.slice(i, i + splitCount)
const nextP = allPoints[i + splitCount]
const colorL = colorList.slice(i, i + splitCount)
if(nextP){
pointL.push(nextP)
colorL.push(colorList[i + splitCount])
}
polylines.push({
// wayPolyline是一个模板对象 用于提供公用属性
...this.data.wayPolyline,
points: pointL,
colorList: colorL
});
}
// 绘制起点 终点
let startMarker = {
id: 10,
latitude: allPoints[0].latitude,
longitude: allPoints[0].longitude,
title: '起',
"aria-label": "起点",
width: '32px',
height: '32px',
iconPath: '/assets/icon/png/start-marker-icon.png'
}
const endPoint = allPoints[allPoints.length - 1]
let endMarker = {
id: 20,
latitude: endPoint.latitude,
longitude: endPoint.longitude,
title: '终',
"aria-label": "终点",
width: '32px',
height: '32px',
iconPath: '/assets/icon/png/end-marker-icon.png'
}
this.setData({
polyline: polylines,
markers: [startMarker,endMarker]
})
mapContext.includePoints({
points: allPoints,
padding: [90,30,30,30],
success: ()=>{
},
fail: (err)=>{
console.log("err",err)
}
})
},
[代码]
小程序中地图踩红线使用限制
colorList 最长只能有32的长度 超过32 安卓手机直接闪退,开发工具显示正常 所以需要将路径按照31进行拆分 再加上下一段中的第一个 否则会出现不连续的情况
最终效果
[图片]
欢迎 扫码体验骑行小程序 沿途A+ 更多好用功能正在努力开发中
[图片]
颜色转换工具函数
[代码]function hexToRgb(hex){
let sColor = hex.toLowerCase()
let sColorChange = []
for (let i=1; i<7; i+=2) {
sColorChange.push(parseInt("0x"+sColor.slice(i, i+2)));
}
return sColorChange
}
function rgbToHex(rgb){
var aColor = rgb.replace(/(?:\(|\)|rgb|RGB)*/g, "").split(",");
var strHex = "#";
for (var i=0; i<aColor.length; i++) {
var hex = Math.round(Number(aColor[i])).toString(16);
if (hex.length < 2) {
hex = '0' + hex;
}
strHex += hex;
}
return strHex
}
function rgbToHsb(arr) {
var h = 0, s = 0, v = 0;
var r = arr[0], g = arr[1], b = arr[2];
arr.sort(function (a, b) {
return a - b;
})
var max = arr[2]
var min = arr[0];
v = max / 255;
if (max === 0) {
s = 0;
} else {
s = 1 - (min / max);
}
if (max === min) {
h = 0;//事实上,max===min的时候,h无论为多少都无所谓
} else if (max === r && g >= b) {
h = 60 * ((g - b) / (max - min)) + 0;
} else if (max === r && g < b) {
h = 60 * ((g - b) / (max - min)) + 360
} else if (max === g) {
h = 60 * ((b - r) / (max - min)) + 120
} else if (max === b) {
h = 60 * ((r - g) / (max - min)) + 240
}
h = parseInt(h);
s = parseInt(s * 100);
v = parseInt(v * 100);
return [h, s, v]
}
function hsbToRgb(h, s, v) {
// var h = arr[0], s = arr[1], v = arr[2];
s = s / 100;
v = v / 100;
var r = 0, g = 0, b = 0;
var i = parseInt((h / 60) % 6);
var f = h / 60 - i;
var p = v * (1 - s);
var q = v * (1 - f * s);
var t = v * (1 - (1 - f) * s);
switch (i) {
case 0:
r = v; g = t; b = p;
break;
case 1:
r = q; g = v; b = p;
break;
case 2:
r = p; g = v; b = t;
break;
case 3:
r = p; g = q; b = v;
break;
case 4:
r = t; g = p; b = v;
break;
case 5:
r = v; g = p; b = q;
break;
default:
break;
}
r = parseInt(r * 255.0)
g = parseInt(g * 255.0)
b = parseInt(b * 255.0)
return `rgb(${r},${g},${b})`
}
function rangeMappingToColor(){
}
module.exports = {
hexToRgb,
rgbToHex,
rgbToHsb,
hsbToRgb,
}
[代码]