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 };