我对这个CodePen感兴趣:
https://codepen.io/rachsmith/pen/PWxoLN
问题是JavaScript代码仅考虑每张卡在展开时都会具有相同的文本,并且文本包含在代码中。
作者提到这只是一种练习,我很喜欢这个工作不依赖任何外部资源这一事实。
那么我该如何更改代码,以便为单击的卡分配正确的文本?
考虑我计划只拥有两张卡。这是我在将文本插入卡片文本字段内的函数上尝试过的:
function animateCoverUp(card) {
// get the position of the clicked card
var cardPosition = card.getBoundingClientRect();
// get the style of the clicked card
var cardStyle = getComputedStyle(card);
setCoverPosition(cardPosition);
setCoverColor(cardStyle);
scaleCoverToFillWindow(cardPosition);
// update the content of the opened page
if (cards[0]) {
openContentText.innerHTML = '<h1>'+card.children[2].textContent+'</h1>'+paragraphText0;
openContentImage.src = card.children[1].src;
} else if (cards[1]) {
openContentText.innerHTML = '<h1>'+card.children[2].textContent+'</h1>'+paragraphText1;
openContentImage.src = card.children[1].src;
}
setTimeout(function() {
// update the scroll position to 0 (so it is at the top of the 'opened' page)
window.scroll(0, 0);
// set page to open
pageIsOpen = true;
}, 300);
}
基本上我已经将其添加到原始函数中,但是它不起作用,并且一直在注入paragraphText0:
if (cards[0]) {
openContentText.innerHTML = '<h1>'+card.children[2].textContent+'</h1>'+paragraphText0;
openContentImage.src = card.children[1].src;
} else if (cards[1]) {
openContentText.innerHTML = '<h1>'+card.children[2].textContent+'</h1>'+paragraphText1;
openContentImage.src = card.children[1].src;
}
答案 0 :(得分:1)
创建文本返回的函数,而不是将文本存储在全局变量paragraphText
中,具体取决于所单击的卡片的索引:
function getFullText(cardIndex) {
switch (cardIndex) {
case 0:
return (
"Somebody once told me the world is gonna roll me. " +
"I ain't the sharpest tool in the shed. " +
"She was looking kind of dumb with her finger and her thumb. " +
'In the shape of an "L" on her forehead.'
);
case 1:
return (
"Well the years start coming and they don't stop coming. " +
"Fed to the rules and I hit the ground running. " +
"Didn't make sense not to live for fun. " +
"Your brain gets smart but your head gets dumb."
);
case 2:
return (
"So much to do, so much to see. " +
"So what's wrong with taking the back streets? " +
"You'll never know if you don't go. " +
"You'll never shine if you don't glow."
);
case 3:
return (
"It's a cool place and they say it gets colder. " +
"You're bundled up now, wait till you get older. " +
"But the meteor men beg to differ. " +
"Judging by the hole in the satellite picture."
);
default:
throw new Error("unknown card index", cardIndex);
}
}
参数cardIndex
是被点击的卡片的从零开始的数字。
从onCardClick
调用此函数,然后将结果传递到animateCoverUp
,如下所示:
function onCardClick(card, i) {
var fullText = getFullText(i);
// set the current card
currentCard = card;
// add the 'clicked' class to the card, so it animates out
currentCard.className += " clicked";
// animate the card 'cover' after a 500ms delay
// pass the index
setTimeout(function() {
animateCoverUp(currentCard, fullText);
}, 500);
// animate out the other cards
animateOtherCards(currentCard, true);
// add the open class to the page content
openContent.className += " open";
}
最后,在animateCoverUp
中,使用第二个参数,即全文本,而不是全局变量paragraphText
(您可以将其删除):
function animateCoverUp(card, fullText) {
// get the position of the clicked card
var cardPosition = card.getBoundingClientRect();
// get the style of the clicked card
var cardStyle = getComputedStyle(card);
setCoverPosition(cardPosition);
setCoverColor(cardStyle);
scaleCoverToFillWindow(cardPosition);
// update the content of the opened page
openContentText.innerHTML =
"<h1>" + card.children[2].textContent + "</h1>" + fullText;
openContentImage.src = card.children[1].src;
setTimeout(function() {
// update the scroll position to 0 (so it is at the top of the 'opened' page)
window.scroll(0, 0);
// set page to open
pageIsOpen = true;
}, 300);
}
这是电笔的有效版本:
答案 1 :(得分:-1)
此解决方案以及此Codepen均未遵循良好实践。您绝对不应该通过JS放置属于HTML的内容。但是,我并不想重写所有内容,这是使它按您希望的方式工作的最简单方法。我只创建了4个变量,您需要将它们放入其中。然后在HTML中使用data-id
属性来区分这些卡片。点击时,您传递card
DOM元素,我们只需要访问data-id
=> var cardId = card.getAttribute('data-id')
。然后将该数字分配给变量名=> eval('paragraphText' + cardId);
(在访问时为typeof字符串)。函数eval()
尝试运行您作为JS代码传递给它的所有内容,以便它获取具有变量名的字符串,例如'paragraphText1'
,并将其转换为JS变量paragraphText1
。
// listing vars here so they're in the global scope
var cards, nCards, cover, openContent, openContentText, pageIsOpen = false,
openContentImage, closeContent, windowWidth, windowHeight, currentCard;
// initiate the process
init();
function init() {
resize();
selectElements();
attachListeners();
}
// select all the elements in the DOM that are going to be used
function selectElements() {
cards = document.getElementsByClassName('card'),
nCards = cards.length,
cover = document.getElementById('cover'),
openContent = document.getElementById('open-content'),
openContentText = document.getElementById('open-content-text'),
openContentImage = document.getElementById('open-content-image')
closeContent = document.getElementById('close-content');
}
/* Attaching three event listeners here:
- a click event listener for each card
- a click event listener to the close button
- a resize event listener on the window
*/
function attachListeners() {
for (var i = 0; i < nCards; i++) {
attachListenerToCard(i);
}
closeContent.addEventListener('click', onCloseClick);
window.addEventListener('resize', resize);
}
function attachListenerToCard(i) {
cards[i].addEventListener('click', function(e) {
var card = getCardElement(e.target);
onCardClick(card, i);
})
}
/* When a card is clicked */
function onCardClick(card, i) {
// set the current card
currentCard = card;
// add the 'clicked' class to the card, so it animates out
currentCard.className += ' clicked';
// animate the card 'cover' after a 500ms delay
setTimeout(function() {animateCoverUp(currentCard)}, 500);
// animate out the other cards
animateOtherCards(currentCard, true);
// add the open class to the page content
openContent.className += ' open';
}
/*
* This effect is created by taking a separate 'cover' div, placing
* it in the same position as the clicked card, and animating it to
* become the background of the opened 'page'.
* It looks like the card itself is animating in to the background,
* but doing it this way is more performant (because the cover div is
* absolutely positioned and has no children), and there's just less
* having to deal with z-index and other elements in the card
*/
function animateCoverUp(card) {
// get the position of the clicked card
var cardPosition = card.getBoundingClientRect();
// get the style of the clicked card
var cardStyle = getComputedStyle(card);
setCoverPosition(cardPosition);
setCoverColor(cardStyle);
scaleCoverToFillWindow(cardPosition);
// update the content of the opened page
var cardId = card.getAttribute('data-id')
openContentText.innerHTML = '<h1>'+card.children[2].textContent+'</h1>'+ eval('paragraphText' + cardId);
openContentImage.src = card.children[1].src;
setTimeout(function() {
// update the scroll position to 0 (so it is at the top of the 'opened' page)
window.scroll(0, 0);
// set page to open
pageIsOpen = true;
}, 300);
}
function animateCoverBack(card) {
var cardPosition = card.getBoundingClientRect();
// the original card may be in a different position, because of scrolling, so the cover position needs to be reset before scaling back down
setCoverPosition(cardPosition);
scaleCoverToFillWindow(cardPosition);
// animate scale back to the card size and position
cover.style.transform = 'scaleX('+1+') scaleY('+1+') translate3d('+(0)+'px, '+(0)+'px, 0px)';
setTimeout(function() {
// set content back to empty
openContentText.innerHTML = '';
openContentImage.src = '';
// style the cover to 0x0 so it is hidden
cover.style.width = '0px';
cover.style.height = '0px';
pageIsOpen = false;
// remove the clicked class so the card animates back in
currentCard.className = currentCard.className.replace(' clicked', '');
}, 301);
}
function setCoverPosition(cardPosition) {
// style the cover so it is in exactly the same position as the card
cover.style.left = cardPosition.left + 'px';
cover.style.top = cardPosition.top + 'px';
cover.style.width = cardPosition.width + 'px';
cover.style.height = cardPosition.height + 'px';
}
function setCoverColor(cardStyle) {
// style the cover to be the same color as the card
cover.style.backgroundColor = cardStyle.backgroundColor;
}
function scaleCoverToFillWindow(cardPosition) {
// calculate the scale and position for the card to fill the page,
var scaleX = windowWidth / cardPosition.width;
var scaleY = windowHeight / cardPosition.height;
var offsetX = (windowWidth / 2 - cardPosition.width / 2 - cardPosition.left) / scaleX;
var offsetY = (windowHeight / 2 - cardPosition.height / 2 - cardPosition.top) / scaleY;
// set the transform on the cover - it will animate because of the transition set on it in the CSS
cover.style.transform = 'scaleX('+scaleX+') scaleY('+scaleY+') translate3d('+(offsetX)+'px, '+(offsetY)+'px, 0px)';
}
/* When the close is clicked */
function onCloseClick() {
// remove the open class so the page content animates out
openContent.className = openContent.className.replace(' open', '');
// animate the cover back to the original position card and size
animateCoverBack(currentCard);
// animate in other cards
animateOtherCards(currentCard, false);
}
function animateOtherCards(card, out) {
var delay = 100;
for (var i = 0; i < nCards; i++) {
// animate cards on a stagger, 1 each 100ms
if (cards[i] === card) continue;
if (out) animateOutCard(cards[i], delay);
else animateInCard(cards[i], delay);
delay += 100;
}
}
// animations on individual cards (by adding/removing card names)
function animateOutCard(card, delay) {
setTimeout(function() {
card.className += ' out';
}, delay);
}
function animateInCard(card, delay) {
setTimeout(function() {
card.className = card.className.replace(' out', '');
}, delay);
}
// this function searches up the DOM tree until it reaches the card element that has been clicked
function getCardElement(el) {
if (el.className.indexOf('card ') > -1) return el;
else return getCardElement(el.parentElement);
}
// resize function - records the window width and height
function resize() {
if (pageIsOpen) {
// update position of cover
var cardPosition = currentCard.getBoundingClientRect();
setCoverPosition(cardPosition);
scaleCoverToFillWindow(cardPosition);
}
windowWidth = window.innerWidth;
windowHeight = window.innerHeight;
}
var paragraphText1 = '<p>Somebody once told me the world is gonna roll me. I ain\'t the sharpest tool in the shed. She was looking kind of dumb with her finger and her thumb in the shape of an "L" on her forehead. Well the years start coming and they don\'t stop coming. Fed to the rules and I hit the ground running. Didn\'t make sense not to live for fun. Your brain gets smart but your head gets dumb. So much to do, so much to see. So what\'s wrong with taking the back streets? You\'ll never know if you don\'t go. You\'ll never shine if you don\'t glow.</p><p>Hey now, you\'re an all-star, get your game on, go play. Hey now, you\'re a rock star, get the show on, get paid. And all that glitters is gold. Only shooting stars break the mold.</p><p>It\'s a cool place and they say it gets colder. You\'re bundled up now, wait till you get older. But the meteor men beg to differ. Judging by the hole in the satellite picture. The ice we skate is getting pretty thin. The water\'s getting warm so you might as well swim. My world\'s on fire, how about yours? That\'s the way I like it and I never get bored.</p>';
var paragraphText2 = '<h1>2</h1>';
var paragraphText3 ='<h1>3</h1>';
var paragraphText4 = '<h1>4</h1>';
/*
** Layout, Text & Colors
*/
body {
background: #150f21;
font-size: 18px;
}
p {
line-height: 1.5;
}
.container {
max-width: 800px;
margin: 0 auto;
}
/* Cards */
.card-column {
width: 50%;
float: left;
padding: 4%;
box-sizing: border-box;
}
.column-1 {
padding-top: 100px;
}
.card {
width: 92%;
max-width: 340px;
margin-left: auto;
margin-right: auto;
position: relative;
background: #EB5160;
color: #fff;
cursor: pointer;
margin-bottom: 60px;
}
.border {
position: absolute;
width: 100%;
height: 100%;
padding: 6px;
border: 1px solid #fff;
opacity: 0.5;
left: -6px;
top: -6px;
}
.card h1 {
position: relative;
padding: 190px 0px 100px 10px;
width: 90%;
}
.card > img {
width: 90%;
position: absolute;
top: -6%;
left: -6%;
}
.card-color-0 {
background-color: #EB5160;
}
.card-color-1 {
background-color: #8F3985;
}
.card-color-2 {
background-color: #8DAA91;
}
.card-color-3 {
background-color: #888DA7;
}
/* The cover (expanding background) */
.cover {
position: fixed;
background: #EB5160;
z-index: 100;
transform-origin: 50% 50%;
}
/* The open page content */
.open-content {
width: 100%;
z-index: 110;
position: absolute;
opacity: 0;
pointer-events: none;
}
.open-content img {
position: relative;
width: 90%;
margin-left: 3%;
margin-top: 20px;
z-index: 5;
}
.open-content .text {
background: #fff;
margin-top: -56%;
padding: 60% 5% 5% 5%;
width: 80%;
margin-left: 5%;
margin-bottom: 5%;
}
.open-content .text h1, .open-content .text p {
max-width: 700px;
margin-left: auto;
margin-right: auto;
}
.close-content {
display: block;
position: absolute;
right: 12px;
top: 12px;
width: 30px;
height: 30px;
}
.close-content span {
background: #222;
width: 30px;
height: 6px;
display: block;
position: absolute;
top: 14px;
}
.x-1 {
transform: rotate(45deg);
}
.x-2 {
transform: rotate(-45deg);
}
/*
** Transitions
*/
.card {
transition: opacity 200ms linear 320ms, transform 200ms ease-out 320ms;
}
.border {
transition: opacity 200ms linear, transform 200ms ease-out;
}
.card img {
transition: opacity 200ms linear 0ms, transform 200ms ease-in 0ms;
}
.card h1 {
transform: translate3d(20%, 0px, 0px);
transition: opacity 200ms linear 120ms, transform 200ms ease-in 120ms;
}
/* Clicked card */
.card.clicked img {
transform: translate3d(0px, -40px, 0px);
opacity: 0;
}
.card.clicked .border {
opacity: 0;
transform: scale(1.3);
}
.card.out, .card.out img {
transform: translate3d(0px, -40px, 0px);
opacity: 0;
}
.card.out h1, .card.clicked h1 {
transform: translate3d(20%, -40px, 0px);
opacity: 0;
}
.cover {
transition: transform 300ms ease-in-out;
}
.open-content {
transition: opacity 200ms linear 0ms;
}
.open-content.open {
opacity: 1;
pointer-events: all;
transition-delay: 1000ms;
}
/*
** Media Queries
*/
@media screen and (max-width: 600px) {
.card-column {
width: 90%;
}
.column-1 {
padding-top: 0px;
}
.open-content img {
margin-top: 40px;
}
}
<!--
Please note: this code is in no way ready to be used as is in production on your website. It will need to be adapted to be cross browser compliant & accessible. I just wanted to share how one might go about this effect with CSS & JS and no other dependencies
-->
<div class="container">
<div class="card-column column-0">
<div class="card card-color-0" data-id="1">
<div class="border"></div>
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/53148/deathtostock-00.jpg" />
<h1>Hey now, you're an allstar</h1>
</div>
<div class="card card-color-2" data-id="2">
<div class="border"></div>
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/53148/deathtostock-02.jpg" />
<h1>Hey now, you're a rock star</h1>
</div>
</div>
<div class="card-column column-1">
<div class="card card-color-1" data-id="3">
<div class="border"></div>
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/53148/deathtostock-01.jpg" />
<h1>Get your game on, go play</h1>
</div>
<div class="card card-color-3" data-id="4">
<div class="border"></div>
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/53148/deathtostock-03.jpg" />
<h1>Get the show on, get paid</h1>
</div>
</div>
</div>
<div id="cover" class="cover"></div>
<div id="open-content" class="open-content">
<a href="#" id="close-content" class="close-content"><span class="x-1"></span><span class="x-2"></span></a>
<img id="open-content-image" src="" />
<div class="text" id="open-content-text">
</div>
</div>