簡體   English   中英

卡片翻轉式登錄表單 Vuejs 的過渡問題,其中卡片在進入或離開時沒有停留在原位

[英]Transition issue with card flip style login form Vuejs where card is not staying in place when entering or leaving

我正在嘗試在我想要的 Vue.js 中設置登錄/注冊組件的樣式,以便當您在兩者之間輕彈時,它會翻轉我擁有的卡片,但是,我遇到的問題是在過渡期間。 我似乎無法讓它工作。 一張卡變出來的時候向右下方移動,另一張卡進來的時候從右下角變成position。這個問題真的很難描述。

下面是網頁設計(雖然navbar是一個單獨的組件)

下面是幾張圖片,展示了轉換正在做什么。 在此處輸入圖像描述

在此處輸入圖像描述

[![在此處輸入圖片描述][4]][4]

該組件的代碼如下:

<template>
  <main class="login-body">
    <transition name="flip">
      <div class="login-box" v-if="currentForm === 'login'">
        <h2>Login</h2>
        <form @submit.prevent>
          <div class="user-box">
            <input v-model="email" type="text" name="username" required />
            <label>Email</label>
          </div>
          <div class="user-box">
            <input
              v-model="password"
              type="password"
              name="password"
              required
            />
            <label>Password</label>
          </div>
          <button @click="signIn">
            <span></span>
            <span></span>
            <span></span>
            <span></span>
            Submit
          </button>
        </form>
        <p>Not Signed Up? <span @click="toggleForm">Sign Up</span></p>
      </div></transition
    >
    <transition name="flip-reverse">
      <div class="login-box" v-if="currentForm === 'register'">
        <h2>Sign Up</h2>
        <form @submit.prevent>
          <div class="user-box">
            <input v-model="email" type="text" name="username" required />
            <label>Username</label>
          </div>
          <div class="user-box">
            <input
              v-model="password"
              type="password"
              name="password"
              required
            />
            <label>Password</label>
          </div>
          <div class="user-box">
            <input
              v-model="confirmPassword"
              type="password"
              name="confirm password"
              required
            />
            <label>Confirm Password</label>
          </div>
          <button @click="signUp">
            <span></span>
            <span></span>
            <span></span>
            <span></span>
            Submit
          </button>
        </form>
        <p>Already Signed Up? <span @click="toggleForm">Sign In</span></p>
      </div></transition
    >
  </main>
  <!-- <main class="home-container">
    <div class="register-card">
      <form
        @submit.prevent
        class="registration-form"
        v-if="currentForm === 'register'"
      >
        <input v-model="email" type="text" placeholder="Email" />
        <input v-model="password" type="password" placeholder="Password" />
        <button type="submit" @click="signIn">Sign In</button>
        <p>Not Signed Up? <span @click="toggleForm">Sign Up</span></p>
      </form>
    </div>
    <div class="login-card">
      <form @submit.prevent class="login-form" v-if="currentForm === 'login'">
        <input v-model="email" type="text" placeholder="Email" />
        <input v-model="password" type="password" placeholder="Password" />
        <input
          v-model="confirmPassword"
          type="password"
          placeholder="Confirm Password"
        />
        <button type="submit" @click="signUp">Sign up</button>
        <p>Already Signed Up? <span @click="toggleForm">Sign In</span></p>
      </form>
    </div>
  </main> -->
</template>

<script>
import { Auth } from "aws-amplify";
export default {
  name: "HomeView",
  data() {
    return {
      currentForm: "login",
      email: "",
      password: "",
      confirmPassword: "",
    };
  },
  methods: {
    toggleForm() {
      this.currentForm = this.currentForm === "login" ? "register" : "login";
    },
    async signUp() {
      if (
        this.email === "" ||
        this.password === "" ||
        this.confirmPassword === ""
      ) {
        alert("You must fill in all required fields");
        return;
      }
      if (this.password !== this.confirmPassword) {
        alert("Passwords do not match");
        return;
      }
      if (
        !this.password.match(
          /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/
        )
      ) {
        alert(
          "Password must contain at least 8 characters, one uppercase letter, one lowercase letter, one number and one special character"
        );
        return;
      }
      try {
        await Auth.signUp({
          username: this.email,
          password: this.password,
          attributes: {
            email: this.email,
          },
        });
        await Auth.signIn({ username: this.email, password: this.password });
        this.email = "";
        this.password = "";
        this.confirmPassword = "";
      } catch (err) {
        if (err.code === "UsernameExistsException") {
          alert("Username already exists");
        }
        console.log(err);
      }
    },
    async signIn() {
      if (this.email === "" || this.password === "") {
        alert("You must fill in all required fields");
        return;
      }
      try {
        await Auth.signIn({ username: this.email, password: this.password });
        this.email = "";
        this.password = "";
      } catch (err) {
        console.log(err);
      }
    },
  },
};
</script>

<style>
/* main > .home-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

main > .register-card {
  display: flex;
  width: 300px;
}
main > .login-card {
  display: flex;
  width: 300px;
}

main > .register-card > form {
  display: flex;
  flex-direction: column;
  align-items: center;
} */

/* html {
  height: 100%;
} */

