# Function to set opacities of two objects so that the resultant opacity is constant

I have two objects, F and G with opacities f(x) and g(x), respectively. Opacity is defined such that F is fully transparent when f(x) is 0, and fully opaque when f(x) is 1. x goes from 0 to 1. For simplicity, g(x) is f(1 - x), so that only one function needs to be defined.

F is composited on top of G such that the resultant opacity is f(x) + (1 - f(x)) g(x), i.e. f(x) + (1 - f(x)) f(1 - x).

How can I find f(x) so that the resultant opacity is constant?

Background:

These objects are SVG text strings for a clock animation. F is the current time and G is the time at the previous second. I want to smoothly fade in G while fading out F. The resultant opacity has to be kept constant so that the rest of the text e.g. digits that haven't changed appear static, and not appear to flicker once a second.

By trial and error, I've found f(x) = 1 - 2 ^ (2x - 2) works and implemented it in the code below, but am curious to learn if there is a method to generate a general answer.

One drawback of my f(x) is that at x = 0, f(0) is 0.75, so the text is not fully opaque. Is there any way for f(0), and thus the resultant combination, to be fully opaque? Thanks!

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg"
width="100%" height="100%" viewBox="-250 -60 500 50" onload="main(evt)">
<title>SVG Clock</title>
<script type="text/ecmascript">
var seconds_integer_old = -1;
var obj_time, obj_time_old;
function opacity(x) { return 1 - Math.pow(2, 2 * x - 2); }
function run() {
var date = new Date();
var time = date.getTime();
var seconds_fraction = time * 0.001;
var seconds_integer = Math.floor(seconds_fraction);
seconds_fraction -= seconds_integer;
obj_time.setAttribute('opacity', opacity(1 - seconds_fraction));
obj_time_old.setAttribute('opacity', opacity(seconds_fraction));
if (seconds_integer_old != seconds_integer) {
obj_time_old.textContent = obj_time.textContent;
obj_time.textContent = date.toString().match(/\d\d:\d\d:\d\d/);
seconds_integer_old = seconds_integer;
}
setTimeout(run, 100); // 10 fps
}
window.run = run;
function main(evt) {
obj_time      = evt.target.ownerDocument.getElementById('time');
obj_time_old  = evt.target.ownerDocument.getElementById('time_old');
run();
}
</script>
<g font-family="monospace" font-weight="bold" font-size="100"
letter-spacing="-10" text-anchor="middle" stroke="none" fill="#000000">
<text id="time"     x="0" y="0"></text>
<text id="time_old" x="0" y="0"></text>
</g>
</svg>

-
Normally if you stack two objects, the transmissibilities are multiplied, so it would be $f(x)(1-f(x))$ –  Ross Millikan Sep 24 '12 at 13:31
@RossMillikan: Sorry, I don't understand; where does g(x) go in that expression? –  Gnubie Sep 25 '12 at 12:18
You said $g(x)=1-f(x)$ so it is the second term. If that isn't given, the opacity would be just $f(x)g(x)$ –  Ross Millikan Sep 25 '12 at 12:56
@RossMillikan: I see, thanks. If that's the case, how do I still go about making the resultant opacity constant? –  Gnubie Sep 29 '12 at 22:14
If you want it constant, you will need a different $g(x)$. The easy by setting $g(x)=0$, when nothing will be transmitted. If you want a target of $0.5$, you would have to have $f$ only range from $0.5$ to $1$, as multiplying by $g$ can only reduce it. Then $g(x)=\frac {0.5}{f(x)}$ will make it constant. –  Ross Millikan Sep 30 '12 at 16:18