我有一个列表,我想要设置动画,以便当选择一个项目时,它会浮到顶部,其余的会飞出。重新选择元素时,它会浮回其位置,而其他元素会飞回。
使用这个 crossfade 演示我能够制作一个非常可靠的版本:
但是,我注意到元素有时不会返回到原始位置,只有随后的重新动画才能修复它。我很确定这是因为我的交叉淡入淡出功能需要更复杂的处理(或者我应该只使用常规过渡?),但我不确定具体如何。
<script>
import { flip } from 'svelte/animate'
import { writable } from 'svelte/store'
import { crossfade, fly } from 'svelte/transition'
const ACTIONS = [
{ key: 'blue' },
{ key: 'green' },
{ key: 'yellow' },
{ key: 'purple' },
{ key: 'orange' },
{ key: 'red' },
]
const selectedAction = writable(null)
let shownActions = ACTIONS.map(a => a)
const [send, receive] = crossfade({
fallback(node, _params) {
return fly(node, { x: -800, duration: 600 })
}
})
function selectAction(action) {
if ($selectedAction === action) {
shownActions = ACTIONS.map(a => a)
selectedAction.update(v => {
if (v === action || action === undefined) {
return null
} else {
return action
}
})
} else {
shownActions = ACTIONS.filter(a => a.key === action)
selectedAction.update(v => {
if (v === action || action === undefined) {
return null
} else {
return action
}
})
window.scrollTo({
top: 0,
behavior: 'smooth'
})
}
}
</script>
<ul>
{#each shownActions as action (action)}
<li
class={`${$$props.class || ''}`}
animate:flip={{ duration: 600 }}
in:receive={{ key: action.key }}
out:send={{ key: action.key }}
>
<button on:click={e => selectAction(action.key)}>{action.key}</button>
</li>
{/each}
</ul>
<style lang="scss">
ul {
list-style: none;
}
li {
display: flex;
margin-bottom: 1rem;
}
button {
margin-right: 1rem;
padding: 0.5rem 1rem;
}
</style>
看起来当您在动画结束之前单击时会出现此问题。您可以使用过渡事件等待动画结束。但过渡期间元素的位置也存在问题。当使用子
div
旁边的 li
元素时,我得到了更好的结果:
{#each shownActions as action (action)}
<li>
<div
class={`${$$props.class || ''}`}
in:receive={{ key: action.key }}
out:send={{ key: action.key }}
>
<button on:click={e => selectAction(action.key)}>{action.key}</button>
</div>
</li>
{/each}