main > .login-body {
  position: relative;
  height: 90vh;
  margin: 0;
  padding: 0;
  font-family: sans-serif;
  background: linear-gradient(#141e30, #243b55);
}

.login-box {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 400px;
  padding: 40px;
  transform: translate(-50%, -50%);
  background: #0d1520;
  border-radius: 10px;
  box-sizing: border-box;
  box-shadow: 0 15px 25px #0f1824;
}

.login-box h2 {
  margin: 0 0 30px;
  padding: 0;
  color: #03e9f4;
  text-align: center;
}

.login-box .user-box {
  position: relative;
}

.login-box .user-box input {
  width: 100%;
  padding: 10px 0;
  font-size: 16px;
  color: #fff;
  margin-bottom: 30px;
  border: none;
  border-bottom: 1px solid #fff;
  outline: none;
  background: transparent;
}

.login-box .user-box label {
  position: absolute;
  top: 0;
  left: 0;
  padding: 10px 0;
  font-size: 16px;
  color: #fff;
  pointer-events: none;
  transition: 0.5s;
}

.login-box .user-box input:focus ~ label,
.login-box .user-box input:valid ~ label {
  top: -20px;
  left: 0;
  color: #03e9f4;
  font-size: 12px;
}

.login-body form {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 15px;
}

.login-box form button {
  background: #0d1520;
  position: relative;
  display: inline-block;
  padding: 10px 20px;
  color: #03e9f4;
  font-size: 16px;
  text-decoration: none;
  text-transform: uppercase;
  overflow: hidden;
  transition: 0.5s;
  margin-top: 40px;
  letter-spacing: 4px;
  border: none;
}

.login-box form button:hover {
  background: #03e9f4;
  color: #fff;
  border-radius: 5px;
  box-shadow: 0 0 5px #03e9f4, 0 0 25px #03e9f4, 0 0 50px #03e9f4,
    0 0 100px #03e9f4;
}

.login-box button span {
  position: absolute;
  display: block;
}

.login-box p span:hover {
  cursor: pointer;
}

.login-box button span:nth-child(1) {
  top: 0;
  left: -100%;
  width: 100%;
  height: 2px;
  background: linear-gradient(90deg, transparent, #03e9f4);
  animation: btn-anim1 2s linear infinite;
}

@keyframes btn-anim1 {
  0% {
    left: -100%;
  }
  50%,
  100% {
    left: 100%;
  }
}

.login-box button span:nth-child(2) {
  top: -100%;
  right: 0;
  width: 2px;
  height: 100%;
  background: linear-gradient(180deg, transparent, #03e9f4);
  animation: btn-anim2 2s linear infinite;
  animation-delay: 0.5s;
}

@keyframes btn-anim2 {
  0% {
    top: -100%;
  }
  50%,
  100% {
    top: 100%;
  }
}

.login-box button span:nth-child(3) {
  bottom: 0;
  right: -100%;
  width: 100%;
  height: 2px;
  background: linear-gradient(270deg, transparent, #03e9f4);
  animation: btn-anim3 2s linear infinite;
  animation-delay: 1s;
}

@keyframes btn-anim3 {
  0% {
    right: -100%;
  }
  50%,
  100% {
    right: 100%;
  }
}

.login-box button span:nth-child(4) {
  bottom: -100%;
  left: 0;
  width: 2px;
  height: 100%;
  background: linear-gradient(360deg, transparent, #03e9f4);
  animation: btn-anim4 2s linear infinite;
  animation-delay: 1.5s;
}

@keyframes btn-anim4 {
  0% {
    bottom: -100%;
  }
  50%,
  100% {
    bottom: 100%;
  }
}

.login-box p {
  color: #03e8f481;
  margin-top: 15px;
}

.login-box p span {
  color: #03e9f4;
}

.flip-enter-active,
.flip-leave-active {
  transition: all 10s;
  transition-delay: 0.5;
}

.flip-enter-from {
  transform: rotateY(-180deg);
}

.flip-leave-to {
  transform: rotateY(180deg);
}

.flip-reverse-enter-active,
.flip-leave-active {
  transition: all 10s;
  transition-delay: 0.5;
}

.flip-reverse-enter-from {
  transform: rotateY(-180deg);
}

.flip-reverse-leave-to {
  transform: rotateY(180deg);
}
</style>

解決此問題的任何幫助將不勝感激:)

這里有幾件事你需要做:

首先,將兩個元素都放入轉換中,鍵入它們,然后使用mode="out-in"

<transition name="flip" mode="out-in">
    <div key="login" v-if="currentForm === 'login'">...</div>
    <div key="register" v-else>...</div>
</transition>

您的第二個問題是動畫,因為這兩個轉換是沖突的,請改用它。

.flip-enter-active, .flip-leave-active {
  transition: all .5s;
}
.flip-enter, .flip-leave-to {
  transform: translate(-50%, -50%) rotateY(-90deg);
}

這是您的表單的一個非常簡化的版本,您可以復制它以顯示它的工作:

<template>
<main class="login-body">
  
  <transition name="flip" mode="out-in">
    
    <div key="login" class="login-box" v-if="currentForm === 'login'">
      <h2>Login</h2>
      <p>Not Signed Up? <button @click="toggleForm">Sign Up</button></p>
    </div>
    
    <div key="register" class="login-box" v-else>
      <h2>Sign Up</h2>
      <p>Already Signed Up? <button @click="toggleForm">Sign In</button></p>
    </div>
    
  </transition>

</main>

</template>

<script>
  export default {
    name: "HomeView",
    data() {
      return {
        currentForm: "login",
      };
    },
    methods: {
      toggleForm() {
        this.currentForm = this.currentForm === "login" ? "register" : "login";
      },
    },
  };
</script>

<style>

  .login-box {
    position: absolute;
    top: 50%;
    left: 50%;
    width: 400px;
    padding: 40px;
    transform: translate(-50%, -50%);
    background: #ccc;
    box-sizing: border-box;
  }

  .flip-enter-active, .flip-leave-active {
    transition: all .5s;
  }
  .flip-enter, .flip-leave-to {
    transform: translate(-50%, -50%) rotateY(-90deg);
  }

</style>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM