Forum Discussion

BillyTheroux's avatar
BillyTheroux
Community Member
14 days ago

JavaScript for Flipcards for STORYLINE!!!

One of the great features of rise is the flip card animations and how great they look. It's one thing that Storyline has never had... UNTIL NOW!!! 

If you place your front card directly in front of your back card and then copy their ID's into this javascript the animation works PERFECTLY!! 

https://360.articulate.com/review/content/23b1e255-6853-40d5-bc47-59f5630ce70a/review

 

 

 

// ------------------------------------

// STORYLINE FLIP CARDS

// ------------------------------------

 

// Add one front/back pair for each card.

const FLIP_CARDS = [

{

frontId: "CARD_1_FRONT_ID",

backId: "CARD_1_BACK_ID"

},

{

frontId: "CARD_2_FRONT_ID",

backId: "CARD_2_BACK_ID"

},

{

frontId: "CARD_3_FRONT_ID",

backId: "CARD_3_BACK_ID"

}

];

 

// ------------------------------------

// CUSTOMIZATION

// ------------------------------------

 

const FLIP_DURATION = 600;

const PERSPECTIVE = 1000;

 

// Horizontal flip:

const FLIP_AXIS = "Y";

 

// Use "X" instead for a vertical flip.

// const FLIP_AXIS = "X";

 

const prefersReducedMotion =

window.matchMedia &&

window.matchMedia("(prefers-reduced-motion: reduce)").matches;

 

const duration = prefersReducedMotion ? 0 : FLIP_DURATION;

 

// ------------------------------------

// CREATE EACH FLIP CARD

// ------------------------------------

 

FLIP_CARDS.forEach((cardInfo) => {

const front = object(cardInfo.frontId);

const back = object(cardInfo.backId);

 

let isFlipped = false;

let isAnimating = false;

 

const rotation = (degrees) =>

`perspective(${PERSPECTIVE}px) rotate${FLIP_AXIS}(${degrees}deg)`;

 

// Keep the two card faces aligned.

front.style.transformOrigin = "center center";

back.style.transformOrigin = "center center";

 

front.style.transformStyle = "preserve-3d";

back.style.transformStyle = "preserve-3d";

 

// Hide the reverse side of each group.

front.style.backfaceVisibility = "hidden";

back.style.backfaceVisibility = "hidden";

 

// Safari compatibility.

front.style.webkitBackfaceVisibility = "hidden";

back.style.webkitBackfaceVisibility = "hidden";

 

// Smooth flip animation.

front.style.transition =

`transform ${duration}ms cubic-bezier(0.4, 0, 0.2, 1), ` +

`filter ${duration}ms ease`;

 

back.style.transition =

`transform ${duration}ms cubic-bezier(0.4, 0, 0.2, 1), ` +

`filter ${duration}ms ease`;

 

// Starting positions.

front.style.transform = rotation(0);

back.style.transform = rotation(180);

 

front.style.filter =

"drop-shadow(0px 4px 6px rgba(0, 0, 0, 0.14))";

 

back.style.filter =

"drop-shadow(0px 4px 6px rgba(0, 0, 0, 0.14))";

 

// Only the visible face should receive clicks.

front.style.pointerEvents = "auto";

back.style.pointerEvents = "none";

 

function flipCard() {

if (isAnimating) {

return;

}

 

isAnimating = true;

isFlipped = !isFlipped;

 

if (isFlipped) {

// Front rotates away; back rotates into view.

front.style.transform = rotation(180);

back.style.transform = rotation(360);

 

front.style.filter =

"drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.08))";

 

back.style.filter =

"drop-shadow(0px 10px 14px rgba(0, 0, 0, 0.22))";

} else {

// Return to the front.

front.style.transform = rotation(0);

back.style.transform = rotation(180);

 

front.style.filter =

"drop-shadow(0px 10px 14px rgba(0, 0, 0, 0.22))";

 

back.style.filter =

"drop-shadow(0px 1px 2px rgba(0, 0, 0, 0.08))";

}

 

window.setTimeout(() => {

// Activate only the face currently showing.

front.style.pointerEvents = isFlipped ? "none" : "auto";

back.style.pointerEvents = isFlipped ? "auto" : "none";

 

isAnimating = false;

}, duration);

}

 

// Clicking either side flips the card.

front.click(flipCard);

back.click(flipCard);

});

3 Replies

  • wiliam56park's avatar
    wiliam56park
    Community Member

    This is a really clever solution! The flip card animation is one of those small details that makes Rise courses feel polished and interactive, so bringing that same effect into Storyline is a great enhancement. Using JavaScript to bridge that gap opens up a lot of creative possibilities for designers who want more engaging interactions without switching platforms. Great work sharing this — definitely a useful technique for anyone building modern e-learning experiences in Storyline!

  • BillyTheroux's avatar
    BillyTheroux
    Community Member

    Thank you! I've been playing around with Javascript for a bunch of new functionality thanks to ChatGPT and it's really made my modules look much more polished and adds to learner engagement!