pull/4742/head
pushkine 5 years ago
parent a75fc80f4c
commit 0ee27c4bc1

@ -28,24 +28,20 @@ let pending_inserts = false;
const run_timed = (now: number) => {
/* Runs every timed out task */
let last_index = timed_tasks.length - 1;
while (last_index >= 0 && now >= timed_tasks[last_index].timestamp) timed_tasks[last_index--].callback(now);
while (~last_index && now >= timed_tasks[last_index].timestamp) timed_tasks[last_index--].callback(now);
if (pending_inserts) {
for (
let i = 0, j = last_index, this_task: TimeoutTask, that_task: TimeoutTask;
i < pending_insert_timed.length;
i++
)
for (let i = 0, j = 0, this_task: TimeoutTask, that_task: TimeoutTask; i < pending_insert_timed.length; i++)
if (now >= (this_task = pending_insert_timed[i]).timestamp) this_task.callback(now);
else {
/* moves each task up until this_task.timestamp > task.timestamp */
for (j = last_index; j > 0 && this_task.timestamp > (that_task = timed_tasks[j]).timestamp; j--)
for (j = last_index; ~j && this_task.timestamp > (that_task = timed_tasks[j]).timestamp; j--)
timed_tasks[j + 1] = that_task;
timed_tasks[j] = this_task;
timed_tasks[j + 1] = this_task;
last_index++;
}
pending_inserts = !!(pending_insert_timed.length = 0);
}
return (running_timed = !!(timed_tasks.length = last_index));
return (running_timed = !!(timed_tasks.length = last_index + 1));
};
const unsafe_loop = (fn) => {
if (!next_frame_length) raf(run);
@ -73,15 +69,15 @@ export const setAnimationTimeout = (callback: () => void, timestamp: number): Ta
*/
export const useTween = (
run: (now: number) => void,
stop: () => void,
stop: (now: number) => void,
end_time: number,
duration = end_time - now()
): TaskCanceller => {
let running = true;
unsafe_loop((t) => {
if (!running) return false;
t = 1 - (end_time - t) / duration;
if (t >= 1) return run(1), stop(), false;
t = (end_time - t) / duration;
if (t >= 1) return run(1), stop(t), false;
if (t >= 0) run(t);
return running;
});

@ -4,14 +4,13 @@ import { resolved_promise } from './environment';
const dirty_components = [];
let update_scheduled = false;
export function schedule_update(component) {
export const schedule_update = (component) => {
dirty_components.push(component);
if (!update_scheduled) (update_scheduled = true), resolved_promise.then(flush);
}
export function tick() {
if (!update_scheduled) (update_scheduled = true), resolved_promise.then(flush);
return resolved_promise;
}
};
export const tick = () =>
update_scheduled ? resolved_promise : ((update_scheduled = true), resolved_promise.then(flush));
export const binding_callbacks = [];
const render_callbacks = [];
const seen_callbacks = new Set();
@ -20,38 +19,55 @@ export const add_render_callback = (fn) =>
const flush_callbacks = [];
export const add_flush_callback = (fn) => void flush_callbacks.push(fn);
const measure_callbacks = [];
export const add_measure_callback = (fn) => void measure_callbacks.push(fn);
let flushing = false;
export function flush() {
if (flushing) return;
else flushing = true;
for (; dirty_components.length; ) {
let i = 0,
j = 0,
$$,
before_update,
dirty;
// RUN LOGIC, CANCEL STYLES
do {
// update components + beforeUpdate
for (let i = 0, $$; i < dirty_components.length; i++) {
for (i = 0; i < dirty_components.length; i++) {
({ $$ } = set_current_component(dirty_components[i]));
if ($$.fragment === null) continue;
const { update, before_update, dirty, after_update } = $$;
update();
for (let j = 0; j < before_update.length; j++) before_update[j]();
$$.update();
for (j = 0, { before_update } = $$; j < before_update.length; j++) before_update[j]();
({ dirty } = $$);
$$.dirty = [-1];
if ($$.fragment) $$.fragment.p($$.ctx, dirty);
render_callbacks.push(...after_update);
render_callbacks.push(...$$.after_update);
}
dirty_components.length = 0;
// update bindings in reverse order
for (let i = binding_callbacks.length - 1; i >= 0; i--) binding_callbacks[i]();
i = binding_callbacks.length;
while (i--) binding_callbacks[i]();
binding_callbacks.length = 0;
// afterUpdate
for (let i = 0; i < render_callbacks.length; i++) render_callbacks[i]();
for (i = 0; i < render_callbacks.length; i++) render_callbacks[i]();
render_callbacks.length = 0;
seen_callbacks.clear();
}
} while (dirty_components.length);
update_scheduled = false;
for (let i = 0; i < flush_callbacks.length; i++) flush_callbacks[i]();
// STYLE MEASURE CHANGES
for (i = 0; i < measure_callbacks.length; i++) flush_callbacks.push(measure_callbacks[i]());
measure_callbacks.length = 0;
// APPLY STYLE CHANGES
for (i = 0; i < flush_callbacks.length; i++) flush_callbacks[i]();
flush_callbacks.length = 0;
update_scheduled = flushing = false;
}
flushing = false;
}

@ -1,5 +1,5 @@
import { element } from './dom';
import { raf } from './environment';
import { raf, now } from './environment';
const enum SVELTE {
RULE = `__svelte_`,
STYLESHEET = `__svelte_stylesheet`,
@ -43,22 +43,23 @@ function hash(str: string) {
while (i--) hash = ((hash << 5) - hash) ^ str.charCodeAt(i);
return hash >>> 0;
}
const gen = (t, step, css) => {
const gen = (step, css) => {
let rule = '{\n';
for (; t < 1; t += step) rule += `${100 * t}%{${css(t)}}\n`;
for (let t = 0; t < 1; t += step) rule += `${100 * t}%{${css(t)}}\n`;
rule += `100% {${css(1)}}\n}`;
const name = SVELTE.RULE + hash(rule);
return [name, `@keyframes ${name} ${rule}`];
};
export function animate_css(css: (t: number) => string, node: HTMLElement, duration: number, t = 0) {
const [name, rule] = gen(t, duration / (FRAME_RATE || calc_framerate()), css);
export function animate_css(css: (t: number) => string, node: HTMLElement, duration: number, delay = 0) {
const [name, rule] = gen(Math.max(1 / 1000, (FRAME_RATE || calc_framerate()) / duration), css);
const [stylesheet, rules] = add_rule(node);
if (!rules.has(name)) {
rules.add(name);
stylesheet.insertRule(rule, stylesheet.cssRules.length);
}
const previous = node.style.animation;
node.style.animation = (previous ? previous + ', ' : '') + `${duration}ms linear 0ms 1 normal both running ${name}`;
node.style.animation =
(previous ? previous + ', ' : '') + `${duration}ms linear ${delay}ms 1 normal both running ${name}`;
running_animations++;
return () => {
const prev = (node.style.animation || '').split(', ');

@ -4,12 +4,12 @@ import { setAnimationTimeout, useTween } from './loop';
import { animate_css } from './style_manager';
import { custom_event } from './dom';
import { TransitionConfig } from '../transition';
import { add_render_callback, add_flush_callback } from './scheduler';
import { add_measure_callback, add_render_callback } from './scheduler';
import { Fragment } from './Component';
function startStopDispatcher(node: Element, direction: boolean) {
add_render_callback(() => node.dispatchEvent(custom_event(`${direction ? 'intro' : 'outro'}start`)));
return () => node.dispatchEvent(custom_event(`${!direction ? 'intro' : 'outro'}end`));
function startStopDispatcher(node: Element, is_intro: boolean) {
node.dispatchEvent(custom_event(`${is_intro ? 'intro' : 'outro'}start`));
return () => node.dispatchEvent(custom_event(`${is_intro ? 'intro' : 'outro'}end`));
}
const outroing = new Set();
@ -47,65 +47,73 @@ export function transition_out(block: Fragment, local?: 0 | 1, detach?: 0 | 1, c
block.o(local);
}
const eased = (fn: (t: number) => any, easing: (t: number) => number) => (easing ? (t: number) => fn(easing(t)) : fn);
const runner = (fn: (t0: number, t1: number) => any, reversed: boolean) =>
reversed ? (t: number) => fn(1 - t, t) : (t: number) => fn(t, 1 - t);
const eased = (fn: (t: number) => any, easing: (t: number) => number, start, end) => (t: number) =>
fn(start + (end - start) * easing(t));
//easing ? (!is_intro ? (t: number) => fn(easing(t)) : (t: number) => fn(1 - easing(1 - t))) : fn;
const runner = (fn: (t0: number, t1: number) => any, is_intro: boolean) =>
is_intro ? (t: number) => fn(t, 1 - t) : (t: number) => fn(1 - t, t);
const mirror = (fn, easing, is_intro) => {
const run = is_intro ? (t) => fn(1 - t, t) : (t) => fn(t, 1 - t);
return easing ? (is_intro ? (t) => run(1 - easing(1 - t)) : (t) => run(easing(t))) : run;
};
type TransitionFn = (node: HTMLElement, params: any) => TransitionConfig;
export function run_transition(
node: HTMLElement,
fn: TransitionFn,
is_intro = true,
params = {},
reversed_from = -1
left_duration = 0,
prev_left = 0
): StopResetReverse {
let config = fn(node, params);
let config;
let running = true;
let cancel_css;
let cancel_raf;
let dispatch_end;
let end_time;
let t;
let start_ratio;
const group = outros;
if (!is_intro) group.r++;
function start({ delay = 0, duration = 300, easing, tick, css }: TransitionConfig) {
const start = ({ delay = 0, duration = 300, easing, tick, css }: TransitionConfig) => {
if (!running) return;
const start_time = ~reversed_from ? reversed_from : now() + delay;
end_time = start_time + duration;
if (css)
cancel_css = animate_css(
runner(eased(css, easing), is_intro),
node,
duration,
(end_time - start_time) / duration
);
t = duration - (left_duration > 0 ? left_duration : 0);
end_time = now() + t;
start_ratio = 1 - easing((t - prev_left) / duration);
if (css) cancel_css = animate_css(eased(runner(css, is_intro), easing, start_ratio, 1), node, t, 0);
dispatch_end = startStopDispatcher(node, is_intro);
cancel_raf = tick
? useTween(runner(eased(tick, easing), is_intro), stop, duration, end_time)
? useTween(eased(runner(tick, is_intro), easing, start_ratio, 1), stop, end_time, t)
: setAnimationTimeout(stop, end_time);
}
function stop(reset_reverse?: 1 | -1) {
if (!is_intro && 1 === reset_reverse && config && 'tick' in config) config.tick(1, 0);
};
const stop = (end_reset_reverse?: number | 1 | -1) => {
if (!running) return;
else running = false;
if (cancel_css) cancel_css();
if (cancel_raf) cancel_raf();
if (dispatch_end) dispatch_end();
if (t > end_time && dispatch_end) dispatch_end();
if (!is_intro && !--group.r) for (let i = 0; i < group.c.length; i++) group.c[i]();
if (!~reset_reverse) return run_transition(node, fn, !is_intro, params, end_time);
else if (!~reversed_from) running_bidi.delete(node);
}
// @ts-ignore
if (typeof config === 'function') add_flush_callback(() => start((config = config())));
else start(config);
if (!~end_reset_reverse)
return run_transition(node, () => config, !is_intro, params, end_time - now(), left_duration);
else if (left_duration) running_bidi.delete(node);
};
add_measure_callback(() => {
config = fn(node, params);
return () => start(typeof config === 'function' ? (config = config()) : config);
});
return stop;
}
export type StopResetReverse = (reset_reverse?: 1 | -1) => StopResetReverse;
const running_bidi: Map<HTMLElement, StopResetReverse> = new Map();
export function run_bidirectional_transition(node: HTMLElement, fn: TransitionFn, is_intro: boolean, params: any) {
let cancel;
if (running_bidi.has(node)) running_bidi.set(node, (cancel = running_bidi.get(node)(-1)));
if (running_bidi.has(node) && (cancel = running_bidi.get(node)(-1))) running_bidi.set(node, cancel);
else running_bidi.set(node, (cancel = run_transition(node, fn, is_intro, params, -1)));
return cancel;
}

@ -136,8 +136,3 @@ export const has_prop = (obj, prop) => Object.prototype.hasOwnProperty.call(obj,
export function action_destroyer(action_result) {
return action_result && is_function(action_result.destroy) ? action_result.destroy : noop;
}
export const minmax = (min: number, max: number) => (value: number) => (min > value ? min : value > max ? max : value);
export const clamper = (min: number, max: number) =>
min !== -Infinity || max !== Infinity
? (fn: (value: number) => any) => (value: number) => (min > (value = fn(value)) ? min : value > max ? max : value)
: (fn: (value: number) => any) => fn;

@ -58,16 +58,14 @@ export function fly(
const style = getComputedStyle(node);
const target_opacity = +style.opacity;
const transform = style.transform === 'none' ? '' : style.transform;
const od = target_opacity * (1 - opacity);
return {
delay,
duration,
easing,
css: (t, u) => `
transform: ${transform} translate(${(1 - t) * x}px, ${(1 - t) * y}px);
opacity: ${target_opacity - od * u};`,
transform: ${transform} translate(${u * x}px, ${u * y}px);
opacity: ${target_opacity - od * u}`,
};
}

Loading…
Cancel
Save