Reputation: 1446
For a project I am attempting to make my own linear gradient code. And I have managed to come quite far, however, it is not perfect. Some places the gradient is not looking as it should.
See the following code where the colorStops are the stops in the gradient. It is supposed to show a gradient in between red, yellow and green as in a traffic light.
gradientSlider = {
colorStops: ["#b30000", "#ffff1a", "#00e600"],
minValue: 0,
maxValue: 100,
init: function(canvas) {
this.canvas = canvas;
this.ctx = canvas.getContext("2d");
this.width = canvas.width;
this.height = canvas.height;
this.colors = this.calculateHexColorForStep();
this.draw();
},
draw: function() {
pixelWidth = this.width / this.maxValue;
for (i = 0; i < this.maxValue; i++) {
this.ctx.beginPath();
this.ctx.rect(i * pixelWidth, 0, pixelWidth, this.height);
this.ctx.fillStyle = this.colors[i];
this.ctx.fill();
}
},
calculateHexColorForStep: function() {
result = [];
stepsPerGradient = this.maxValue / (this.colorStops.length - 1);
for (i = 0; i < this.colorStops.length - 1; i++) {
percentIncrease = 100 / stepsPerGradient / 100;
firstColor = this.colorStops[i];
targetColor = this.colorStops[i + 1];
firstColorDecArray = this.tools.parseColor(firstColor);
targetColorDecArray = this.tools.parseColor(targetColor);
for (j = 0; j <= stepsPerGradient; j++) {
if (j == 0) {
result.push(firstColor);
} else if (j == stepsPerGradient) {
result.push(targetColor);
} else {
stepColorDecArray = [firstColorDecArray[0] + (percentIncrease * j) * (targetColorDecArray[0] - firstColorDecArray[0]),
firstColorDecArray[1] + (percentIncrease * j) * (targetColorDecArray[1] - firstColorDecArray[1]),
firstColorDecArray[2] + (percentIncrease * j) * (targetColorDecArray[2] - firstColorDecArray[2])
];
result.push(this.tools.decimalToHex(stepColorDecArray));
}
}
}
return result;
},
tools: {
parseColor: function(hexColorString) {
var m;
m = hexColorString.match(/^#([0-9a-f]{6})$/i)[1];
if (m) {
return [parseInt(m.substring(0, 2), 16), parseInt(m.substring(2, 4), 16), parseInt(m.substring(4, 6), 16)];
}
},
decimalToHex: function(decimalNumberArray) {
//TODO fikse tall under ti - alltid to plasser
var results = [];
results[1] = Math.round(decimalNumberArray[0]).toString(16);
results[2] = Math.round(decimalNumberArray[1]).toString(16);
results[3] = Math.round(decimalNumberArray[2]).toString(16);
for (var i = 1; i <= results.length; i++) {
if (!(isNaN(results[i]))) {
if (results[i] < 10) {
results[i] = "0" + results[i];
}
}
}
return "#" + results[1] + results[2] + results[3];
}
}
}
//get the canvas element
var canvasElm = document.querySelector("canvas");
//initialize the slider
gradientSlider.init(canvasElm);
<canvas id="gradient-slider" width="600" height="200" class="gradientslider"></canvas>
Upvotes: 0
Views: 116
Reputation: 36
My solution is a fixed version of the function tools.decimalToHex. The error was that you treat the results array as an array of numbers, instead of an array of strings.
decimalToHex : function(decimalNumberArray){
var results = [];
// Maybe check if number is in range 0 - 255, before converting to string?
results[0] = Math.round(decimalNumberArray[0]).toString(16);
results[1] = Math.round(decimalNumberArray[1]).toString(16);
results[2] = Math.round(decimalNumberArray[2]).toString(16);
for (var i = 0; i<results.length; i++) {
if(results[i].length < 2) {
results[i] = "0" + results[i];
}
}
return "#" + results[0] + results[1] + results[2];
}
Corresponding jsFiddle: https://jsfiddle.net/8xr4zujj/4/
Upvotes: 2