I'm trying to create a data visualization with pure JS. I can't find any examples of how to do this that don't rely on third-party libraries.
Let's say you have some data:
data = {
green = 20%;
yellow = 30%;
red = 50%;
}
And you have created a rectangle in HTML that you can fill with color.
How can I use JS to fill the colors according to the percentage of each color? As you'll see in my code below, right now I've just hard-coded in the color percentages. But I want it to be dynamic so it updates when the data changes.
Here's what I have so far:
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">
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
Assuming you validate somewhere else that percentages values all add up to 100, iterate through the percentages object and fill like this:
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">
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
CodePudding user response:
We can use createLinearGradient()
for this. Just converted 20% to 0.2 etc (sum has to be 1 or less);
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>
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>