<p><em><a href="https://codepen.io/TabAtkins/pen/xepaqm">Original demo</a> and basically all JS by <a href="https://codepen.io/TabAtkins/">Tab Atkins</a></em></p>
<p>
<code>linear-gradient(90deg, blue, 33.3%, white 50%, 61.5%, #5050FF 75%, 84%, blue 93%)</code> vs. simulated <code>linear-gradient(90deg, blue, ease-in, white, ease-out, blue)</code>
</p>
<article>
<div id="d01"></div>
<canvas id="c01a" width=200 height=200></canvas>
<canvas id="c01b" width=200 height=200></canvas>
</article>
<p>
<code>linear-gradient(90deg, blue, 11.5%, #AFAFFF 25%, 34%, white 47%, white 54%, 83%, blue)</code> vs. simulated <code>linear-gradient(90deg, blue, ease-out, white, ease-in, blue)</code>
</p>
<article>
<div id="d02"></div>
<canvas id="c02a" width=200 height=200></canvas>
<canvas id="c02b" width=200 height=200></canvas>
</article>
<p>
<code>linear-gradient(90deg, blue, 5%, #ABABFF 18%, 23%, #DCDCFF 30%, 37%, white 46%, white 54%, 63%, #DCDCFF 70%, 77%, #ABABFF 82%, 89.5%, #5656FF 95%, 98.25%, blue)</code> vs. simulated <code>linear-gradient(90deg, blue, bezier(0,.42,.58,1), white, cubic-bezier(.42,0,1,.58), blue)</code>
</p>
<article>
<div id="d03"></div>
<canvas id="c03a" width=200 height=200></canvas>
<canvas id="c03b" width=200 height=200></canvas>
</article>
article, div, canvas, section {
display: block;
width: 1000px;
height: 50px;
margin: 0;
}
canvas {
display: inline;
width: 500px;
}
article {
display: flex;
flex-wrap: wrap;
height: auto;
padding: 10px 1px 1px;
margin-bottom: 1em;
background:
linear-gradient(90deg, #0008 1px, 1px, transparent) top left / 10% 100% repeat-x,
linear-gradient(90deg, #0003 1px, 1px, transparent) top left / 1% 100% repeat-x,
#EEE;
}
p {
margin-bottom: 0.25em;
}
code {
color: maroon;
background: #FDC;
}
/* ease-in | ease-out */
#d01 {
background: linear-gradient(90deg, blue, 33.3%, white 50%, 61.5%, #5050FF 75%, 84%, blue 93%);
}
/* ease-out | ease-in */
#d02 {
background: linear-gradient(90deg, blue, 11.5%, #AFAFFF 25%, 34%, white 46%, white 54%, 83%, blue);
}
/* bezier(0,.42,.58,1) | cubic-bezier(.42,0,1,.58) */
#d03 {
background: linear-gradient(90deg, blue, 5%, #ABABFF 18%, 23%, #DCDCFF 30%, 37%, white 46%, white 54%, 63%, #DCDCFF 70%, 77%, #ABABFF 82%, 89.5%, #5656FF 95%, 98.25%, blue);
}
const ease_in = [[.42, 0], [1, 1]]; // ease-in
const ease_out = [[0, 0], [.58, 1]]; // ease-out
const ease = [[0, .25], [.1, 1]]; // ease
const ease_in_out = [[0, .42], [.58, 1]]; // ease-in-out
const ease_out_in = [[.42, 0], [1, .58]]; // ease-in-out
class BezierMap {
constructor(p1, p2) {
this.points = [];
for(var i = 0; i <= 1000; i++ ) {
this.points.push(bezierPoint(i/1000, p1, p2));
}
}
get(x) {
if(x < 0 || x > 1) throw "In .get(x), x must be in [0,1]";
let prevPoint = null;
let nextPoint = this.points[0];
for(const p of this.points.slice(1)) {
[prevPoint, nextPoint] = [nextPoint, p];
if(p[0] > x) break;
}
const prog = (x-prevPoint[0]) / (nextPoint[0]/prevPoint[0]);
return linearNumber(prog, prevPoint[1], nextPoint[1]);
}
}
function bezierPoint(prog, p1, p2) {
const m1 = linearArray(prog, [0,0], p1);
const m2 = linearArray(prog, p1, p2);
const m3 = linearArray(prog, p2, [1,1]);
const n1 = linearArray(prog, m1, m2);
const n2 = linearArray(prog, m2, m3);
return linearArray(prog, n1, n2);
}
function linearArray(p, a1, a2) {
if(a1.length != a2.length) throw "In linearArray(x,y), x and y must be same length.";
return a1.map((e,i)=>linearNumber(p, e, a2[i]));
}
function linearNumber(p, a, b) {
const p_ = 1-p;
return p_*a + p*b;
}
function drawEasing(canvas, easing, start, end) {
const ctx = canvas.getContext("2d");
if (!start) var start = [0, 0, 1];
if (!end) var end = [1, 1, 1];
for(var i = 0; i < 200; i++) {
var prog = i/200;
var map = new BezierMap(...easing);
var colorProg = map.get(prog);
const color = linearArray(colorProg, start, end);
ctx.fillStyle = `rgb(${color.map(x=>x*100+"%").join(",")})`;
ctx.fillRect(i, 0, 1, 200);
}
}
drawEasing(document.querySelector("#c01a"), ease_in);
drawEasing(document.querySelector("#c01b"), ease_out, [1,1,1], [0,0,1]);
drawEasing(document.querySelector("#c02a"), ease_out);
drawEasing(document.querySelector("#c02b"), ease_in, [1,1,1], [0,0,1]);
drawEasing(document.querySelector("#c03a"), ease_in_out);
drawEasing(document.querySelector("#c03b"), ease_out_in, [1,1,1], [0,0,1]);
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.