Home > Blockchain >  how would I go about making a color generator that returns a color within two specified colors? And
how would I go about making a color generator that returns a color within two specified colors? And

Time:12-11

Keeping the example basic, let's say I take red (#FF0000) and green (#00FF00) and want to generate a basic color between these WITHOUT generating any colors below its "brightness". In other words, only colors horizontally between red and green with no vertical deviation if that makes sense. The same would go for darker colors; if I choose a low brightness, only colors of equally low brightness would be generated. It would be a function that would take at least 3 separate arguments; color1, color2, brightness. How could I approach something like this?

Otherwise, if "brightness" as an argument is still not specific enough (since I lack a good understanding of hex colors), then at the very least a function that takes only 100% brightness into consideration.

I have looked into a lot of posts already with similar questions, but I haven't come across one that spoke about this specifically. The closest post I found was this one.. But what I was looking for was not there.

Edit: Here is what I mean by "horizontally" and "vertically", random image from google

CodePudding user response:

Given the link you provided in the comments, of what appears to be an HSLA color picker, you want to generate a color that is between red and green on the first box of the picker horizontally (hue) but at the same vertical position (light) and same positions on the saturation and alpha sliders.

  • Red - #FF0000 is equivalent to hsl(0deg 100% 50%)
  • Green - #00FF00 is equivalent to hsl(120deg 100% 50%)

So essentially what you want is a color with a hue between 0 and 120 degrees, with saturation and light both fixed at 100 percent and 50 percent respectively.


Translating this into RGB becomes a little less intuitive, but what you want is a range of all the RGB colors with hues in between those of #FF0000 and #00FF00 but with the same saturation and brightness values.

You can keep the brightness and saturation constant in this case by only allowing the R and G values to change and keeping at least one of them maxed out.

So your color range can have either:

  • FF 00-FF 00
  • 00-FF FF 00

CodePudding user response:

Given that the HSL looks like the color space that better fits this scenario:

https://developer.mozilla.org/en-US/docs/Web/CSS/color_value/hsl

An approach to your problem could be to have two colors expressed in hsl having both the fixed lightness of 50%.

Than when you wish to find the color in between the two, it's just a matter of calculating the average of their two color parts (hue and saturation) and have the third part (lightness) arbitrary selected.

I made a demo where you can pick color1 and color2 choosing their hue and saturation with a range slider. When you click on the Blend button, the resulting color will be calculated and from there you'll be in the position to fine tune its lightness.

There are several units you can use for hue, saturation and brightness. I chose turn for hue because it has the range 0-1 and % for saturation and lightness.

//add the event listener to color1 and color2 range sliders
document.querySelectorAll('.color.input input[type=range]')
  .forEach(range => {
     range.addEventListener('change', (event)=>{
        const range = event.target;
        const parent = range.closest('.color');
        refresh(parent);
      });
    });

document.querySelector('#color3 #lightness')
  .addEventListener('change', (event)=>{
     blend();
  });

document.addEventListener('DOMContentLoaded', ()=>{
  refresh( document.getElementById('color1') );
  refresh( document.getElementById('color2') );
});

//refresh the color status for the given color container
function refresh(color){

  //hue is expressed in turns (value between 0 and 1)
  const hue = 0.01 * color.querySelector('.hue').value;
  //saturation is expressed as % (value between 0% and 100%)
  const saturation = color.querySelector('.saturation').value;
  //lightness on the input color is fixed (%)
  const lightness = 50;
  
  const hsl = getHSL(hue, saturation, lightness);
  color.dataset.hsl = hsl;
  color.dataset.hue = hue;
  color.dataset.saturation = saturation;
  color.dataset.lightness = lightness;
  
  color.querySelector('.hsl').innerText = hsl;
  color.querySelector('.colorshow').style.background = hsl;
}

function getHSL(hue, saturation, lightness){
  return `hsl(${hue.toFixed(2)}turn ${saturation}% ${lightness}%)`;
}

//calculate the average between color1 and color2 and sets the color3
function blend(){
  const ds1 = document.getElementById('color1').dataset;
  const ds2 = document.getElementById('color2').dataset;
  const hue = (parseFloat(ds1.hue)   parseFloat(ds2.hue)) / 2;
  const saturation = (parseFloat(ds1.saturation)   parseFloat(ds2.saturation)) / 2;
  const lightness = document.getElementById('lightness').value;
  const hsl = getHSL(hue, saturation, lightness);
  document.querySelector('#color3 .hsl').innerText = hsl;
  document.querySelector('#color3 .colorshow').style.background = hsl;
}
.container{
  display: flex;
}

.color{
  width: 25%;
  border: solid;
  display: flex;
  flex-flow: column;
  margin-right: 1rem;
  padding: 1rem;
}

.color > *{
  display:block;
}

.color > p{
  margin: 0 0 1rem 0;
  border-bottom: solid 1px lightgray;
}

.colorshow{
  width: 100%;
  min-height: 50px;
  border: solid 1px lightgray;
  margin-top: 10px;
  box-sizing: border-box;
  flex: 1 1 auto;
}

.hsl{
  font-size: 1rem;
  border: solid lightgray;
  padding: 0 .25rem;
}

button{
  margin-right: 1rem;
  display: block;
  
}
<div >

  <div id="color1" >
    <p>Color 1</p>
    <div ></div>
    <div ></div>
    <label for="hue">Hue:</label>
    <input type="range" id="hue1"  min="0" max="100">
    <label for="saturation">Saturation:</label>
    <input type="range" id="saturation1"  min="0" max="100">
  </div>
  
  <div id="color2" >
    <p>Color 2</p>
    <div ></div>
    <div ></div>
    <label for="hue">Hue:</label>
    <input type="range" id="hue2"  min="0" max="100">
    <label for="saturation">Saturation:</label>
    <input type="range" id="saturation2"  min="0" max="100">
  </div>
  
  <button onclick="blend();">Blend</button>
  
  <div id="color3" >
      <p>Color result</p>
      <div ></div>
      <div ></div>
      <label for="saturation">Lightness:</label>
    <input type="range" id="lightness" min="0" max="100">
  </div>
  
</div>

  • Related