背景信息
我正在使用 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
),然后将卡重新定位到屏幕的另一侧,然后调用相反的滑动效果。我偶尔注意到它会出现故障或行为略有不同,所以如果有人有替代解决方案,我很乐意听到它!
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>