Reputation: 5235
I have a code that generates color from values ( from 0 to 200% )
Actually the specter is Green-yellow-red.
I would like to change the gradient to Green-Grey-Red : green if percentage < 100% , grey if in 100% field, red if > 100%.
I don't see how to do it using mathematics formula.
window.onload = function() {
let colorShower = document.querySelector('.color-shower')
let colorSlider = document.querySelector('#colorSlider')
let percentage = (200 -colorSlider.value) /2
let buildColor = (capHue) => `hsl(${capHue},90%,60%)`
colorShower.style.backgroundColor = buildColor(percentage)
colorSlider.addEventListener('input', e => {
percentage = (200 -colorSlider.value) /2
colorShower.style.backgroundColor = buildColor(percentage)
})
}
.color-shower {
width: 100%;
height: 50px;
}
.color-slider {
width: 100%;
}
<div class = "color-shower"></div>
<input type = "range" min = "1" max = "200" value = "1" class = "color-slider" id = "colorSlider">
Upvotes: 0
Views: 73
Reputation: 48600
Edit: OK, I updated my response with a dynamic solution. I created wrapper <div>
elements around the display/input elements. These wrappers allow you to define both a start-hue
and end-hue
data attribute. These are used as the gradient start/end for the display.
It's easy to miss (since you have to scroll all the way to the bottom), but with the plugin below; you can call GradientSlider()
after your page loads.
The "static" default properties are at the bottom of the function definition. This can easily be re-written into an ES5/6 class.
GradientSlider.defaultOptions = {
selector : '.gradient-slider'
};
Various sliders are created below. I borrowed Infodev's absolute-value trick to adjust the saturation value as the slider approaches and 50%.
function GradientSlider(options) {
let opts = Object.assign({}, GradientSlider.defaultOptions, options);
construct(opts.selector); // Begin...
function construct(selector) {
Array.from(document.querySelectorAll(selector))
.forEach(gradientSlider => initializeSlider(gradientSlider));
}
function initializeSlider(gradientSlider) {
let hueStart = parseInt(gradientSlider.getAttribute('data-start-hue'), 10);
let hueEnd = parseInt(gradientSlider.getAttribute('data-end-hue'), 10);
let display = gradientSlider.querySelector('.gradient-slider-display');
let slider = gradientSlider.querySelector('.gradient-slider-input');
slider.addEventListener('input', onSliderChange);
let percentage = getSliderPercentage(slider);
let hue = percentage < 50 ? hueStart : hueEnd;
display.style.backgroundColor = calculateColor(hue, percentage);
}
function onSliderChange(e) {
let gradientSlider = e.target.parentElement;
let hueStart = parseInt(gradientSlider.getAttribute('data-start-hue'), 10);
let hueEnd = parseInt(gradientSlider.getAttribute('data-end-hue'), 10);
let display = gradientSlider.querySelector('.gradient-slider-display');
let percentage = getSliderPercentage(e.target);
let hue = percentage < 50 ? hueStart : hueEnd;
display.style.backgroundColor = calculateColor(hue, percentage)
}
function calculateColor(hue, percentage) {
return `hsl(${hue}, ${Math.abs(50 - percentage)}%, 50%)`;
}
function getSliderPercentage(slider) {
let value = parseInt(slider.value, 10);
let minValue = parseInt(slider.getAttribute('min'), 10);
let maxValue = parseInt(slider.getAttribute('max'), 10);
return scaleBetween(value, 0, 100, minValue, maxValue);
}
// Source: https://stackoverflow.com/a/60514474/1762224
function scaleBetween(n, tMin, tMax, sMin, sMax) {
return (tMax - tMin) * (n - sMin) / (sMax - sMin) + tMin;
}
}
GradientSlider.defaultOptions = {
selector : '.gradient-slider'
};
GradientSlider(); // Call the plugin...
.gradient-slider,
.gradient-slider > .gradient-slider-display,
.gradient-slider > .gradient-slider-input {
width: 100%;
}
.gradient-slider-display {
height: 50px;
}
<div class="gradient-slider" data-start-hue="120" data-end-hue="0">
<div class="gradient-slider-display"></div>
<input class="gradient-slider-input" type="range" min="1" max="200" value="1" />
</div>
<div class="gradient-slider" data-start-hue="240" data-end-hue="300">
<div class="gradient-slider-display"></div>
<input class="gradient-slider-input" type="range" min="50" max="150" value="75" />
</div>
<div class="gradient-slider" data-start-hue="30" data-end-hue="180">
<div class="gradient-slider-display"></div>
<input class="gradient-slider-input" type="range" min="0" max="10" value="7" />
</div>
Upvotes: 1
Reputation: 5235
I have found the solution but it's not perfect
Using this formulahsl(${hue}, ${Math.abs(100 - perc)}%, 50%)
;
window.onload = function() {
let colorShower = document.querySelector('.color-shower')
let colorSlider = document.querySelector('#colorSlider')
let percentage = (200 -colorSlider.value) /2
let buildColor = (capHue) => `hsl(${capHue}, ${Math.abs(100 - colorSlider.value)}%, 50%)`
colorShower.style.backgroundColor = buildColor(percentage)
colorSlider.addEventListener('input', e => {
percentage = (200 -colorSlider.value) /2
colorShower.style.backgroundColor = buildColor(percentage)
})
}
.color-shower {
width: 100%;
height: 50px;
}
.color-slider {
width: 100%;
}
<div class = "color-shower"></div>
<input type = "range" min = "1" max = "200" value = "1" class = "color-slider" id = "colorSlider">
But I still have some orange.
Upvotes: 1