5

I'm creating a game with world where player can move.

And there is some GUI (eq, stats..) which has elements with no background (background is game world).

These elements have black text color, and my question is:

Can this text change to white when background'll be black, or can this text'll be always opposite color than background?

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
Brunon Blok
  • 199
  • 1
  • 9
  • 2
    Personal suggestion: use black text with a white outline – Feathercrown Dec 08 '16 at 14:52
  • 1
    [here is how to invert colors](http://stackoverflow.com/questions/9600295/automatically-change-text-color-to-assure-readability) – Kevin Kloet Dec 08 '16 at 14:52
  • Welcome to Stack Overflow! Please read [ask]. Key phrases: "Search, and research" and "Explain ... any difficulties that have prevented you from solving it yourself". – Heretic Monkey Dec 08 '16 at 14:58
  • So, are you talking about setting the text color based on arbitrary image background (*that dynamically changes for example as the background is animating*)? – Gabriele Petrioli Dec 08 '16 at 14:59
  • Black text with a white outline looks horrible, @GabyakaG.Petrioli Yes. When player moves he is in the same place all the time, but game objects are moving, so when black GUI text is on black game object it's unreadable. – Brunon Blok Dec 08 '16 at 15:15

3 Answers3

4

There is a css property that does exactly what you want, but support is a bit limited (no IE/Edge).

It is mix-blend-mode and using a value of difference yields very similar results to what you need. (many more modes supported).

The mix-blend-mode CSS property describes how an element's content should blend with the content of the element's direct parent and the element's background.

Relevant example:

html, body{height:100%}
.game {
  width: 100%;
  height: 100%;
  background:url('http://www.intrawallpaper.com/static/images/rainbow_texture679.jpg') 0% 50% no-repeat;
animation: moveBG 10s linear infinite;
}
.gui {
  color:grey;
  padding:25px;
  line-height:1.4;
  mix-blend-mode: difference;
}
@keyframes moveBG {
  0% {background-position: 0% 50%;}
 25% {background-position: 50% 0%;}
 50% {background-position: 100% 50%;}
 75% {background-position: 50% 100%;}
100% {background-position: 0% 50%;}
}
<div class="game">
  <div class="gui">
  Ellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Duis ornare metus sed justo pulvinar dapibus. Cras posuere leo quis semper lacinia. Pellentesque vitae ligula ut magna interdum tincidunt. Integer est velit, congue eget quam nec, feugiat malesuada nulla. Sed nisi lacus, pharetra mattis dapibus ac, hendrerit ac quam. Nulla facilisi.
  </div>
</div>

Alternatives to this (for wider support) would be the box-shadow trick that @Rourin posted (which could be combined with the mix-blend-mode for the best results), or repeating the CSS effect using a canvas element and applying the effect programmatically (but this is quite more involved and with heavier performance).

Community
  • 1
  • 1
Gabriele Petrioli
  • 191,379
  • 34
  • 261
  • 317
3

Its best not to invert because inverted colors also can be very unreadable or just very straining for the eyes.

Here is a really cool algorithm that automatically chooses the most legible text color based on background.

You can use this example in your game loop when you draw the frames and texts.

var c = document.getElementById('container');

var colourIsLight = function (r, g, b) {
  
  // Counting the perceptive luminance
  // human eye favors green color... 
  var a = 1 - (0.299 * r + 0.587 * g + 0.114 * b) / 255;
  return (a < 0.5);
}

var randomRgb = function () {
  var r = /* 189; //*/ Math.floor(Math.random() * 256);
  var g = /*60; //*/ Math.floor(Math.random() * 256);
  var b = /*151; //*/ Math.floor(Math.random() * 256);
  return [r, g, b];
};

var colourFromRgb = function (r, g, b) {
  return 'rgb(' + r + ',' + g + ',' + b + ')';
};

for (var i = 0; i < 1000; i += 1) {
  var el = document.createElement('div');
  el.setAttribute('class', 'box');
  el.textContent = "Hello";
  
  var bgRgb = randomRgb();
  var bgColour = colourFromRgb(bgRgb[0], bgRgb[1], bgRgb[2]);
  var textColour = colourIsLight(bgRgb[0], bgRgb[1], bgRgb[2]) ? 'black' : 'white';
  
  el.setAttribute('style', 'background-color: ' + bgColour + '; color: ' + textColour);
  
  c.appendChild(el);
}
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

#container {
  text-align: center;
}

.box {
  display: inline-block;
  vertical-align: top;
  text-align: center;
  width: 100px;
  height: 100px;
  line-height: 100px;
  font-size: 20px;
  font-family: sans-serif;
  font-weight: bold;
}
<div id="container"></div>

http://codepen.io/WebSeed/full/pvgqEq/

Timmetje
  • 7,641
  • 18
  • 36
  • It's helpful, thanks. But I don't know how to implement it to my game, this color changing must be for all document and in every frame, because e.g. player's stats are updating by js in every frame. – Brunon Blok Dec 08 '16 at 15:18
  • That's why in the game you add it in the game loop. You need to draw your GUI each frame too. `function run(running){drawBackground(); drawPlayer(); drawMonsters(); drawBullets(); drawGui();}` etc. and in the drawGui, you check out use bg values and the algorithm to draw gui. – Timmetje Dec 08 '16 at 15:53
1

You can use 4 text-shadows to give the black text a white outline.

Working Example:

.black {
display:inline-block;
position: absolute;
top: 0;
left: 0;
z-index: 0;
width: 100px;
height: 140px;
background-color: rgb(0,0,0);
transform: translateX(420px);
animation: slideLeft 6s linear infinite;
}

@keyframes slideLeft {
  0% {transform: translateX(420px);}
 50% {transform: translateX(0);}
100% {transform: translateX(420px);}
}

p {
position: relative;
z-index: 6;
font-size: 20px;
text-shadow:
1px 1px 1px rgb(255,255,255),
1px -1px 1px rgb(255,255,255),
-1px -1px 1px rgb(255,255,255),
-1px 1px 1px rgb(255,255,255);}
}
<p>This is Paragraph 1 - the text is black but it has a white outline.</p>
<p>This is Paragraph 2 - the text is black but it has a white outline.</p>
<p>This is Paragraph 3 - the text is black but it has a white outline.</p>

<div class="black">
</div>
Rounin
  • 27,134
  • 9
  • 83
  • 108