Some checks failed
Build & Deploy / 🔍 Prepare (push) Successful in 20s
Build & Deploy / 🧪 QA (push) Failing after 34s
Build & Deploy / 🏗️ Build (push) Has started running
Build & Deploy / 🚀 Deploy (push) Has been cancelled
Build & Deploy / 🧪 Smoke Test (push) Has been cancelled
Build & Deploy / ⚡ Lighthouse (push) Has been cancelled
Build & Deploy / 🔔 Notify (push) Has been cancelled
48 lines
1.7 KiB
Plaintext
48 lines
1.7 KiB
Plaintext
import { mixNumber } from './number.mjs';
|
|
import { warning } from 'motion-utils';
|
|
import { hslaToRgba } from '../hsla-to-rgba.mjs';
|
|
import { hex } from '../../value/types/color/hex.mjs';
|
|
import { rgba } from '../../value/types/color/rgba.mjs';
|
|
import { hsla } from '../../value/types/color/hsla.mjs';
|
|
import { mixImmediate } from './immediate.mjs';
|
|
|
|
// Linear color space blending
|
|
// Explained https://www.youtube.com/watch?v=LKnqECcg6Gw
|
|
// Demonstrated http://codepen.io/osublake/pen/xGVVaN
|
|
const mixLinearColor = (from, to, v) => {
|
|
const fromExpo = from * from;
|
|
const expo = v * (to * to - fromExpo) + fromExpo;
|
|
return expo < 0 ? 0 : Math.sqrt(expo);
|
|
};
|
|
const colorTypes = [hex, rgba, hsla];
|
|
const getColorType = (v) => colorTypes.find((type) => type.test(v));
|
|
function asRGBA(color) {
|
|
const type = getColorType(color);
|
|
warning(Boolean(type), `'${color}' is not an animatable color. Use the equivalent color code instead.`);
|
|
if (!Boolean(type))
|
|
return false;
|
|
let model = type.parse(color);
|
|
if (type === hsla) {
|
|
// TODO Remove this cast - needed since Motion's stricter typing
|
|
model = hslaToRgba(model);
|
|
}
|
|
return model;
|
|
}
|
|
const mixColor = (from, to) => {
|
|
const fromRGBA = asRGBA(from);
|
|
const toRGBA = asRGBA(to);
|
|
if (!fromRGBA || !toRGBA) {
|
|
return mixImmediate(from, to);
|
|
}
|
|
const blended = { ...fromRGBA };
|
|
return (v) => {
|
|
blended.red = mixLinearColor(fromRGBA.red, toRGBA.red, v);
|
|
blended.green = mixLinearColor(fromRGBA.green, toRGBA.green, v);
|
|
blended.blue = mixLinearColor(fromRGBA.blue, toRGBA.blue, v);
|
|
blended.alpha = mixNumber(fromRGBA.alpha, toRGBA.alpha, v);
|
|
return rgba.transform(blended);
|
|
};
|
|
};
|
|
|
|
export { mixColor, mixLinearColor };
|