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"
xmlns:xlink="http://www.w3.org/1999/xlink"
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>