在JS textContent更改时触发CSS动画

时间:2018-10-12 14:53:56

标签: javascript css3

我基本上是在创建一个简单的测验应用程序。现在,当问题不正确时,它将更新问题空间的textContent,以使用户知道他们错了。然后,在setTimeOut之后,它将再次将其更改回问题。

从目前的情况来看,这很好。尽管这些变化立即发生,但我现在希望它们逐渐消失。我一直在尝试通过更改不透明度来弄清楚,尽管现在没有任何影响。所以我想我要么设置动画错误(非常可能),要么我在JavaScript中做错了什么。

所以我要寻找的是

  1. 淡入新的textContent告诉用户该问题是错误的
  2. 等待1秒 3.淡出newTextContent并替换为旧的问题内容。

对于1和3:我认为可以先创建一个简单的关键帧动画然后反转它。 (不透明度100到0%,然后不透明度0%到100)。

  1. 我现在可以使用setTimeout等待1秒钟,因为我不确定如何确保动画触发来执行fadeEffect。

我正在使用Vanilla Js(不推荐使用Jquery),有人可以在这里向我指出正确的方向吗?

Jsfiddle:https://jsfiddle.net/ubw97kfe/ 我添加了注释以指向我要引用的特定代码元素。

// Title of Question Set
const title = document.querySelector(".input_title-input");

// Array of Questions
const questions = [];
let chosen = [];

// Selected Question
let qChosen = [];

// Toggles if a new question is selected
let toggle = 0;

// Selecting Inputs and Button
let question = document.querySelector(".input_question-input");
let answer = document.querySelector(".input_answer-input");
let submit = document.querySelector(".input_submit-button");
let display = document.querySelector(".input_display");
let card = document.querySelector(".card_container");
let start = document.querySelector(".input_start-btn");
let guessInput = document.querySelector(".guess_input");
let submitGuess = document.querySelector(".submitGuess");
let nextQuestion = document.querySelector(".nextQuestion");

// Select all display items
let displayItems = document.getElementsByClassName("input_display-item");

// Select LI quiz card values
let cardQuestion = document.querySelector(".quiz_question");
let cardAnswer = document.querySelector(".quiz_answer");

// Event Listener on Submit Button for Display Items Idividually
submit.addEventListener("click", function() {
    if (question.value === "" || answer.value === "") {
        question.classList.toggle("error");
        answer.classList.toggle("error");
    } else {
        createObj();

        let trashCan = createDisplayItem();
        trashCan.dataset.index = questions.length - 1;
        trashCan.addEventListener("click", function(e) {
            start.disabled = true;
            questions.splice(this.dataset.index, 1);
            // this.parentNode.remove();
            let thisItem = this.parentNode;
            fadeOutIn(thisItem, 1000);

            
            console.log(questions.length);
        });
        inputReset();
        toggle = questions.length;
        start.removeAttribute("disabled");


        console.log(questions.length);
    }
});

start.addEventListener("click", function() {
    generateCard();
    hideInputs();
});




/* ============================================
==============================================*/

// Event Listener to test if guess is correct
submitGuess.addEventListener("click", function() {
    if (guessInput.value.toLowerCase() === qChosen.answer.toLowerCase()) {
        card.classList.toggle("flip");
        submitGuess.disabled = true;
    } else {
        // Insert wrong message here
        cardQuestion.textContent = "You have guessed incorrectly. Please Try Again";
        // SetTimeout to reset back to Chosen Question
        setTimeout(function(){
            cardQuestion.textContent = qChosen.question;
        }, 1000);
    }
});


/* ============================================
==============================================*/


// Selects the Next question
nextQuestion.addEventListener("click", function() {
    card.classList.toggle("flip");
    guessInput.value = "";
    submitGuess.disabled = false;
    setTimeout(generateCard, 1000);
});

// Create The object for inclusion to array
function createObj() {
    let obj = {};
    obj.question = question.value;
    obj.answer = answer.value;
    questions.push(obj);
}

// Resets inputs to blank after submit
function inputReset() {
    question.value = "";
    answer.value = "";
    if (question.classList.contains("error")) {
        question.classList.toggle("error");
        answer.classList.toggle("error");
    }
}

