Algorithm for smooth alpha crossfade? - algorithm

My application fades between various media and text layers by adjusting their alpha values. However, when using a linear crossfade the brightness appears to "dip" halfway through and then fade back up. After some searching I found this answer that explains the issue, however the suggested solution, fading only one layer at a time, won't work for me since most of the layers I use already contain transparency.
Here's an example of the issue I'm having, in HTML/CSS (code below because SO requires it.
<style>
body, html {
width: 100%;
height: 100%;
margin: 0;
background-color: black;
}
.example {
position: absolute;
width: 100%;
height: 100%;
opacity: 0;
}
#example1 {
background-color: red;
animation: 1s linear 0s fade infinite alternate;
}
#example2 {
background-color: red;
animation: 1s linear 1s fade infinite alternate;
}
#keyframes fade {
from {opacity: 0;}
to {opacity: 1;}
}
</style>
<div id="example1" class="example"></div>
<div id="example2" class="example"></div>
The two divs should fade their opacities back in forth, resulting in a solid red image the entire time. Instead, it appears to dip in brightness.
What is the algorithm or formula for creating a smooth crossfade using alpha? I'm using OpenGL, if that's relevant. (The HTML/CSS snippet was just the easiest way of demonstrating the issue).

Sorry, but it's not possible.
First off, the equation you want is defined here. I'll copy it here in other terms:
outputColor = overAlpha * overColor + (1 - overAlpha) * underColor
If I understand your question correctly, you're looking for a periodic function f(t) for your alpha transition such that:
1 = f(t - 1) + (1 - f(t)) * f(t - 1) = f(t - 1) + f(t) - f(t - 1) * f(t)
The only function that satisfies that equation, at least according to wolfram alpha is the constant 1. And that won't work if you want it to be zero at the beginning, and have it loop infinitely.
Unless you don't want a periodic function, and you just want your fades to look kinda nice. The equation linked above.

There is some good discussion of this topic at this other question.
It's true that there is no perfect solution, other than a step function, but you can mitigate the effects somewhat. The important thing is to have easing functions that cross at a relatively "high" point, rather than at 0.5. See graphs at this answer.

Related

Is it possible to have a floating x-axis on a d3js grapgh?

