|
import { cubicOut, cubicInOut, linear } from '../easing/index.js'; |
|
import { assign, split_css_unit, is_function } from '../internal/index.js'; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function blur( |
|
node, |
|
{ delay = 0, duration = 400, easing = cubicInOut, amount = 5, opacity = 0 } = {} |
|
) { |
|
const style = getComputedStyle(node); |
|
const target_opacity = +style.opacity; |
|
const f = style.filter === 'none' ? '' : style.filter; |
|
const od = target_opacity * (1 - opacity); |
|
const [value, unit] = split_css_unit(amount); |
|
return { |
|
delay, |
|
duration, |
|
easing, |
|
css: (_t, u) => `opacity: ${target_opacity - od * u}; filter: ${f} blur(${u * value}${unit});` |
|
}; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function fade(node, { delay = 0, duration = 400, easing = linear } = {}) { |
|
const o = +getComputedStyle(node).opacity; |
|
return { |
|
delay, |
|
duration, |
|
easing, |
|
css: (t) => `opacity: ${t * o}` |
|
}; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function fly( |
|
node, |
|
{ delay = 0, duration = 400, easing = cubicOut, x = 0, y = 0, opacity = 0 } = {} |
|
) { |
|
const style = getComputedStyle(node); |
|
const target_opacity = +style.opacity; |
|
const transform = style.transform === 'none' ? '' : style.transform; |
|
const od = target_opacity * (1 - opacity); |
|
const [xValue, xUnit] = split_css_unit(x); |
|
const [yValue, yUnit] = split_css_unit(y); |
|
return { |
|
delay, |
|
duration, |
|
easing, |
|
css: (t, u) => ` |
|
transform: ${transform} translate(${(1 - t) * xValue}${xUnit}, ${(1 - t) * yValue}${yUnit}); |
|
opacity: ${target_opacity - od * u}` |
|
}; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function slide(node, { delay = 0, duration = 400, easing = cubicOut, axis = 'y' } = {}) { |
|
const style = getComputedStyle(node); |
|
const opacity = +style.opacity; |
|
const primary_property = axis === 'y' ? 'height' : 'width'; |
|
const primary_property_value = parseFloat(style[primary_property]); |
|
const secondary_properties = axis === 'y' ? ['top', 'bottom'] : ['left', 'right']; |
|
const capitalized_secondary_properties = secondary_properties.map( |
|
(e) => `${e[0].toUpperCase()}${e.slice(1)}` |
|
); |
|
const padding_start_value = parseFloat(style[`padding${capitalized_secondary_properties[0]}`]); |
|
const padding_end_value = parseFloat(style[`padding${capitalized_secondary_properties[1]}`]); |
|
const margin_start_value = parseFloat(style[`margin${capitalized_secondary_properties[0]}`]); |
|
const margin_end_value = parseFloat(style[`margin${capitalized_secondary_properties[1]}`]); |
|
const border_width_start_value = parseFloat( |
|
style[`border${capitalized_secondary_properties[0]}Width`] |
|
); |
|
const border_width_end_value = parseFloat( |
|
style[`border${capitalized_secondary_properties[1]}Width`] |
|
); |
|
return { |
|
delay, |
|
duration, |
|
easing, |
|
css: (t) => |
|
'overflow: hidden;' + |
|
`opacity: ${Math.min(t * 20, 1) * opacity};` + |
|
`${primary_property}: ${t * primary_property_value}px;` + |
|
`padding-${secondary_properties[0]}: ${t * padding_start_value}px;` + |
|
`padding-${secondary_properties[1]}: ${t * padding_end_value}px;` + |
|
`margin-${secondary_properties[0]}: ${t * margin_start_value}px;` + |
|
`margin-${secondary_properties[1]}: ${t * margin_end_value}px;` + |
|
`border-${secondary_properties[0]}-width: ${t * border_width_start_value}px;` + |
|
`border-${secondary_properties[1]}-width: ${t * border_width_end_value}px;` |
|
}; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function scale( |
|
node, |
|
{ delay = 0, duration = 400, easing = cubicOut, start = 0, opacity = 0 } = {} |
|
) { |
|
const style = getComputedStyle(node); |
|
const target_opacity = +style.opacity; |
|
const transform = style.transform === 'none' ? '' : style.transform; |
|
const sd = 1 - start; |
|
const od = target_opacity * (1 - opacity); |
|
return { |
|
delay, |
|
duration, |
|
easing, |
|
css: (_t, u) => ` |
|
transform: ${transform} scale(${1 - sd * u}); |
|
opacity: ${target_opacity - od * u} |
|
` |
|
}; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function draw(node, { delay = 0, speed, duration, easing = cubicInOut } = {}) { |
|
let len = node.getTotalLength(); |
|
const style = getComputedStyle(node); |
|
if (style.strokeLinecap !== 'butt') { |
|
len += parseInt(style.strokeWidth); |
|
} |
|
if (duration === undefined) { |
|
if (speed === undefined) { |
|
duration = 800; |
|
} else { |
|
duration = len / speed; |
|
} |
|
} else if (typeof duration === 'function') { |
|
duration = duration(len); |
|
} |
|
return { |
|
delay, |
|
duration, |
|
easing, |
|
css: (_, u) => ` |
|
stroke-dasharray: ${len}; |
|
stroke-dashoffset: ${u * len}; |
|
` |
|
}; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export function crossfade({ fallback, ...defaults }) { |
|
|
|
const to_receive = new Map(); |
|
|
|
const to_send = new Map(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
function crossfade(from_node, node, params) { |
|
const { |
|
delay = 0, |
|
duration = (d) => Math.sqrt(d) * 30, |
|
easing = cubicOut |
|
} = assign(assign({}, defaults), params); |
|
const from = from_node.getBoundingClientRect(); |
|
const to = node.getBoundingClientRect(); |
|
const dx = from.left - to.left; |
|
const dy = from.top - to.top; |
|
const dw = from.width / to.width; |
|
const dh = from.height / to.height; |
|
const d = Math.sqrt(dx * dx + dy * dy); |
|
const style = getComputedStyle(node); |
|
const transform = style.transform === 'none' ? '' : style.transform; |
|
const opacity = +style.opacity; |
|
return { |
|
delay, |
|
duration: is_function(duration) ? duration(d) : duration, |
|
easing, |
|
css: (t, u) => ` |
|
opacity: ${t * opacity}; |
|
transform-origin: top left; |
|
transform: ${transform} translate(${u * dx}px,${u * dy}px) scale(${t + (1 - t) * dw}, ${ |
|
t + (1 - t) * dh |
|
}); |
|
` |
|
}; |
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function transition(items, counterparts, intro) { |
|
return (node, params) => { |
|
items.set(params.key, node); |
|
return () => { |
|
if (counterparts.has(params.key)) { |
|
const other_node = counterparts.get(params.key); |
|
counterparts.delete(params.key); |
|
return crossfade(other_node, node, params); |
|
} |
|
|
|
|
|
|
|
items.delete(params.key); |
|
return fallback && fallback(node, params, intro); |
|
}; |
|
}; |
|
} |
|
return [transition(to_send, to_receive, false), transition(to_receive, to_send, true)]; |
|
} |
|
|