将数据可视化为 Javascript 中的颜色条

Visualize Data as Color Bar in Javascript

我正在尝试使用纯 JS 创建数据可视化。我找不到任何不依赖第三方库的示例来说明如何执行此操作。

假设您有一些数据:

data = {
  green = 20%;
  yellow = 30%;
  red = 50%;
}

并且您已经在 HTML 中创建了一个可以填充颜色的矩形。

如何用JS根据每种颜色的百分比填充颜色?正如您将在下面的代码中看到的,现在我只是硬编码了颜色百分比。但我希望它是动态的,以便在数据更改时更新。

这是我目前的情况:

const drawColors = () => {
  const colorBar = document.getElementById("color-bar");
  const context = colorBar.getContext('2d');

  // Hard coding percentages
  context.beginPath();
  context.fillStyle = "green";
  context.fillRect(0, 0, 100, 100);

  context.fillStyle = "yellow"
  context.fillRect(100, 0, 100, 100);

  context.fillStyle = "red"
  context.fillRect(200, 0, 100, 100);
}

drawColors();
<canvas id="color-bar" width="300" height="100">

假设您在其他地方验证百分比值总和为 100,遍历百分比对象并像这样填充:

const percentages = {
  green: 50,
  yellow: 30,
  red: 20
}

const drawColors = () => {
  const colorBar = document.getElementById("color-bar")
  const context = colorBar.getContext('2d')
  //Calculate pixels from percentage based on canvas width.
  const toPixels = percentage => (percentage*colorBar.width)/100

  context.beginPath()
  let addedColors = 0 //To set the starting point of each fill.
  
  Object.keys(percentages).forEach(color => {
    let widthToPaint = toPixels(percentages[color])
    context.fillStyle = color
    context.fillRect(addedColors, 0, widthToPaint , 100)
    addedColors+= widthToPaint
  })
}

drawColors()
<canvas id="color-bar" width="300" height="100">

为此我们可以使用 createLinearGradient()。刚刚将 20% 转换为 0.2 等(总和必须为 1 或更少);

data = {
    green : 0.2,
    yellow : 0.3,
    red : 0.5
}

drawColorBar('canvas',data);

function drawColorBar(selector, data){
    const canvas = document.querySelector(selector);
    const ctx = canvas.getContext('2d');
    
    const gradient = ctx.createLinearGradient(0,0,canvas.width,0);
    let start = 0;
    for(const color in data){
        gradient.addColorStop(start, color);
        start += data[color];
        gradient.addColorStop(start, color);
    }
    
    ctx.fillStyle = gradient;
    ctx.fillRect(0,0,canvas.width,canvas.height);
}
<canvas></canvas>