// Creates Each Display Item
function createDisplayItem() {
    // Create new Div
    let newUl = document.createElement("ul");

    // Create Li and Image Elements
    let liQuestion = document.createElement("li");
    let liAnswer = document.createElement("li");
    let trashCan = document.createElement("img");

    // Set img src
    trashCan.src = "../assets/trash.svg";

    // Set classes
    newUl.className = "input_display-item";
    liQuestion.className = "input_display-question";
    liAnswer.className = "input_display-answer";
    trashCan.className = "input_display-delete";

    // Set LI textContent
    liQuestion.textContent = question.value;
    liAnswer.textContent = answer.value;

    // Append Children
    display.appendChild(newUl);
    newUl.appendChild(liQuestion);
    newUl.appendChild(liAnswer);
    return newUl.appendChild(trashCan);
}

//Generating Card Information per question
function generateCard() {
    random();
    if (toggle < 0) {
        cardQuestion.textContent = "There are no more questions left";
        cardAnswer.textContent = "There are no more questions left";
    } else {
        cardQuestion.textContent = qChosen.question;
        cardAnswer.textContent = qChosen.answer;
    }
}

// Choses a random value for the selection set
function random() {
    if (questions.length === 0) {
        toggle = -1;
    } else {
        let num = Math.floor(Math.random() * questions.length);
        chosen = questions.splice(num, 1).concat(chosen);
        qChosen = chosen[0];
    }
}

// hides all the inputs when start quiz is selected
function hideInputs(){
    for(let i = 0; i < displayItems.length; i++){
        fadeOutIn(displayItems[i], 1000);
    }
}

// FadeOut the display items when trashCan is clicked.
function fadeOutIn(elem, speed){
    if(!elem.style.opacity){
        elem.style.opacity = 1;
    }

    var outInterval = setInterval(function(){
        elem.style.opacity -= 0.02;
        if(elem.style.opacity <=0){
            clearInterval(outInterval);
            elem.remove();
        }
    }, speed/50)
}
/** Variables
 ---------------------------------------------------------*/
/** Reset
 ---------------------------------------------------------*/
* {
  margin: 0;
  padding: 0; }

*,
*::before,
*::after {
  -webkit-box-sizing: inherit;
  box-sizing: inherit; }

html {
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  font-size: 62.5%; }

