본문 바로가기

개발하자

두 요소 "점프" 사이의 부드러운 전환

반응형

두 요소 "점프" 사이의 부드러운 전환

나는 스벨테를 사랑하지만, 기본적인 것에 집착한다. 다음 코드는 두 요소 사이를 부드럽게 전환해야 하지만 대신 "점프"를 합니다. 즉, 들어오는 요소가 도착하기 전에 공간을 만드는 것 같습니다.

이 문제는 리치 해리스가 몇 년 전에 언급한 것과 유사하지만, 나는 해결책이 구현되었다고 보지 않는다. 전환에 대한 모든 예제는 단일 요소만 사용합니다.

다음은 기본 마크업/코드입니다:

{#if div1}
    <div 
      in:fly={{ x: 100, duration: 400, delay: 400 }}
      out:fly={{ x: 100, duration: 400 }}>Div 1</div>
{:else}
    <div 
      in:fly={{ x: 100, duration: 400, delay: 400 }}
      out:fly={{ x: 100, duration: 400 }}>Div 2</div>
{/if}

<button on:click={()=>{ div1 = !div1}}>Switch</button>

Vue에서 작동하는 동등한 값은 다음과 같습니다:

<transition name="fly" mode="out-in">
    <div v-if="div1">Div 1</div>
    <div v-else>Div 2</div>
</transition>

여기 a가 있습니다. 버튼이 아래로 점프하여 새 요소를 위한 공간을 확보할 수 있습니다. 400의 지속 시간과 동일한 "in" 전환 지연 시간을 추가했습니다(기본값인 것은 알지만 명확성을 위해 명시적으로 설정하고 싶었습니다). 지연은 첫 번째 링크(해리스가 "지연의 무모한 사용"이라고 부른 것)에서 언급하고 제안한 바와 같이, 다음 요소를 전환하기 전에 첫 번째 요소가 전환되도록 허용해야 한다.

저는 또한 요소가 바깥쪽에 위치하도록 명시적으로 설정하려고 했습니다. 공간을 차지하지 않도록 절대적입니다. 작동하더라도 약간 우아하지 않은 것 같습니다. 어떤 이유에서인지, 전환은 위치를 설정하는 클래스를 재정의합니다: 절대.

어떤 도움이든 대단히 감사합니다!

업데이트: 원하는 효과를 얻었습니다. 여기서 제가 한 것은 스벨테의 플라이 전이를 복사하고 수정하여 추가 매개변수를 취하도록 한 것입니다. 'position'은 '절대', '상대' 또는 원하는 대로 설정할 수 있습니다. 이상한 부작용이 없도록 CSS를 몇 번 수정한다(컨테이너를 위치로 설정하고 각 요소의 너비를 100%로 설정하여 크기를 변경하지 않도록 한다). 이것은 효과가 있지만, 나는 여전히 스벨테의 전환을 수정하지 않고 노동 집약적인 방법이 있어야 한다고 생각한다.




나도 부에에서 왔어, 스벨테와 함께했던 아웃인이 한 가지 그리워. 리치 해리스는 스벳 3 이전에 그것을 인정하기도 했지만 내가 아는 한 실제로 수정을 시행한 적은 없다.

단일 조건, 지연 전용, 아웃 인 전환 방법의 문제는 스벨테가 전환 시 지연에도 불구하고 조건이 전환되면 들어오는 요소를 생성한다는 것입니다. 전환 속도를 늦추고 개발 도구를 확인하여 이를 확인할 수 있습니다. 두 요소 모두 존재합니다. 들어오는 전환 지연은 요소의 크기를 방해하지 않고 단지 가시성만 제공합니다.

한 가지 방법은 당신이 절대적인 위치에서 했던 것을 하는 것입니다. 집중적이고 진부한 것이 됩니다. 또 다른 방법은 전환되는 요소를 고정하는 컨테이너의 절대 높이를 설정하고, 컨테이너 밖으로 다른 모든 것을 끌어내고 오버플로를 숨기는 것이다.

내가 마지막으로 사용한 방법은 좀 더 우회적이지만, 스벨테는 애니메이션이 완료될 때 파견되는 아웃로드 이벤트가 있기 때문에 파란색에 대한 변수 또는 두 번째 조건에 대한 변수를 추가하고 두 번째 조건에 대한 if 블록(여기 파란색)을 추가하고 트리거를 배선하여 활성 변수를 확인하고 전환할 수 있습니다 Off를 선택한 다음 Outroend 이벤트 내의 다른 변수를 켜십시오. 지속 시간이 지연 시간이 되기 때문에 지연을 제거할 수도 있습니다.

전환 중 DOM을 검사하는 것은 두 요소가 별도의 조건에 의존하기 때문에 동시에 존재하지 않는 유일한 방법인 것 같습니다. 이를 달성할 수 있는 더 우아한 방법이 있을 것으로 확신하지만 이것은 나에게 효과가 있습니다.

:

유일하게 작동하는 다른 옵션이 있습니다. 운 좋게도 이 시점에서는 거의 보편적입니다. 요소의 높이에 대해 전혀 걱정할 필요가 없는 보너스가 추가된 절대 포지셔닝 방법과 매우 유사합니다

이것의 이면에 있는 아이디어는 CSS 그리드를 사용하면 두 요소가 동일한 공간을 차지하도록 강제할 수 있고, 두 요소(또는 2개 이상) 모두에 1col x 1 행의 암묵적 그리드에서 동일한 시작 및 끝 열과 행을 제공함으로써 가능하다는 것이다(그리드는 우리가 사용하지 않을 추가 열과 행을 만들지 않을 만큼 충분히 똑똑하다). 스벨테는 변환을 사용하기 때문에 레이아웃 변경 없이 요소를 주고 받을 수 있습니다. 요소에 영향을 미치는 절대 위치나 지연에 대해 더 이상 걱정할 필요가 없으며 전환 타이밍을 완벽하게 미세 조정할 수 있습니다.

여기 간단한 설정을 보여줄 수 있는 것과 이것을 사용하여 꽤 달콤한 레이어 효과를 얻을 수 있는 방법을 보여줄 수 있는 또 다른 것이 있다, 와!




둘 이상의 상태를 교환할 경우 동작을 사용자 지정 저장소로 추상화하는 것이 매우 유용합니다. 상점은 다음과 같이 보일 수 있습니다:

statefulSwap(initialState) {
    const state = writable(initialState);
    let nextState = initialState;
    
    function transitionTo(newState) {
        if(nextState === newState) return;
        nextState = newState
        state.set(null)
    }
    
    function onOutro() {
        state.set(nextState)
    }
    return {
        state,
        transitionTo,
        onOutro
    }
}

조건 블록을 사용하여 요소 간을 전환할 수 있습니다:

{#if $state == "first"}
    <h1 transition:fade on:outroend={onOutro}>
        First
</h1>
{:else if $state == "second"}
    <h1 transition:fade on:outroend={onOutro}>
        Second
</h1>
{/if}

이 기술은 처음에 현재 상태를 로 설정한 다음 첫 번째 요소가 전환된 후에 새 상태를 적용하여 Vue의 동작을 에뮬레이트합니다.

여기 예가 있습니다. 여기서의 장점은 스왑 로직을 추적할 필요 없이 다양한 애니메이션 작업과 타이밍으로 원하는 만큼의 상태를 가질 수 있다는 것입니다. 그러나 조건부 마크업에 기본 블록이 있는 경우에는 작동하지 않습니다.




"그리드 웨이"의 기본 설정은 다음과 같습니다:

<script>
    import { scale } from "svelte/transition"
  
    let condi = true;
</script>

<div class="container">
    {#if condi}
        <div class="item" in:scale out:scale />
    {:else}
        <div class="item" in:scale out:scale />
    {/if}
</div>

<style>
    .container {
        display: grid;
    }

    .item {
        grid-column-start: 1;
        grid-column-end: 2;
        grid-row-start: 1;
        grid-row-end: 2;
    }
</style>

스벨트 REPL


반응형