sigmaxf
sigmaxf

Reputation: 8492

Vuejs back and forth transition skipping ahead to last frame on back

I'm creating a slider element of 2 items only. I want them to smoothly slide back and forth to the left and right when I click back / next. It works well when I click next, elements scroll and fade, but when I click back, the first element jumps ahead in time no matter what I do, this gif explains a bit more visually:

enter image description here

Edit: Here is a fiddle - http://jsfiddle.net/eywraw8t/273583/

This is my css:

.first-slide-enter{
  opacity: 0;
  transform: translatex(-100%);
  transition: all 1.5s ease-out;
}
.first-slide-enter-to{
  opacity: 1;
  transform: translatex(0);
  transition: all 1.5s ease-out;
}
.first-slide-leave-to{
    opacity: 0;
    transform: translatex(-100%);
    transition: all 1.5s ease-out;
}


.second-slide-enter{
  opacity: 0;
  transform: translatex(0);
  transition: all 1.5s ease-out;
}
.second-slide-enter-to{
    opacity: 1;
    transform: translatex(-100%);
    transition: all 1.5s ease-out;
}
.second-slide-leave-to{
    opacity: 0;
    transform: translatex(0);
    transition: all 1.5s ease-out;
}

This is my html:

        <transition name="first-slide">
            <div v-if="!newShortcut.link">

                <div id="drop-shortcut" class="drag-file clickable" @click="addShortcut">
                    <i class="fas fa-file-upload fa-lg"></i>
                    <p style="margin:20px 0 0;">Drag file here
                        <br> or click to browse</p>
                </div>                      
                <div>
                        <button @click="newShortcut.link = !newShortcut.link">Next</button>
                </div>

            </div>
        </transition>

        <transition name="second-slide">
            <div v-if="newShortcut.link">
                <div id="drop-icon" class="drag-file" @click="">
                    <i class="far fa-file-image fa-lg"></i>
                    <p style="margin:20px 0 0;">Drag file here
                        <br> or click to browse</p>
                </div>
                <div>
                    <button @click="newShortcut.link = !newShortcut.link">back</button>
                </div>
            </div>
        </transition>

How to make this work?

Upvotes: 0

Views: 2358

Answers (2)

Matti Price
Matti Price

Reputation: 3551

So @Julian is correct for the blocking issue, but there is another way to fix it that might work for you better. See this fiddle : http://jsfiddle.net/xcmn76Lo/

Basically what was needed was some tweaking to the second slide. There is a hook you can use similar to enter to specify where it starts leaving from. In this case since the other div reserves its space immediately, you need to start the leave transition offsetting appropriately.

.second-slide-leave{
  transform:translatex(-100%);
}

Then instead of transition to 100%, set leave-to to 0 (aka where it WOULD end up if moved over by the incoming div).

.second-slide-leave-to{
    opacity: 0;
    transform: translatex(0);
    transition: all 1.5s ease-out;
}

Upvotes: 1

Julian Paolo Dayag
Julian Paolo Dayag

Reputation: 3719

The issue was because of how your elements are displayed. Each slide is a block, so it occupies a space in your layout.

So when you were at the second slide and click the back button. What happens before that is, there was no slide 1 in the layout and when vue starts to insert the slide 1 back, it occupies a space which causes the second slide to suddenly jump from left to right.

So to fix that behavior, you can make each slide's position as absolute so that if they are inserted back, they will not cause such behavior because absolute position will not affect it's neighboring element's position unlike the relative position.

#app>div {
  position: absolute;
  height: 200px;
  width: 200px;
  text-align: center;
  left: 0;
  top: 0;
}

and update the css transition for the second slide a little bit:

.second-slide-enter {
  opacity: 0;
  transform: translatex(100%);
  transition: all 1.5s ease-out;
}

.second-slide-enter-to {
  opacity: 1;
  transform: translatex(0);
  transition: all 1.5s ease-out;
}

.second-slide-leave-to {
  opacity: 0;
  transform: translatex(100%);
  transition: all 1.5s ease-out;
}

Here's the full JS Fiddle: http://jsfiddle.net/eywraw8t/273631/

Upvotes: 1

Related Questions