5

Basically, I'm generating a random graph with D3.js and I would like to generate a random fill-color and border-color for each node, the border color has to be a shade of the fill color. I'm currently using something like this to generate random fill-color:

randomColor() {
  const r = () => Math.floor(256 * Math.random());
  return  {color: `rgb(${r()}, ${r()}, ${r()})`, border: `rgb(${r()}, ${r()}, ${r()})`};
}

But the border is also random so it's not linked with the main color.

Thanks in advance.

Daniel_Knights
  • 7,940
  • 4
  • 21
  • 49
ryuzak1
  • 234
  • 3
  • 14
  • I would try generating the primary color first, getting the R/G/B values, and then literally dividing or multiplying the primary color by a number to get another shade. For example if your first color is `100,120,130`, you could divide by 2 to get `50,60,65`. Try that and let me know if it makes sense at all. – TKoL Aug 10 '20 at 08:48
  • Multiplying would only work, btw, if you limit the multiple so that the biggest number in the primary color could never go above 256. Dividing is probably the better option, but I'm not super confident about it. – TKoL Aug 10 '20 at 08:49
  • does [this answer](https://stackoverflow.com/questions/5560248/programmatically-lighten-or-darken-a-hex-color-or-rgb-and-blend-colors) help or [this answer](https://stackoverflow.com/questions/40619476/javascript-generate-different-shades-of-the-same-color) – Jannes Carpentier Aug 10 '20 at 08:55
  • I suggest looking at this [answer](https://stackoverflow.com/a/1351485/7368985) and mixing the main color with white to make it lighter or black to make it darker. – M0nst3R Aug 10 '20 at 09:05

5 Answers5

2

You just have to keep the chosen RGB values randomly generated and divide them by a ratio, 2 here:

function randomColor() {
  const rnd = () => Math.floor(256 * Math.random());
  let r = rnd(), g = rnd(), b = rnd(),
      r2 = parseInt(r / 2), g2 = parseInt(g / 2), b2 = parseInt(b / 2);
  return  {color: `rgb(${r}, ${g}, ${b})`, border: `rgb(${r2}, ${g2}, ${b2})`};
}

let style = randomColor();

document.getElementById('test').style.backgroundColor = style.color;
document.getElementById('test').style.borderColor = style.border;
#test {
  border: 5px solid white;
}
<div id="test">TEST</div>
Kaddath
  • 5,933
  • 1
  • 9
  • 23
1

Save the values to an array and alter those values directly in the border property of the returned object:

const color = randomColor();

function randomColor() {
  const r = () => Math.floor(256 * Math.random());
  const rgb = [r(), r(), r()];
  return {
    color: `rgb(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`,
    border: `rgb(${rgb[0] - 50}, ${rgb[1] - 50}, ${rgb[2] - 50})`
  };
}

document.querySelector('div').style.color = color.color;
document.querySelector('div').style.border = '1px solid ' + color.border;

console.log(color);
<div>I am a div</div>

rgb defaults to 0 if a negative value is passed in so you don't have to worry about conditional checking.

Daniel_Knights
  • 7,940
  • 4
  • 21
  • 49
0

You can use this :

function randomColor() {
  const r = () => Math.floor(256 * Math.random());
  let rVal = r();
  let gVal = r();
  let bVal = r();
  let diff = r() + 1;
  return {
    color: `rgb(${rVal}, ${gVal}, ${bVal})`,
    border: `rgb(${(rVal + diff) % 255}, ${(gVal + diff) % 255}, ${(bVal + diff) % 255})`
  };
}
Pranav Rustagi
  • 2,604
  • 1
  • 5
  • 18
0

adding to the other answers... maybe something with a configurable hsl? since h is your basecolor you can change the other two vaules pretty randomly ;)

function randomColor(sat = '100%', lum1 = '50%', lum2 = '30%') {
  const h = Math.floor(360 * Math.random());
  return {
    color: `hsl(${h}, ${sat}, ${lum1}`,
    border: `hsl(${h}, ${sat}, ${lum2})`
  };
}

const color = randomColor();

document.querySelector('div').style.backgroundColor = color.color;
document.querySelector('div').style.borderColor = color.border;

console.log(color);
#test {
  border: 5px solid white;
}
<div id="test">I am a div</div>
Argee
  • 1,216
  • 1
  • 12
  • 22
0

You can consider CSS to help you with this task using the brightness filter where you need to generate only one color per element:

A simplified example:

$('.box').each(function() {
  $(this).css('color', randomColor());
})

function randomColor() {
  const r = Math.floor(200 * Math.random()) + 30;
  const g = Math.floor(200 * Math.random()) + 30;
  const b = Math.floor(200 * Math.random()) + 30;
  return `rgb(${r}, ${g}, ${b})`;
}
.box {
  display: inline-block;
  width: 100px;
  height: 100px;
  margin: 10px;
  position: relative;
  padding: 10px;
  background: currentColor;
}

.box::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  border: 12px solid;
  filter: brightness(0.6);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
<div class="box"></div>
Temani Afif
  • 245,468
  • 26
  • 309
  • 415