body {
  font-weight: 400;
  line-height: 1.5;
  font-size: 2rem;
  background-color: #bdbdc7; }

/** Primary Container
 ---------------------------------------------------------*/
.container {
  max-width: 180rem;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex; }

.flex {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  justify-content: center;
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center; }

.fadeOut {
  visibility: hidden;
  transition: all 0.5s ease-out; }

/** Input Section
 ---------------------------------------------------------*/
input[type="text"] {
  padding: 0.5rem;
  width: auto;
  min-width: 100%;
  line-height: 2rem; }

.input {
  width: 40rem;
  height: 100vh;
  padding: 1rem;
  background-color: #ccc;
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-align: start;
  -ms-flex-align: start;
  align-items: flex-start;
  -webkit-box-orient: vertical;
  -webkit-box-direction: normal;
  -ms-flex-direction: column;
  flex-direction: column; }
  .input_title {
    width: 100%;
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-orient: vertical;
    -webkit-box-direction: normal;
    -ms-flex-direction: column;
    flex-direction: column; }
    .input_title-label {
      display: -webkit-box;
      display: -ms-flexbox;
      display: flex;
      -webkit-box-pack: center;
      -ms-flex-pack: center;
      justify-content: center; }
    .input_title-input {
      padding: 0.5rem; }
  .input_question {
    width: 100%;
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-orient: vertical;
    -webkit-box-direction: normal;
    -ms-flex-direction: column;
    flex-direction: column; }
    .input_question-label {
      display: -webkit-box;
      display: -ms-flexbox;
      display: flex;
      -webkit-box-pack: center;
      -ms-flex-pack: center;
      justify-content: center; }
    .input_question-input {
      padding: 0.5rem; }
  .input_answer {
    width: 100%;
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-orient: vertical;
    -webkit-box-direction: normal;
    -ms-flex-direction: column;
    flex-direction: column; }
    .input_answer-label {
      display: -webkit-box;
      display: -ms-flexbox;
      display: flex;
      -webkit-box-pack: center;
      -ms-flex-pack: center;
      justify-content: center; }
    .input_answer-input {
      padding: 0.5rem; }
  .input_question-input.error, .input_answer-input.error {
    border: 2px red solid; }
  .input_submit {
    width: 100%; }
    .input_submit-button {
      margin-top: 1rem;
      padding: 0 1.5rem; }
  .input_start {
    width: 100%; }
  .input_display {
    width: 100%;
    font-size: 1.5rem;
    padding: 2rem 0 1rem 0; }
    .input_display-item {
      margin-bottom: 1rem;
      padding: .2rem 2rem;
      text-transform: capitalize;
      background-color: #fff;
      border-radius: 1rem;
      list-style: none;
      display: -webkit-box;
      display: -ms-flexbox;
      display: flex;
      -webkit-box-pack: justify;
      -ms-flex-pack: justify;
      justify-content: space-between;
      -webkit-box-align: center;
      -ms-flex-align: center;
      align-items: center; }
    .input_display-item:nth-child(odd) {
      background-color: #aaa;
      border-radius: 1rem; }
    .input_display-delete {
      height: 1.8rem;
      width: 1.8rem; }

.input :not(.input_display) div {
  padding-bottom: 2rem; }

/** Quiz Card
 ---------------------------------------------------------*/
.card {
  display: -webkit-box;
  display: -ms-flexbox;
  display: flex;
  -webkit-box-pack: center;
  -ms-flex-pack: center;
  justify-content: center;
  -webkit-box-align: center;
  -ms-flex-align: center;
  align-items: center;
  width: 100%; }
  .card_container {
    -webkit-transform-style: preserve-3d;
    transform-style: preserve-3d;
    -webkit-perspective: 1000px;
    perspective: 1000px;
    width: 60rem;
    margin: 1rem;
    cursor: pointer; }
    .card_container .front {
      -webkit-transform: rotateY(0deg);
      transform: rotateY(0deg);
      -webkit-transform-style: preserve-3d;
      transform-style: preserve-3d; }
      .card_container .front:after {
        position: absolute;
        top: 0;
        left: 0;
        z-index: 1;
        width: 100%;
        height: 100%;
        content: "";
        display: block;
        opacity: 0.6;
        background-color: #000;
        -webkit-backface-visibility: hidden;
        backface-visibility: hidden;
        border-radius: 10px; }
    .card_container .back {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      background-color: #cedce7;
      background: linear-gradient(45deg, #dedce7 0%, #596a72 100%);
      -webkit-transform: rotateY(180deg);
      transform: rotateY(180deg);
      -webkit-transform-style: preserve-3d;
      transform-style: preserve-3d; }
    .card_container .front,
    .card_container .back {
      background-color: red;
      background-size: cover;
      background-position: center;
      -webkit-transition: -webkit-transform 0.7s cubic-bezier(0.4, 0.2, 0.2, 1);
      transition: -webkit-transform 0.7s cubic-bezier(0.4, 0.2, 0.2, 1);
      transition: transform 0.7s cubic-bezier(0.4, 0.2, 0.2, 1);
      transition: transform 0.7s cubic-bezier(0.4, 0.2, 0.2, 1), -webkit-transform 0.7s cubic-bezier(0.4, 0.2, 0.2, 1);
      transition: transform 0.7s cubic-bezier(0.4, 0.2, 0.2, 1);
      -webkit-backface-visibility: hidden;
      backface-visibility: hidden;
      text-align: center;
      min-height: 500px;
      height: auto;
      border-radius: 10px;
      color: #fff;
      font-size: 1.5rem; }

.flip {
  -webkit-transition: -webkit-transform 0.7s cubic-bezier(0.4, 0.2, 0.2, 1);
  transition: -webkit-transform 0.7s cubic-bezier(0.4, 0.2, 0.2, 1);
  transition: transform 0.7s cubic-bezier(0.4, 0.2, 0.2, 1);
  transition: transform 0.7s cubic-bezier(0.4, 0.2, 0.2, 1), -webkit-transform 0.7s cubic-bezier(0.4, 0.2, 0.2, 1);
  transition: transform 0.7s cubic-bezier(0.4, 0.2, 0.2, 1); }
  .flip .back {
    -webkit-transform: rotateY(0deg);
    transform: rotateY(0deg);
    -webkit-transform-style: preserve-3d;
    transform-style: preserve-3d; }
  .flip .front {
    -webkit-transform: rotateY(-180deg);
    transform: rotateY(-180deg);
    -webkit-transform-style: preserve-3d;
    transform-style: preserve-3d; }

.inner {
  -webkit-transform: translateY(-50%) translateZ(60px) scale(0.94);
  transform: translateY(-50%) translateZ(60px) scale(0.94);
  top: 50%;
  position: absolute;
  left: 0;
  width: 100%;
  padding: 2rem;
  -webkit-box-sizing: border-box;
  box-sizing: border-box;
  outline: 1px solid transparent;
  -webkit-perspective: inherit;
  perspective: inherit;
  z-index: 2; }


/* The particular element applying the animation
==============================================*/

.quiz_question {
  animation: fade 10s linear; }

/* ============================================
==============================================*/



.front .inner p {
  font-size: 2rem;
  margin-bottom: 2rem;
  position: relative; }

.card_container-guess {
  padding-top: 2rem; }
  .card_container-guess .guess_input {
    width: 2rem;
    margin: 1rem auto;
    padding: 1rem;
    border-radius: 1rem;
    -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.55), 0px 1px 1px rgba(255, 255, 255, 0.5);
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.55), 0px 1px 1px rgba(255, 255, 255, 0.5);
    border: 1px solid #666;
    opacity: 0.6;
    outline: none; }
    .card_container-guess .guess_input:hover, .card_container-guess .guess_input:focus {
      opacity: .8;
      color: #08c;
      -webkit-box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25), inset 0px 3px 6px rgba(0, 0, 0, 0.25);
      box-shadow: 0px 1px 0px rgba(255, 255, 255, 0.25), inset 0px 3px 6px rgba(0, 0, 0, 0.25); }
  .card_container-guess-buttons {
    display: -webkit-box;
    display: -ms-flexbox;
    display: flex;
    -webkit-box-pack: justify;
    -ms-flex-pack: justify;
    justify-content: space-between; }
    .card_container-guess-buttons .btnNew {
      margin: 1rem 2rem; }

