css Flashcard的幻灯片与Angular

falq053o  于 2024-01-09  发布在  Angular
关注(0)|答案(1)|浏览(140)

背景资料

我正在用Angular制作一个抽认卡Web应用程序,我在让抽认卡滑入和滑出视图时遇到了一些困难。该应用程序允许用户通过 *input's * 添加抽认卡,然后将其保存为cookie。然后用户可以使用 next/previous 按钮浏览抽认卡,并使用 Remove Current Card 按钮删除抽认卡。当用户单击当前显示的抽认卡时,当用户在抽认卡之间导航时,无论他们最后是在正面还是背面离开卡片,他们总是出现在卡片的正面。

问题

到目前为止,只有一个物理html元素被认为是 flashcard。在单击 next/previous 时,此flashcard然后滑出视图,被新的卡片内容替换,并从退出的同一侧滑回视图。相反,当用户按下 next/previous 按钮时,我希望卡片滑出视图的相应一侧,而“新卡”从另一侧滑入。
我尝试了几种不同的方法,包括在实际卡片的两侧添加一张额外的卡片,以及各种css转换和动画,但无法顺利实现。

验证码

为了这个片段的目的,我已经删除了用户动态添加和删除抽认卡的功能。

var app = angular.module('flashcardApp', []);
app.controller('FlashcardController', function($scope, $timeout) {
  this.flashcards = [{
      frontContent: 'Front of Card 1',
      backContent: 'Back of Card 1',
      isFlipped: false
    },
    {
      frontContent: 'Front of Card 2',
      backContent: 'Back of Card 2',
      isFlipped: false
    },
    {
      frontContent: 'Front of Card 3',
      backContent: 'Back of Card 3',
      isFlipped: false
    },
    {
      frontContent: 'Front of Card 4',
      backContent: 'Back of Card 4',
      isFlipped: false
    }
  ];

  this.currentCardIndex = 0;
  this.animating = false;

  this.flipCard = function() {
    if (!this.animating) {
      this.flashcards[this.currentCardIndex].isFlipped = !this.flashcards[this.currentCardIndex].isFlipped;
    }
  };

  this.nextCard = function() {
    if (this.currentCardIndex < this.flashcards.length - 1 && !this.animating) {
      this.animating = true;
      this.slideRight = true;
      $timeout(() => {
        this.slideRight = false;
        this.currentCardIndex++;
        this.flashcards[this.currentCardIndex].isFlipped = false;
        $timeout(() => this.animating = false, 100);
      }, 600);
    }
  };

  this.previousCard = function() {
    if (this.currentCardIndex > 0 && !this.animating) {
      this.animating = true;
      this.slideLeft = true;
      $timeout(() => {
        this.slideLeft = false;
        this.currentCardIndex--;
        this.flashcards[this.currentCardIndex].isFlipped = false;
        $timeout(() => this.animating = false, 100);
      }, 600);
    }
  };
});
body,
html {
  height: 100%;
  margin: 0;
  font-family: 'Arial', sans-serif;
  background-color: #f7f7f7;
  color: #444;
}

.flashcard-container {
  perspective: 1000px;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  position: relative;
}

.flashcard-wrapper {
  width: 50%;
  height: 60vh;
  margin: auto;
  position: relative;
  z-index: 1;
  transition: transform 0.6s ease;
}

.flashcard {
  width: 100%;
  height: 100%;
  border-radius: 15px;
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
  background-color: #ffffff;
  border: 1px solid #e0e0e0;
  position: relative;
  transform-style: preserve-3d;
  cursor: pointer;
  user-select: none;
}

.flashcard,
.front,
.back {
  transition: transform 0.6s ease;
}

.flashcard.flipped {
  transform: rotateY(180deg);
}

.front,
.back {
  position: absolute;
  width: 100%;
  height: 100%;
  backface-visibility: hidden;
  border-radius: 15px;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 24px;
  padding: 20px;
  box-sizing: border-box;
}

.back {
  transform: rotateY(180deg);
  background-color: #eeeeee;
}

