pull/10798/head
Rich Harris 2 years ago
parent 70b2da0bd3
commit 4df995cdb9

@ -214,7 +214,7 @@ function animate(element, options, counterpart, t2, callback) {
if (css) {
// WAAPI
var keyframes = [];
var n = options.duration / (1000 / 60); // TODO should be adjusted_duration?
var n = adjusted_duration / (1000 / 60);
for (var i = 0; i <= n; i += 1) {
var t = t1 + delta * easing(i / n);

@ -83,12 +83,26 @@ class Animation {
}
/**
* @param {number} target_frame
* @param {number} t
*/
#apply_keyframe(target_frame) {
const keyframes = this.#keyframes;
const keyframes_size = keyframes.length - 1;
const frame = keyframes[Math.min(keyframes_size, Math.floor(keyframes.length * target_frame))];
#apply_keyframe(t) {
const n = Math.min(1, Math.max(0, t)) * (this.#keyframes.length - 1);
const lower = this.#keyframes[Math.floor(n)];
const upper = this.#keyframes[Math.ceil(n)];
let frame = lower;
if (lower !== upper) {
frame = {};
for (const key in lower) {
frame[key] = interpolate(
/** @type {string} */ (lower[key]),
/** @type {string} */ (upper[key]),
n % 1
);
}
}
for (let prop in frame) {
// @ts-ignore
@ -114,6 +128,40 @@ class Animation {
}
}
/**
* @param {string} a
* @param {string} b
* @param {number} p
*/
function interpolate(a, b, p) {
if (a === b) return a;
const fallback = p < 0.5 ? a : b;
const a_match = a.match(/[\d.]+|[^\d.]+/g);
const b_match = b.match(/[\d.]+|[^\d.]+/g);
if (!a_match || !b_match) return fallback;
if (a_match.length !== b_match.length) return fallback;
let result = '';
for (let i = 0; i < a_match.length; i += 2) {
const a_num = parseFloat(a_match[i]);
const b_num = parseFloat(b_match[i]);
result += a_num + (b_num - a_num) * p;
if (a_match[i + 1] !== b_match[i + 1]) {
// bail
return fallback;
}
result += a_match[i + 1] ?? '';
}
return result;
}
/**
* @param {Keyframe[]} keyframes
* @param {{duration: number}} options

@ -18,7 +18,7 @@ export default test({
raf.tick(25);
assert.equal(div.style.opacity, '0.25');
raf.tick(49);
assert.equal(div.style.opacity, '0');
raf.tick(35);
assert.equal(div.style.opacity, '0.18333333333333335');
}
});

@ -18,10 +18,9 @@ export default test({
raf.tick(75);
// these numbers look wrong because they're not lerped... maybe we should fix that
assert.equal(div.style.scale, '0.8333333333333334'); // intro continues while outro plays
assert.equal(div.style.opacity, '0.8333333333333334');
assert.equal(div.style.rotate, '300deg');
assert.equal(div.style.scale, '0.75'); // intro continues while outro plays
assert.equal(div.style.opacity, '0.75');
assert.equal(div.style.rotate, '270deg');
component.visible = true;

Loading…
Cancel
Save