Last active
January 28, 2020 00:44
-
-
Save buhrmi/1e806fc4ab50e5cd5453ccfb90711e99 to your computer and use it in GitHub Desktop.
d3-powered crossfade for svelte
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { interpolateTransformCss as interpolate} from 'd3' | |
import { cubicOut } from 'svelte/easing' | |
export function crossfade({ fallback, ...defaults }) { | |
const to_receive = new Map(); | |
const to_send = new Map(); | |
function crossfade(fromNode, toNode, params) { | |
const { delay = 0, duration = d => Math.sqrt(d) * 30, easing = cubicOut } = Object.assign(Object.assign({}, defaults), params); | |
const toStyle = getComputedStyle(toNode); | |
const fromStyle = getComputedStyle(fromNode); | |
toNode.style.transform = 'none' | |
fromNode.style.transform = 'none' | |
const toRect = toNode.getBoundingClientRect(); | |
const fromRect = fromNode.getBoundingClientRect(); | |
toNode.style.transform = '' | |
fromNode.style.transform = '' | |
const dx = fromRect.left - toRect.left; | |
const dy = fromRect.top - toRect.top; | |
const d = Math.sqrt(dx * dx + dy * dy); | |
let fromTransform = fromStyle.transform === 'none' ? '' : fromStyle.transform | |
let toTransform = toStyle.transform === 'none' ? '' : toStyle.transform; | |
fromTransform = `translate(${dx}px, ${dy}px)` + fromTransform | |
toTransform = `translate(${0}px, ${0}px)` + toTransform | |
const interpolator = interpolate(fromTransform, toTransform) | |
const opacity = +toStyle.opacity; | |
return { | |
delay, | |
duration: typeof(duration) == 'function' ? duration(d) : duration, | |
easing, | |
css: (t) => ` | |
opacity: ${t * opacity}; | |
transform: ${interpolator(t)} ; | |
` | |
}; | |
} | |
function transition(items, counterparts, intro) { | |
return (node, params) => { | |
items.set(params.key, {node}); | |
return () => { | |
if (counterparts.has(params.key)) { | |
const { node: fromNode } = counterparts.get(params.key); | |
counterparts.delete(params.key); | |
return crossfade(fromNode, node, params); | |
} | |
// if the node is disappearing altogether | |
// (i.e. wasn't claimed by the other list) | |
// then we need to supply an outro | |
items.delete(params.key); | |
return fallback && fallback(node, params, intro); | |
}; | |
}; | |
} | |
return [ | |
transition(to_send, to_receive, false), | |
transition(to_receive, to_send, true) | |
]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment