微信小程序地圖組件,根據(jù)行駛速度繪制彩虹線, js顏色轉(zhuǎn)換
微信小程序地圖組件,根據(jù)行駛速度繪制彩虹線
彩虹線
可以自定義一段地圖折線中的顏色值達(dá)到一條線段出現(xiàn)過(guò)個(gè)顏色的效果
小程序地圖組件的踩紅線參數(shù)

效果演示:


甚至

小程序代碼片段 [源碼]
https://developers.weixin.qq.com/s/XwWhRhmW7UKc
測(cè)試數(shù)據(jù)?

waySpeed 一個(gè)記錄行駛速度的數(shù)組 與記錄點(diǎn)列表的長(zhǎng)度相同
wayPath 記錄點(diǎn) 經(jīng)緯度
基本原理
使用HSL 色彩空間中的色相數(shù)值達(dá)到變換顏色的效果
起始顏色 速度最慢 紅色

結(jié)束顏色 速度最快 綠色

只改變H 色相值 使飽和度和亮度保持不變時(shí) 顏色值表現(xiàn)出的色彩不同,但亮度和飽和度相同

色相不同 但亮度 飽和度相同的三種顏色

參考:
https://blog.csdn.net/qq_36984465/article/details/109715123
https://zhuanlan.zhihu.com/p/158524543
實(shí)現(xiàn)原理
計(jì)算速度的最大速度和最小速度的差值 得到速度區(qū)間
計(jì)算結(jié)束顏色減去起始顏色的差值
生成時(shí)計(jì)算當(dāng)前速度在速度區(qū)間的占比 通過(guò)這個(gè)比值拿到應(yīng)有的色相值進(jìn)行取整
將這個(gè)色相與飽和度和亮度重新組成hsl顏色轉(zhuǎn)為hex格式進(jìn)行使用
代碼片段
drawMap(){
? ? ? ? const mapContext = wx.createMapContext('map')
?
? ? ? ? ? ? // 拿到全部坐標(biāo)點(diǎn)
? ? ? ? let allPoints = this.data.wayPath.map(({latitude,longitude})=>{
? ? ? ??
? ? ? ? ? ? return {
? ? ? ? ? ? ? ? latitude: latitude, // 緯度
? ? ? ? ? ? ? ? longitude:longitude // 經(jīng)度
? ? ? ? ? ? }
? ? ? ? })
? ? ? ? // 最大速度和最小速度
? ? ? ? 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))
? ? ? ? // 色相差值 色相范圍區(qū)間?
? ? ? ? const diffHue = endColorHsb[0] - startColorHsb[0]
? ? ? ? // 最小色相
? ? ? ? const minHue = startColorHsb[0]
? ? ? ??
? ? ? ? // 生成整段路線的顏色列表
? ? ? ? const colorList = this.data.waySpeed.map((speed, index)=>{
? ? ? ? ? ? // 當(dāng)前速度的占比
? ? ? ? ? ? const ratioSpeed = parseFloat(((speed - minSpeed) / (minSpeed + diffSpeed)).toFixed(2))
? ? ? ? ? ? // 當(dāng)前色相
? ? ? ? ? ? const hue = minHue + Math.round(Math.round(diffHue / 32) * Math.round(ratioSpeed*32))
? ? ? ? ? ? // 顏色
? ? ? ? ? ? return rgbToHex(hsbToRgb(...[hue, startColorHsb[1], startColorHsb[2]]))
? ? ? ? ? ??
? ? ? ? })
? ? // 地圖中的全部折線
? ? let polylines = []
? ? // 拆分每段的個(gè)數(shù)
? ? const splitCount = 31
? ? // 拆分整個(gè)數(shù)組
? ? 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是一個(gè)模板對(duì)象 用于提供公用屬性
? ? ? ? ? ? ...this.data.wayPolyline,
? ? ? ? ? ? points: pointL,
? ? ? ? ? ? colorList: colorL
? ? ? ? });
? ? }
?
? ? // 繪制起點(diǎn) 終點(diǎn)
? ? ? ? let startMarker = {
? ? ? ? ? ? id: 10,
? ? ? ? ? ? latitude: allPoints[0].latitude,
? ? ? ? ? ? longitude: allPoints[0].longitude,
? ? ? ? ? ? title: '起',
? ? ? ? ? ? "aria-label": "起點(diǎn)",
? ? ? ? ? ? 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": "終點(diǎn)",
? ? ? ? ? ? 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 最長(zhǎng)只能有32的長(zhǎng)度 超過(guò)32 安卓手機(jī)直接閃退,開(kāi)發(fā)工具顯示正常 所以需要將路徑按照31進(jìn)行拆分 再加上下一段中的第一個(gè) 否則會(huì)出現(xiàn)不連續(xù)的情況
最終效果

歡迎 掃碼體驗(yàn)騎行小程序 沿途A+ 更多好用功能正在努力開(kāi)發(fā)中

顏色轉(zhuǎn)換工具函數(shù)
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;//事實(shí)上,max===min的時(shí)候,h無(wú)論為多少都無(wú)所謂
? ? } 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},$)`
}
function rangeMappingToColor(){
}
module.exports = {
? ? hexToRgb,
? ? rgbToHex,
? ? rgbToHsb,
? ? hsbToRgb,
}
?