抽认卡通过 Angular 滑入滑出

问题描述 投票:0回答:1

背景信息

我正在使用 Angular 制作抽认卡 Web 应用程序,但在让抽认卡滑入和滑出视图时遇到一些困难。该应用程序允许用户通过input's添加抽认卡,然后将其保存为cookie。然后,用户可以使用“下一个/上一个”按钮浏览抽认卡,并使用“删除当前卡”按钮删除抽认卡。当用户单击当前显示的抽认卡时,它会将其翻转并在背面显示内容。当用户在抽认卡之间导航时,无论他们最后将卡片留在正面还是背面,它们始终会出现在卡片的正面。 问题

截至目前,只有一个物理 html 元素被视为 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>


正如您在上面的代码片段中看到的,抽认卡从同一侧退出和重新进入,而我希望它们以与图像轮播类似的方式从相反侧退出和进入。非常感谢任何建议!

我已经找到了一个似乎有效的解决方案...我现在正在将卡滑向所需的方向,删除过渡效果(

transform 0.6s ease

),然后将卡重新定位到屏幕的另一侧,然后调用相反的滑动效果。我偶尔注意到它会出现故障或行为略有不同,所以如果有人有替代解决方案,我很乐意听到它!

javascript html css angular
1个回答
0
投票

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>


    
© www.soinside.com 2019 - 2024. All rights reserved.