Skip to main content
kulss
Inspiring
May 19, 2023
Answered

Expression to change color of a text based on background

  • May 19, 2023
  • 3 replies
  • 4795 views

Hi there!

I have this situation where I want to have a text that changes its color between white and black depending on the background shape layer. Let's say:

  • If background is yellow, text is black

  • If background is red, text is white

I'm pretty sure I could do it with an if/else statement, but I'm not sure how to make it work on After Effects.

Thank you!

This topic has been closed for replies.
Correct answer Dan Ebberts

Down below you can find the HEX values I am using and the color that the text should be.

 

#4266F5 - White
#AD7DF9 - White
#3B6F88 - White
#2F8343 - White
#A51A3D - White
#A10400 - White
#EF464A - White
#77A8FA - Black
#FF6F3C - Black
#FF9A33 - Black
#FFC41F - Black
#91C949 - Black
#36C188 - Black
#64CEE1 - Black

 

 

Thing is that, with the expression you already wrote but using 0.52 instead, all background colors match with their text color except of #FF6F3C, which is White instead of Black.

bg = thisComp.layer("Pill").content("Rectangle 1").content("Fill 1").color;
bg[1] > .52 ? 0 : 100

 

I'm not sure if something like "if color is (all the HEX Values that need to have white text), text = white // else = black" could be done in this situation 🧐

 

Thank you for your time, Dan! 🙌


In that case, if you know all the exact hex values, you could do something like this, where you check against a list of colors where you want white, and if it's not one of those you get black (same set up as before):

whites = [0x4266F5, 0xAD7DF9, 0x3B6F88, 0x2F8343, 0xA51A3D, 0xA10400, 0xEF464A];

function colorToHex(theColor){
  var r = Math.round(theColor[0]*255);
  var g = Math.round(theColor[1]*255);
  var b = Math.round(theColor[2]*255);
  return (r*65536 + g*256 + b)
}

bg = thisComp.layer("Background").content("Rectangle 1").content("Fill 1").color;
hexColor = colorToHex(bg);
white = false;
for (i = 0; i < whites.length; i++){
  if (hexColor == whites[i]){
    white = true;
    break;
  }
}
white ? 100 : 0

3 replies

Community Expert
May 22, 2023

I have done similar things by using the Luminance value of the sampled background to switch fill colors. I convert the RGBA sample you get from sampleImage(point) to HSL, then just query the 3rd variable in the generated array. You could do the same with Hue if you like. It might simplify things if you knew a hue range.

 

Here's a simple expression that changes from white to gray when the background sample layer gets darker.

 

ref = thisComp.layer("Sample Me");
s = ref.sampleImage([960, 540]);
l = rgbToHsl(s);

if (l[2] < .5)
	[1, 1, 1, 1]
else
	[.3, .3, .3, 1]

 

ShiveringCactus
Community Expert
Community Expert
May 20, 2023

While you can use an Expression and I see Dan has provided one, you don't need to do anything as complicated.  You can do exactly what you're asking by using a transfer mode.

Use White Text and a White shape with a white background but set the text's and shape's tranfer mode to Difference.  You can then use an adjustment layer to change the background colours and a second one with it's track matte set to the text to change the colours of the text:

 

kulss
kulssAuthor
Inspiring
May 22, 2023

Hi ShiveringCactus! 

 

Appreciate your answer, I'll make sure to give it a try whenever I have to go through the same issue again. In this case, I was looking for an expression as it's not for a project of mine, but a MOGRT.

 

I wanted to turn this into a MOGRT so editors can use it without overcomplicating their workflow and having to explain new things for every new asset, even though maybe this overcomplicated my process a bit, but that's my job I guess haha

Dan Ebberts
Community Expert
Community Expert
May 19, 2023

The trick is to figure out how to dectect yellow vs. red. One way, I guess, would be to check the value of the green channel. So you could create black text, add a Fill Color Animator and set it to white, and add something like this to the Amount property of the Range Selector:

bg = thisComp.layer("Background").content("Rectangle 1").content("Fill 1").color;
bg[1] > .25 ? 0 : 100
kulss
kulssAuthor
Inspiring
May 19, 2023

Hi Dan!

 

I tried that and it is indeed working! What I see is that in order to define a bit better which colors make the text white or black, I have to manipulate de .25 part, isn't it?

 

Thank you so much!

Dan Ebberts
Community Expert
Community Expert
May 19, 2023

Yes, when you pick up the background color, you end up with the red, green, and blue channel values as floating point values between 0.0 and 1.0. So it can get tricky if you're looking for an exact hex value, for example. In the red vs. yellow example, I picked .25 for the green channel because red wouldn't have much (if any) green, but .5 might be better, because that would be half way between pure red and pure yellow. But if you're looking for a specific hex value, you might need a more complex expression that checks for a small range of values within each color channel. I could probably give you a better answer if you have a specific example in mind.