如何用原生Canvas实现单值数组的渐变色热力线?
原生Canvas实现单条彩色热力线
实现思路
- 数值归一化:将原始数值映射到0-1区间,便于统一计算颜色。
- 颜色映射:将0-1的归一化值转换为对应色彩,白色代表0,数值越高颜色越深。
- 绘制热力线:通过绘制连续的彩色矩形块(或粗线条)实现热力线效果。
完整实现代码
HTML
<canvas id="myCanvas" width="800" height="50"></canvas>
JavaScript
var values = [0, 4, 44, 11, 55, 2, 6, 0, 0, 0, 0, 0, 0, 3, 2, 4, 2, 22, 55, 6, 44, 34, 56, 26, 87, 93, 112, 115, 45, 6] // 数值归一化函数,处理0-1区间映射 function normalize(min, max) { var delta = max - min; return function(val) { return delta === 0 ? 0 : (val - min) / delta; // 避免所有数值相同时除以0 }; } // 执行归一化 const normalizedValues = values.map(normalize(Math.min(...values), Math.max(...values))); // 颜色转换函数:归一化值→颜色,0对应白色,值越高颜色越深 function getColor(normalizedVal) { // 使用HSL色彩空间,固定色相为红色系,亮度随数值升高降低 const brightness = 100 - normalizedVal * 80; return `hsl(0, 50%, ${brightness}%)`; // 若需要从白到黑的渐变,替换为以下代码: // const brightness = 100 - normalizedVal * 100; // return `hsl(0, 0%, ${brightness}%)`; } // 获取Canvas上下文 var canvas = document.querySelector('#myCanvas'), ctx = canvas.getContext('2d'); const canvasWidth = canvas.width; const canvasHeight = canvas.height; const segmentCount = normalizedValues.length; const segmentWidth = canvasWidth / segmentCount; // 绘制热力线(色块模式) normalizedValues.forEach((val, index) => { const x = index * segmentWidth; ctx.fillStyle = getColor(val); ctx.fillRect(x, 0, segmentWidth, canvasHeight); }); // 若需要线条模式,替换上述绘制代码为以下内容: /* normalizedValues.forEach((val, index) => { const x = index * segmentWidth; ctx.beginPath(); ctx.moveTo(x, canvasHeight / 2); ctx.lineTo(x + segmentWidth, canvasHeight / 2); ctx.strokeStyle = getColor(val); ctx.lineWidth = canvasHeight; // 用粗线条模拟色块效果 ctx.stroke(); }); */
关键细节说明
- 归一化容错处理:增加了
delta === 0的判断,避免所有数值相同时出现除以0的错误。 - 颜色自定义:可通过修改
getColor函数的HSL参数调整色彩风格,比如更换色相(如200对应蓝色系)、饱和度,或切换为RGB模式。 - 绘制模式选择:默认采用色块模式,视觉效果更直观;线条模式适合需要更"线感"的场景,通过调整
lineWidth控制线条粗细。
内容的提问来源于stack exchange,提问作者Toniq
相关产品推荐
相关产品推荐

