Vue로 부모 구성 요소를 가로 지르는 Transition 실현

가정하는 용도



예를 들어 Vue에서 카드 게임을 구현할 때,
  • 야마바 두고
  • 카드

  • 그리고 Compnent를 정의한다고 가정합니다.

    그리고 지금 「카드」는 「야마카키 두는 곳」의 아이로, 「야마카타 놓기장」에서 「패」로 이동한다고 합니다.
    이때 카드는 위치 애니메이션을 하고 싶은 것입니다만, vue의 transitiontransition group 에서는 실현할 수 없습니다.
    왜냐하면 부모 Component가 산찰에서 패로 바뀌기 때문에 1입니다.

    데모



    구체적으로는 이런 것입니다.
    4분할된 땅이 부모 Component로, 숫자가 쓰여진 사각형이 자식 Component로, 클릭하면 다른 부모 Component로 이동합니다.
    여기에서 실제로 시도 할 수 있습니다.



    구현



    Vue의 transition-group에서도 사용되고 있다 FLIP라는 아이디어를 사용하고 있습니다.
    기본은
    - before-leave에서 현재 위치를 기억하십시오.
    - after-enter에서 現在の位置 - 直前の位置 만 translate하고 그 차이만 이동 애니메이션
    라는 느낌입니다.

    parent-change-transition.vue
    <template>
      <transition v-on:before-enter="beforeEnter" v-on:after-enter="afterEnter" v-on:before-leave="beforeLeave">
        <slot/>
      </transition>
    </template>
    
    <script>
    //...
    
      export default {
        name: "parent-change-transition",
        methods: {
          beforeLeave (el) {
            previousPosition[this.childId] = el.getBoundingClientRect()
          },
          beforeEnter (el) {
            el.hidden = true
          },
          afterEnter (el) {
            el.hidden = false
            if (!previousPosition[this.childId]) return
            // 現在位置と直前位置の差だけtranslateし、tweenさせる
          }
        }
      }
    </script>
    
    

    그러나 이것만이라면 애니메이션하는 것은 대상의 아이뿐입니다.
    즉 대상의 아이가 이동한 후, 남겨진 다른 아이가 한순간에 이동해 버리기 때문에, 무슨 일이 일어났는지 알기 어려워져 버립니다.

    처음에는 이 부분에만 손목 전환 을 사용하면 좋을까? 라고 생각했습니다만, 부모에게 <transition-group> 를 사용하면 아이의 <transition> 가 무시되기 때문에 잘 되지 않습니다.

    거기서 모든 아이의 위치를 ​​기억해 두고, 전 프레임과 위치가 바뀌면 애니메이션 시킨다고 하는 진흙스러운 실장이 필요하게 됩니다.

    parent-change-transition.vue
    <template>
      <transition v-on:before-enter="beforeEnter" v-on:after-enter="afterEnter" v-on:before-leave="beforeLeave">
        <slot/>
      </transition>
    </template>
    
    <script>
      let previousPosition = {}
    
      export default {
        name: "parent-change-transition",
        props: {
          idPropertyName: { type:String, default: 'id' },
          duration: { type:Number, default: 300 }
        },
        data () {
          return { intervalIndex: null }
        },
        mounted () {
          this.startPositionInspection()
        },
        computed: {
          childId () {
            return this[[this.idPropertyName]]
          }
        },
        methods: {
          startPositionInspection () {
            let p = this.$el.getBoundingClientRect()
            this.intervalIndex = setInterval(() => {
              let current = this.$el.getBoundingClientRect()
              if (current.x === p.x && current.y === p.y) return
              this.move(p, current)
            }, 10)
          },
          move (previous, current) {
            clearInterval(this.intervalIndex)
            this.$el.animate([
              { transform: `translate(${previous.x - current.x}px, ${previous.y - current.y}px)` },
              { transform: 'translate(0, 0)' }
            ], { duration: this.duration }).addEventListener('finish', () => this.startPositionInspection())
          },
          beforeLeave (el) {
            previousPosition[this.childId] = el.getBoundingClientRect()
          },
          beforeEnter (el) {
            el.hidden = true
          },
          afterEnter (el) {
            el.hidden = false
            if (!previousPosition[this.childId]) return
            this.move(previousPosition[this.childId], el.getBoundingClientRect())
          }
        }
      }
    </script>
    

    사용 예 코드 등: htps : // 기주 b. 코 m / 이나 모리 / ゔ 에어 파렌 t - 찬 - t 란시 치온

    npm



    htps //w w. 음 pmjs. 코 m / Pa c 카게 / ゔ 에 파렌 t - 찬 - t 란시 치온
    모처럼이므로 등록했습니다.



    "카드"를 평평하게 나란히 스스로 좌표 관리하면 transition 하지만 괜찮습니다.

    좋은 웹페이지 즐겨찾기