.navigation-btn {
  padding: 10px 20px;
  margin: 20px;
  border: none;
  border-radius: 5px;
  background-color: #2c3e50;
  color: white;
  font-size: 16px;
  cursor: pointer;
  transition: background-color 0.3s ease;
  position: absolute;
  z-index: 2;
}

.navigation-btn.previous {
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
}

.navigation-btn.next {
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
}

.slide-left {
  transform: translateX(-150%);
}

.slide-right {
  transform: translateX(150%);
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
<div class="flashcard-container" ng-app="flashcardApp" ng-controller="FlashcardController as flashCtrl">
  <button class="navigation-btn previous" ng-disabled="flashCtrl.currentCardIndex === 0" ng-click="flashCtrl.previousCard()">Previous</button>
  <div class="flashcard-wrapper" ng-class="{ 'slide-left': flashCtrl.slideLeft, 'slide-right': flashCtrl.slideRight }">
    <div class="flashcard" ng-class="{ flipped: flashCtrl.flashcards[flashCtrl.currentCardIndex].isFlipped }" ng-click="flashCtrl.flipCard()">
      <div class="front" ng-show="!flashCtrl.flashcards[flashCtrl.currentCardIndex].isFlipped">
        <p>{{ flashCtrl.flashcards[flashCtrl.currentCardIndex].frontContent }}</p>
      </div>
      <div class="back" ng-show="flashCtrl.flashcards[flashCtrl.currentCardIndex].isFlipped">
        <p>{{ flashCtrl.flashcards[flashCtrl.currentCardIndex].backContent }}</p>
      </div>
    </div>
  </div>
  <button class="navigation-btn next" ng-disabled="flashCtrl.currentCardIndex === flashCtrl.flashcards.length - 1" ng-click="flashCtrl.nextCard()">Next</button>
</div>

正如你在上面的片段中看到的,抽认卡从同一侧退出和重新进入,而我希望它们以类似于图像旋转木马的方式从相反的两侧退出和进入。任何建议都非常感谢!

bkhjykvo

bkhjykvo1#

我已经想出了一个解决方案,似乎是工作...我现在滑动卡在所需的方向,消除过渡效果(transform 0.6s ease),然后重新定位卡到屏幕的对面,然后调用对面的滑动效果。我注意到偶尔虽然它会出现小故障或表现略有不同,所以如果有人有替代解决方案,我很想听听!

var app = angular.module('flashcardApp', []);
app.controller('FlashcardController', function($scope, $timeout) {
  this.flashcards = [{
      frontContent: 'Front of Card 1',
      backContent: 'Back of Card 1',
      isFlipped: false
    },
    {
      frontContent: 'Front of Card 2',
      backContent: 'Back of Card 2',
      isFlipped: false
    },
    {
      frontContent: 'Front of Card 3',
      backContent: 'Back of Card 3',
      isFlipped: false
    },
    {
      frontContent: 'Front of Card 4',
      backContent: 'Back of Card 4',
      isFlipped: false
    }
  ];

  this.currentCardIndex = 0;
  this.animating = false;

  this.flipCard = function() {
    if (!this.animating) {
      this.flashcards[this.currentCardIndex].isFlipped = !this.flashcards[this.currentCardIndex].isFlipped;
    }
  };

  this.nextCard = function() {
    if (this.currentCardIndex < this.flashcards.length - 1 && !this.animating) {
      this.animating = true;
      var wrapper = angular.element(document.querySelector('.flashcard-wrapper'));

      this.slideLeft = true;

      $timeout(() => {
        this.currentCardIndex++;
        this.flashcards[this.currentCardIndex].isFlipped = false;

        this.slideLeft = false;
        this.hideCard = true;
        wrapper.css('transition', 'none');

        $timeout(() => {
          this.hideCard = false;
          this.slideRight = true;

          $timeout(() => {
            wrapper.css('transition', 'transform 0.6s ease');

            $timeout(() => {
              this.slideRight = false;
              this.animating = false;
            }, 600);
          }, 20);

        }, 20);

      }, 600);
    }
  };


  this.previousCard = function() {
    if (this.currentCardIndex > 0 && !this.animating) {
      this.animating = true;
      var wrapper = angular.element(document.querySelector('.flashcard-wrapper'));

      this.slideRight = true;

      $timeout(() => {
        this.currentCardIndex--;
        this.flashcards[this.currentCardIndex].isFlipped = false;

        this.slideRight = false;
        this.hideCard = true;
        wrapper.css('transition', 'none');

        $timeout(() => {
          this.hideCard = false;
          this.slideLeft = true;

          $timeout(() => {
            wrapper.css('transition', 'transform 0.6s ease');

            $timeout(() => {
              this.slideLeft = false;
              this.animating = false;
            }, 600);
          }, 20);

        }, 20);

      }, 600);
    }
  };

});
body,
html {
  height: 100%;
  margin: 0;
  font-family: 'Arial', sans-serif;
  background-color: #f7f7f7;
  color: #444;
}

.flashcard-container {
  perspective: 1000px;
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  position: relative;
}

.flashcard-wrapper {
  width: 50%;
  height: 60vh;
  margin: auto;
  position: relative;
  z-index: 1;
  transition: transform 0.6s ease;
}

.flashcard {
  width: 100%;
  height: 100%;
  border-radius: 15px;
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
  background-color: #ffffff;
  border: 1px solid #e0e0e0;
  position: relative;
  transform-style: preserve-3d;
  cursor: pointer;
  user-select: none;
}

.flashcard,
.front,
.back {
  transition: transform 0.6s ease;
}

.flashcard.flipped {
  transform: rotateY(180deg);
}

.front,
.back {
  position: absolute;
  width: 100%;
  height: 100%;
  backface-visibility: hidden;
  border-radius: 15px;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 24px;
  padding: 20px;
  box-sizing: border-box;
}

.back {
  transform: rotateY(180deg);
  background-color: #eeeeee;
}

.navigation-btn {
  padding: 10px 20px;
  margin: 20px;
  border: none;
  border-radius: 5px;
  background-color: #2c3e50;
  color: white;
  font-size: 16px;
  cursor: pointer;
  transition: background-color 0.3s ease;
  position: absolute;
  z-index: 2;
}

.navigation-btn.previous {
  left: 10px;
  top: 50%;
  transform: translateY(-50%);
}

.navigation-btn.next {
  right: 10px;
  top: 50%;
  transform: translateY(-50%);
}

.slide-left {
  transform: translateX(-150%);
}

.slide-right {
  transform: translateX(150%);
}

.hidden-card {
  position: absolute;
  left: -100%;
  z-index: -1;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
<div class="flashcard-container" ng-app="flashcardApp" ng-controller="FlashcardController as flashCtrl">
  <button class="navigation-btn previous" ng-disabled="flashCtrl.currentCardIndex === 0" ng-click="flashCtrl.previousCard()">Previous</button>
  <div class="flashcard-wrapper" ng-class="{ 'hidden-card': flashCtrl.hideCard, 'slide-left': flashCtrl.slideLeft, 'slide-right': flashCtrl.slideRight }">
    <div class="flashcard" ng-class="{ flipped: flashCtrl.flashcards[flashCtrl.currentCardIndex].isFlipped }" ng-click="flashCtrl.flipCard()">
      <div class="front" ng-show="!flashCtrl.flashcards[flashCtrl.currentCardIndex].isFlipped">
        <p>{{ flashCtrl.flashcards[flashCtrl.currentCardIndex].frontContent }}</p>
      </div>
      <div class="back" ng-show="flashCtrl.flashcards[flashCtrl.currentCardIndex].isFlipped">
        <p>{{ flashCtrl.flashcards[flashCtrl.currentCardIndex].backContent }}</p>
      </div>
    </div>
  </div>
  <button class="navigation-btn next" ng-disabled="flashCtrl.currentCardIndex === flashCtrl.flashcards.length - 1" ng-click="flashCtrl.nextCard()">Next</button>
</div>

相关问题