.btnNew {
  height: 5rem;
  width: 12rem;
  margin: 1.5rem 3rem 1rem 1rem;
  font-weight: 700;
  color: #333;
  background-image: -webkit-gradient(linear, left top, left bottom, from(#f4f1ee), to(#fff));
  background-image: linear-gradient(to bottom, #f4f1ee, #fff);
  -webkit-box-shadow: 0px 8px 30px 1px rgba(0, 0, 0, 0.3), inset 0px 4px 1px 1px white, inset 0px -3px 1px 1px rgba(204, 198, 197, 0.5);
  box-shadow: 0px 8px 30px 1px rgba(0, 0, 0, 0.3), inset 0px 4px 1px 1px white, inset 0px -3px 1px 1px rgba(204, 198, 197, 0.5);
  border-radius: 5%;
  position: relative;
  -webkit-transition: all .1s linear;
  transition: all .1s linear;
  outline: none; }

.btnNew:after {
  color: #e9e6e4;
  content: "";
  display: block;
  font-size: 30px;
  height: 3rem;
  text-decoration: none;
  text-shadow: 0px -1px 1px #bdb5b4, 1px 1px 1px white;
  position: absolute;
  width: 3rem; }

.btnNew:hover {
  background-image: -webkit-gradient(linear, left top, left bottom, from(#fff), to(#f4f1ee));
  background-image: linear-gradient(to bottom, #fff, #f4f1ee);
  color: #0088cc; }

.btnNew:active {
  background-image: -webkit-gradient(linear, left top, left bottom, from(#efedec), to(#f7f4f4));
  background-image: linear-gradient(to bottom, #efedec, #f7f4f4);
  -webkit-box-shadow: 0 3px 5px 0 rgba(0, 0, 0, 0.4), inset opx -3px 1px 1px rgba(204, 198, 197, 0.5);
  box-shadow: 0 3px 5px 0 rgba(0, 0, 0, 0.4), inset opx -3px 1px 1px rgba(204, 198, 197, 0.5);
  outline: none; }

.btnNew:active:after {
  color: #dbd2d2;
  text-shadow: 0px -1px 1px #bdb5b4, 0px 1px 1px white;
  outline: none; }


/* KeyFrame Animation in question */
@keyframes fade {
  0% {
    opacity: 100%; }
  100% {
    opacity: 0%; } }
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Flash</title>

    <!-- Custom CSS -->
    <link rel="stylesheet" href="css/main.css">
</head>

<body>
    <div class="container">
        <section class="input">
            <div class="input_title">
                <label class="input_title-label" for="title">Enter a Title</label>
                <input class="input_title-input" id="title" type="text" placeholder="List of Towels">
            </div>

            <div class="input_question">
                <label class="input_question-label" for="question">Enter a Question</label>
                <input class="input_question-input" id="question" type="text" placeholder="What is 42?">
            </div>

            <div class="input_answer">
                <label class="input_answer-label" for="answer">Enter an Answer</label>
                <input class="input_answer-input" id="answer" type="text" placeholder="The Meaning Life, Universe, and Everything">
            </div>

            <div class="input_submit flex">
                <button class="input_submit-button btnNew">Submit</button>
            </div>

            <div class="input_display"></div>

            <div class="input_start flex">
                <button type="button" class="input_start-btn btnNew" disabled>Start Quiz</button>
            </div>
        </section>

        <section class="card">
            <div class="card_container">
                <div class="front">
                    <div class="inner">
                        <p class="quiz_question">Please Set Some Questions Up</p>
                    </div>
                </div>

                <div class="back">
                    <div class="inner">
                        <p class="quiz_answer"></p>
                    </div>
                </div>

                <div class="card_container-guess">
                    <input type="text" class="guess_input">
                    <div class="card_container-guess-buttons">
                        <button class="submitGuess btnNew">Submit Guess</button>
                        <button class="nextQuestion btnNew">Next Question</button>
                    </div>
                </div>
            </div>
        </section>
    </div>


    <!-- Custom JS -->
    <script src="js/scripts.js"></script>
</body>

</html>

1 个答案:

答案 0 :(得分:1)

主要问题是您想用另一个字符串替换一个字符串。因此,您不能真正地同时淡出第一个和第二个。您可以将另一张卡片制作为溢出卡片并将其放在问题卡片上,这样您就可以更好地控制动画和文本样式。

我用这个替换了submitGuess.addEventListener

    // Event Listener to test if guess is correct
submitGuess.addEventListener("click", function() {
  if (guessInput.value.toLowerCase() === qChosen.answer.toLowerCase()) {
    card.classList.toggle("flip");
    submitGuess.disabled = true;
  } else {
    // Insert wrong message here
    cardQuestion.style.animation="colorfadeerr 0.5s ease-in-out forwards";
    // SetTimeout to reset back to Chosen Question
    setTimeout(function(){
      cardQuestion.style.animation="colorfadequestion 0.3s ease-in-out";            
    }, 1500);
  }
});

cardQuestion.addEventListener("animationstart", function() {
  if(cardQuestion.textContent === qChosen.question)
    cardQuestion.textContent = "You have guessed incorrectly. Please Try Again";
  else
    cardQuestion.textContent = qChosen.question;
});

并将其添加到CSS中:

@keyframes colorfadeerr {
  0% {
    color: rgba(255,255,255,0.0); }
  10% {
    color: rgba(255,255,255,0.0); } 
  100% {
    color: rgba(255,200,200,1.0); } 
    }

@keyframes colorfadequestion {
  0% {
    color: rgba(255,255,255,0.0); }
  30% {
    color: rgba(255,255,255,0.0); } 
  100% {
    color: rgba(255,255,255,1.0); } 
    }

第一个动画将隐藏文本,并以另一种颜色显示错误消息。第二个动画将再次向您显示第一个文本(白色)。

我不知道这是否可以帮助您。我试图让它类似于您的代码。但是如前所述,如果您可以在问题上再放一张卡片,效果会更好。因此,您可以同时淡出问题和淡入错误消息。