Have a graph that is very long. And I have the x-axis on the top of the graph. Was wondering if it is possible to have a floating x-axis so when the user scrolls down the graph the x-axis stays on the screen for the user to see?
Thank you for your help
In most case in d3js,
developers create a single svg element. But you can separate them; eg. x/y axis and data drawing area. And then You can assign this svg field statically via css to be constant.
var axisSvg = d3js.select('axisSvg').append('svg').attr('class','axisSvg);
var mainSvg = d3js.select('mainSvg').append('svg').attr('class','maingSvg);
and in css
.axisSvg{
position: fixed;
bottom: 0;
right: 0;
width: 300px;
}

rotating svg elements around center

What am I doing wrong to rotate around center
I set transform-origin of each is right in the center of square
Look here pls
https://jsfiddle.net/yqx90or9/1/
group.style.transformOrigin = '100px 100px'
group.style.transform = 'rotate(90deg)'
The problem is this line:
transition: all 1s linear 1s;
When you change the style, you are changing the transform, but you are also changing the transform-origin. So both get animated. The result is your weird behaviour. Change it to:
transition: transform 1s linear 1s;

css: max-width or max-size

On my website I have images that have a width of 720 pixels. I want images to be either 95% of the width of the page (max-width: 95%), or 720px if the page width is too large. So, on larger screens, I don't want to blow them up. Is there a way to achieve this in CSS?
You can specify a width and a max-width. The element will respect the width, or shrink if max-width is smaller.
This behavior is described on the MDN.
It prevents the used value of the width property from becoming larger
than the value specified for max-width.
img {
background-color: grey;
border: 1px solid blue;
width: 400px; /* Ideal width */
max-width: 80%; /* Max width */
}
<img src="http://placehold.it/400x400">
Note as indicated in the other answer, you could set width to a percentage and max-width to pixels. The end result is the same: the calculated width of the image becomes the smallest of the two.
To me, specifying the width in pixels makes more sense semantically. After all, you want to have an image of so many pixels wide (related to the image itself), and want to have a constraint on the percentage for smaller screens. But if you write it the other way around, I won't hold it against you. ;-)
GolezTrol has it nearly right but just has the max-width and width values the wrong way round.
Below is the correct elements set as you require.
img {
width: 95%; /* Ideal width */
max-width: 720px; /* Max width */
}
<img src="http://placehold.it/800x800">
Max-width MDN Documentation
Width MDN Documentation

Random section of image to display

I have a large image roughly 2500px wide and 300px tall. I have saved 4 versions of this image:
left side
right side
left flipped
right flipped
Images are saved as follows.
img/Banner1.png
img/Banner2.png
img/Banner3.png
img/Banner4.png
var Num;
function gen(){
var x;
x = Math.floor(Math.random()*4+1);
Num = x;
while(Num == x){
Num = Math.floor(Math.random() * 3 + 1);
}
document.write("<style type='text/css'>");
document.write(".banner{");
document.write("background-image: url('img/Banner" + Num + ".png');");
document.write("background-position:left top, left bottom;");
document.write("background-repeat:repeat-x;");
document.write("-webkit-border-top-left-radius: 50px;");
document.write("-webkit-border-top-right-radius: 50px;");
document.write("-webkit-box-shadow: 0px 0px 5px 5px rgba(10, 10, 10, 0.5);");
document.write("-moz-box-shadow: 0px 0px 5px 5px rgba(10, 10, 10, 0.5);");
document.write("box-shadow: 0px 0px 5px 5px rgba(10, 10, 10, 0.5);");
document.write("border-bottom: 3px solid #505050;");
document.write("</style>");
}
gen();
Thus far you may have noticed there is no problem however this seems somewhat in-efficient. I am wondering if anyone has a recommendation for improvement in regards to performance.
Your code does not use Banner4.png. That's because Math.random() does exclude the value 1, so Math.random() is in [0,1), triple that and you are in [0,3), add one to get [1,4) and take the floor and you get {1,2,3}. So make that * 4 instead of * 3.
As Kevin already mentioned in a comment, your use of x seems unmotivated and bad performance-wise. You don't seem to be using its value, so you might as well avoid the loop and write
Num = Math.floor(Math.random() * 4 + 1);
as the first line of the function. You might also combine all those document.write calls into a single one, for a slight performance gain, but I'd guess the effect should be rather negligible. The effect by omitting the loop would be negligible as well, but there it would also make the code less confusing, which is a reason why I'd suggest that modification in any case. Otherwise, don't try to optimize for performance if it reduces maintainability, unless you know for sure that you have a reason to need optimization.

Retrieving SVG position in Firefox vs Chrome with viewBox set

I'm trying to get the left position of an svg element that has a viewBox set. The viewBox is basically a square, while the actual svg element is more rectangular. In most cases, this isn't a problem (and in Chrome, everything works fine), however, when trying to get the left position of the element within Firefox, as the viewBox is square, Firefox reports the left position of the viewBox rather than the svg element.
See http://jsfiddle.net/c6SW6/11/ for an example which should make things obvious.
Basically, in Chrome, the number reported for the left position is 8 This is the number that I want. In Firefox, it's reported as 108. How do I get Firefox to report the number 8 as well?
Code
HTML
<div>
<svg viewBox="0 0 100 100"><rect x=0 y=0 width=100 height=100></rect></svg>
</div>
<p>
</p>
CSS
div {
height: 100px;
width: 300px;
margin: 0;
padding: 0;
position: absolute;
top: 200px;
}
svg {
background-color: green;
height: 100%;
width: 100%;
}
JS
$('p').text($('svg').offset().left);
Assuming we gave the rect an id="r" attribute...
If you just want the offset of the rect in the svg itself then it's
$('p').text(document.getElementById("r").getCTM().e);
If you want the offset from the page origin instead...
Call rect.getBoundingClientRect() and the left and top will contain the answer
$('p').text(document.getElementById("r").getBoundingClientRect().left);
or alternatively rect.getScreenCTM() the e and f members of the result will be the answer
$('p').text(document.getElementById("r").getScreenCTM().e);
If you rotate the svg using a transform then you'll get different answers, getBoundingClientRect() will give you an unrotated bounding rect but getScreenCTM will give you a transformed offset, since you're not doing that you can use either currently.
The 8 is the difference, i.e. the position of the element element on the page. That's not consistent with the description but if you want 8 then it's:
$('p').text(document.getElementById("r").getScreenCTM().e -
document.getElementById("r").getCTM().e);

Resources