0
(0)

I hope the title got your attention because this will be a mystical experience. Every card tells you a prophecy, every card has a special meaning and the way you get a new and random card showing up is by pushing a button.

So what are the steps?

  • We need an SVG sprite with all the cards (12 in this case)
  • a randomizer function has to be created between 1 and 12 but at each click of the button the total number of cards decreases with 1 (we need to avoid getting the same card)
  • When there is no more card left it should alert the user, that the card stack is empty and no more prophecy is available

Creating an SVG sprite

In my case instead of getting 12 individual SVGs and merging them together to get an SVG sprite, I actually got a big svg file with all the cards inside. Still it was not a sprite so I needed to convert it to one !

The original SVG file had each card wrapped ina g tag(grouping tag), but I needed to make some modifications:

I changed the g tags into symbol tags and put all symbols in a defs (definitions) tag:

Each symbol tag got an id (card1, card2…) and a viewbox attribute where I just simply defined the x, y, width and height properties. Each symbol had to be moved to 0 horizontal and vertical position since they were not starting from top-left. This means that in the case of each symbol the x and y property got the value from the first rect (rectangle) x and y attribute value.

Now we need to load the sprite in our HTML file:

But wait ! We don’t want to show the first card at the begining, we need a neutral card or some cover image:

So I duplicated the first symbol and assigned the value card0 on it’s id. I kept the frame(the rectangle elements and just changed the SVG text tag’s text to “Get your card”.

Now the use tag will load from cards.svg the symbol with the id card0.

The Javascript part is next. We need to create an array with numbers starting from 1 and ending in 12. I used the Array.from method because it creates a new array with modified values just like the map method does. Each number in the array got an increase by 1 in order to start the numbering from 1(not from 0).

let items =  Array.from(Array(12).keys(), n => n + 1);

After this we need to pick a random item from the items array and add it to the end of the href(instead of the 0). All this needed to happen when the user clicks the button:

const button = document.getElementById('ctaGetNextCard');
const randomCard = () => {
   const card = document.querySelector('#card use');
   const newNr = Math.floor(Math.random()*items.length);

   card.setAttribute('xlink:href', `cards.svg#card${newNr}`);
}
button.addEventListener('click', randomCard);

The problem is, based on the code above, the cards will be shuffled forever, getting the same card multiple times. But we don’t want that ! What we want is, each time a card is shown, it is also removed from the stack. When there is no card left in the stack we notify the user that game is over and “Get a life!”.

So after refactoring that part, the code started to look like this:

const randomNr = () =>  {
   const newNr = Math.floor(Math.random()*items.length);
   const randomCardIndex = items[newNr];
   items.splice(newNr, 1);
   return randomCardIndex
};
if(items.length > 1) {
   card.setAttribute('xlink:href', `cards.svg#card${randomNr()}`);
}  
else {
   card.setAttribute('xlink:href', `cards.svg#card${randomNr()}`);
   button.setAttribute('hidden', true);
   setTimeout(() => {
      alert('No more cards left');
   },1000)
}  

I store the new random item in a variable because the original one will be deleted from the array immediately after, so we would return a different element instead of the removed one. So first we store the random item in a constant, then we remove it from the array and finally we return the stored item(number) and load the card with that number.

If there is only 1 card left in the stack then we display that last card, hide the button and alert the user that there is no more card left after 1 second(for the sake of smoothness).

The entire javascript code is this:

const button = document.getElementById('ctaGetNextCard');
let items =  Array.from(Array(12).keys(), n => n + 1);
const randomCard = () => {
  const card = document.querySelector('#tarotCards use');
  
  const randomNr = () =>  {
    const newNr = Math.floor(Math.random()*items.length);
    const randomCardIndex = items[newNr];
    items.splice(newNr, 1);
    return randomCardIndex
  };
  if(items.length > 1) {
    card.setAttribute('xlink:href', `cards.svg#card${randomNr()}`);
  }  
  else {
    card.setAttribute('xlink:href', `cards.svg#card${randomNr()}`);
    button.setAttribute('hidden', true);
    setTimeout(() => {
      alert('No more cards left');
    },1000)
  }  
}
button.addEventListener('click', randomCard);

Svg image credits: Tarot Vectors by Vecteezy

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

Categorized in: