3

我有一个要隐藏/显示的输入字段,并使用淡入淡出和幻灯片过渡。我想出了两个例子,但都有各自的缺点,我想知道是否有更优雅的解决方案。

我只需要回答这两个问题之一,因为它们都可以解决我的问题。

问题 1:有没有办法为一个转换指令触发多个转换?

问题 2:如何在if 语句将元素放入 DOM添加一个将触发普通 css-transition 的类?

示例 1

Svelte 不允许在同一个元素上进行两个过渡。所以一种解决方案是嵌套两个元素,如下所示。有没有一种方法可以同时使用 fade 和 slide 编写自定义过渡transition:myMultiTransition

{#if active === true}
  <span transition:fade>
    <span transition:slide>
      <input type="text" />
    </span>
  </span>
{/if}

示例 2

在我的另一个解决方案中,我只是使用普通的 css 转换来切换一个活动类。这里的问题是<input>-field 永远不会离开 DOM。它的高度为 0px,但将其留在那里似乎是错误的。

如何使用 an 成功显示输入字段,{#if active === true}然后添加一个触发过渡效果的类?Svelte 似乎添加了应该在元素进入 DOM 之前触发转换的活动类。

我尝试以各种组合使用await tick(), onMountbeforeUpdate但没有运气。

当使用 setTimeout 添加具有延迟的类时,它可以工作 - 但我不喜欢这种解决方案,因为如果时间不准确,它可能会失败,而且我不希望在过渡开始之前有延迟。

<span class:{active}>
   <input type="text" />
</span>

<style>
  .active {
     // Normal transition: opacity 1s etc ... 
  }
</style>

REPL

https://svelte.dev/repl/89cb7d26d9484d0193b4bc6bf59518ef?version=3.38.3

4

2 回答 2

1

坚持您已经提供的第一个解决方案可能是最容易的:为每个转换添加一个包装器。

如果您想重用特定的转换组合,编写自己的转换组合可能是值得的。此时您可以尝试使用 Svelte 的实现:这是 Slide + Fade 的示例

function fadeSlide(node, options) {
    const slideTrans = slide(node, options)
    return {
        duration: options.duration,
        css: t => `
            ${slideTrans.css(t)}
            opacity: ${t};
        `
    };
}

https://svelte.dev/repl/f5c42c6dc6774f29ad9350cd2dc2d299?version=3.38.3

通用解决方案(理论)

在 Svelte 中,过渡本身不依赖 CSS 过渡。Svelte 过渡仅提供每个过渡步骤的样式。因此,一个通用的解决方案是创建一个合并转换,它采用 2..N 个转换函数并将来自单个转换的样式放在一起。不幸的是,由于 CSS 中的冲突情况,这并不总是微不足道的。

例如,结合两个过渡...一个不透明度应该为 0,另一个目标不透明度为 0.5。问题是:输出应该是什么样子?如果预期为 0,则必须有一些逻辑转换“不透明度:0;不透明度:0.5;” 到“不透明度:0;”。当然还有更复杂的案例。

于 2021-07-03T17:55:23.067 回答
0

您可以创建自己的转换函数:

<script>
    import { cubicOut } from 'svelte/easing';
    let visibleDoubleElements = false;


    function slidefade(node, params) {
        const existingTransform = getComputedStyle(node).transform.replace('none', '');

        return {
            delay: params.delay || 0,
            duration: params.duration || 400,
            easing: params.easing || cubicOut,
            css: (t, u) => `transform-origin: top left; transform: ${existingTransform} scaleY(${t}); opacity: ${t};`
        };
    }
</script>


<label>
    <input type="checkbox" bind:checked={visibleDoubleElements}>
    Svelte transition
</label>

{#if visibleDoubleElements === true}
    <input transition:slidefade type="text" placeholder="Double elements" />
{/if}

REPL: https ://svelte.dev/repl/da8880947eff4f32b740a8742d9f817e?version=3.38.3

于 2021-07-03T12:31:11.977 回答