Canvas热力图颜色通过归一化数据值映射到RGB或HSL空间动态计算,采用分段线性插值与预生成256级LUT优化性能。

Canvas热力图的颜色梯度不是靠预设图片或CSS渐变,而是通过数值映射到RGB(或HSL)空间动态计算出来的。核心在于:把数据强度值(0~1归一化后)映射为平滑、可读、符合视觉感知的颜色序列。
归一化数据值到[0, 1]区间
原始热力数据(如点击次数、密度值)通常是非均匀分布的。直接用原始值做颜色映射会导致大部分区域偏暗或偏亮。必须先做归一化:
- 找出全局最小值 min 和最大值 max(可选:用百分位数如5%~95%截断异常值)
- 对每个点的原始值 v,计算:t = (v - min) / (max - min),确保 t ∈ [0, 1]
- 若 v < min,设 t = 0;若 v > max,设 t = 1
定义关键色标并线性插值(Lerp)
常见热力图使用4~5个锚点色(如蓝→青→黄→橙→红),每个对应一个归一化位置(通常是等距或自定义分布)。算法本质是分段线性插值:
- 定义色标数组,例如:[[0, 'rgb(0,0,255)'], [0.25, 'rgb(0,255,255)'], [0.5, 'rgb(0,255,0)'], [0.75, 'rgb(255,255,0)'], [1, 'rgb(255,0,0)']]
- 对当前 t,找到它所在的两个相邻锚点(t0, c0)和(t1, c1)
- 计算插值权重:w = (t - t0) / (t1 - t0)
- 分别对R、G、B通道做线性插值:r = r0 + w * (r1 - r0),同理算g、b
用HSL空间实现更自然的渐变
RGB线性插值在黄色→红色段易出现灰浊感。改用HSL(色相/饱和度/亮度)插值更符合人眼感知:
立即学习“前端免费学习笔记(深入)”;
- 将各锚点RGB转为HSL(可用标准转换公式,注意H∈[0,360),S/L∈[0,1])
- 对H通道,需处理跨0°/360°问题(如从350°插值到10°,应走短弧:+20°而非-340°)
- 对S和L直接线性插值即可;最后再转回RGB用于fillStyle或putImageData
- 示例:蓝(240°,1,0.5)→红(0°,1,0.5),H插值时把0°视为360°,按240→360→0路径过渡更顺滑
优化性能:预生成颜色查找表(LUT)
每帧对成千上万个像素实时计算HSL→RGB开销大。实际项目中建议预先生成256级LUT:
- 创建长度为256的Uint8ClampedArray或普通数组
- 对i = 0…255,计算 t = i / 255,查表得对应RGB三元组,存入lut[i] = [r,g,b]
- 渲染时,对每个像素的归一化值t,取索引 idx = Math.round(t * 255),查表得颜色,避免重复计算
- 支持快速写入ImageData:data[off] = r; data[off+1] = g; data[off+2] = b; data[off+3] = 255;



















